diff --git a/mozilla/security/jss/Makefile b/mozilla/security/jss/Makefile new file mode 100644 index 00000000000..41158781e1c --- /dev/null +++ b/mozilla/security/jss/Makefile @@ -0,0 +1,90 @@ +#! gmake +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. + +# don't even try to build for now +default: + +####################################################################### +# (1) Include initial platform-independent assignments (MANDATORY). # +####################################################################### + +include manifest.mn + +####################################################################### +# (2) Include "global" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/config.mk + +####################################################################### +# (3) Include "component" configuration information. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (4) Include "local" platform-dependent assignments (OPTIONAL). # +####################################################################### + + + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### + + +nss_release:: +ifdef BUILD_OPT + @echo "== nss_release.pl ==" + @perl -I$(CORE_DEPTH)/coreconf $(CORE_DEPTH)/ninja/nss_release.pl \ + "RELEASE_TREE=$(RELEASE_TREE)" \ + "RELEASE=$(RELEASE)" \ + "RELEASE_VERSION=$(RELEASE_VERSION)" \ + "PLATFORM=$(PLATFORM)" \ + "OS_ARCH=$(OS_ARCH)" +else + @echo "The \"nss_release.pl\" script may ONLY be used on OPTimized builds!!!" +endif + diff --git a/mozilla/security/jss/cmd/Makefile b/mozilla/security/jss/cmd/Makefile new file mode 100644 index 00000000000..8d818df89f2 --- /dev/null +++ b/mozilla/security/jss/cmd/Makefile @@ -0,0 +1,76 @@ +#! gmake +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +####################################################################### +# (1) Include initial platform-independent assignments (MANDATORY). # +####################################################################### + +include manifest.mn + +####################################################################### +# (2) Include "global" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/config.mk + +####################################################################### +# (3) Include "component" configuration information. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (4) Include "local" platform-dependent assignments (OPTIONAL). # +####################################################################### + + + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### + + + diff --git a/mozilla/security/jss/cmd/jssjava/GenNativesToRegister.pl b/mozilla/security/jss/cmd/jssjava/GenNativesToRegister.pl new file mode 100644 index 00000000000..56794b3a563 --- /dev/null +++ b/mozilla/security/jss/cmd/jssjava/GenNativesToRegister.pl @@ -0,0 +1,252 @@ +#!/usr/bin/perl +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +############################################################################ +# (I) Offer a standard "Usage:" statement and process command line options # +############################################################################ + + # (A) Print out the "Usage:" statement since there must always + # be at least TWO command line arguments to $0. + + if ( "$ARGV[1]" eq "" ) + { +USAGE: + print( STDERR "Usage: perl " ); + print( STDERR $0 ); + print( STDERR " " ); + print( STDERR " " ); + print( STDERR " [jni_header_2] . . ." ); + print( STDERR " [jni_header_n]\n" ); + exit( -1 ); + } + + # (B) Initialize array index + + $index = 0; + + # (C) Process all command line options + + while( $_ = $ARGV[0] ) + { + if( ( "$ARGV[0]" eq "help" ) || ( "$ARGV[0]" eq "?" ) ) + { + # (1) print Usage: message + goto USAGE; + } + elsif( "$ARGV[0]" =~ /^(.*).h$/ ) + { + # (2) retrieve name of generated file + $generated_header_filename = $ARGV[0]; + } + else + { + # (3) retrieve name of jni file + $jni_header_filename[$index] = "_jni/"; + $jni_header_filename[$index] .= $ARGV[0]; + $jni_header_filename[$index] =~ s/\./_/g; + $jni_header_filename[$index] .= ".h"; + + # (4) store class "path" of jni + $jni_class_path[$index] = $ARGV[0]; + $jni_class_path[$index] =~ s/\./\//g; + + # (5) compose native "name" of jni array entry + $jni_native_methods[$index] = "&"; + $jni_native_methods[$index] .= $ARGV[0]; + $jni_native_methods[$index] =~ s/\./_/g; + $jni_native_methods[$index] .= "_natives[0]"; + + $index++; + } + + shift; + } + +############################################################################ +# (II) Generate header file containing native method registration material # +############################################################################ + + # (A) If it exists, remove the old header file + # prior to regenerating a new header file + + if( -e $generated_header_filename ) + { + unlink $generated_header_filename; + } + + # (B) Create a new file that will contain all + # native method registration material + + open( FD, ">>$generated_header_filename" ); + + # (C) Compose header section of new file + + # (1) print the static portion + print( FD "/**-- DO NOT EDIT THIS FILE. IT IS MACHINE GENERATED --**/\n" ); + print( FD "#include \n\n" ); + + # (2) print the computed portion + for( $index = 0; $index < scalar( @jni_header_filename ); $index++ ) + { + print( FD "#include \"$jni_header_filename[$index]\"\n" ); + } + + print( FD "\n" ); + + # (D) Process all jni files + + for( $index = 0; $index < scalar( @jni_header_filename ); $index++ ) + { + # (1) initialize $class, $method, $signature, + # $jnimethod, and $jnimethod_count + $class = ""; + $method = ""; + $signature = ""; + $jnimethod = ""; + + $jnimethod_count[$index] = 0; + + # (2) open this jni file + open( JNIFD, $jni_header_filename[$index] ); + + # (3) process first value of "Class:" in this jni file + while( $line = ) + { + if( $line =~ /Class:/ ) + { + # (a) remove all trailing white space + $line =~ s/\s*$//; + + # (b) assign relevant portion of "Class:" string + $class = substr( $line, rindex( $line, " " ) + 1 ); + + # (c) print "Class:" string to file as an array name + print( FD "const JNINativeMethod ", $class, "_natives[] =\n" ); + print( FD "{\n" ); + + # (d) break + last; + } + } + + # (4) process each value of "Method:", "Signature:", + # and "JNIEXPORT" in this jni file + while( $line = ) + { + if( $line =~ /Method:/ ) + { + # (a) remove all trailing white space + $line =~ s/\s*$//; + + # (b) assign relevant portion of "Method:" string + $method = substr( $line, rindex( $line, " " ) + 1 ); + } + elsif( $line =~ /Signature:/ ) + { + # (c) remove all trailing white space + $line =~ s/\s*$//; + + # (d) assign relevant portion of "Signature:" string + $signature = substr( $line, rindex( $line, " " ) + 1 ); + } + elsif( $line =~ /JNIEXPORT/ ) + { + # (e) remove all trailing white space + $line =~ s/\s*$//; + + # (f) assign relevant portion of "JNIEXPORT" string + $jnimethod = substr( $line, rindex( $line, " " ) + 1 ); + } + + # (5) construct array entry from $method, + # $signature, and $jnimethod + if( ( $method ne "" ) && + ( $signature ne "" ) && + ( $jnimethod ne "" ) ) + { + # (a) print an array value + print( FD " {\"", $method, "\", " ); + print( FD "\"", $signature, "\", " ); + print( FD "(void *)", $jnimethod, "},\n" ); + + # (b) increment the total number of + # JNI methods for this file + $jnimethod_count[$index]++; + + # (c) reset $method, $signature, + # and $jnimethod to be empty + $method = ""; + $signature = ""; + $jnimethod = ""; + } + } + + # (5) terminate this native JNI methods array + print( FD " 0\n" ); + print( FD "};\n\n" ); + + # (6) close this jni file + close( JNIFD ); + + # (7) move to next jni file + shift; + } + + # (E) Compose footer section of new file + + # (1) print the static portion + print( FD "struct native_methods {\n" ); + print( FD " char *classname;\n" ); + print( FD " int nmethods;\n" ); + print( FD " const JNINativeMethod *nat_methods;\n" ); + print( FD "} nativeMethods[] =\n" ); + print( FD "{\n" ); + + # (2) print the computed portion + for( $index = 0; $index < scalar( @jni_header_filename ); $index++ ) + { + print( FD " {\"$jni_class_path[$index]\", " ); + print( FD "$jnimethod_count[$index], " ); + print( FD "$jni_native_methods[$index]},\n" ); + } + + # (3) terminate the footer + print( FD " 0\n" ); + print( FD "};\n\n" ); + + # (F) Close the new file that now contains all + # native method registration material + + close( FD ); + diff --git a/mozilla/security/jss/cmd/jssjava/Makefile b/mozilla/security/jss/cmd/jssjava/Makefile new file mode 100644 index 00000000000..c68bd604c77 --- /dev/null +++ b/mozilla/security/jss/cmd/jssjava/Makefile @@ -0,0 +1,103 @@ +#! gmake +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +all:: + gmake -f jnigen.mk + gmake -f csrcs.mk + +import:: + gmake -f jnigen.mk import + gmake -f csrcs.mk import + +clean:: + gmake -f jnigen.mk clean + gmake -f csrcs.mk clean + +export:: + gmake -f jnigen.mk export + gmake -f csrcs.mk export + +private_export:: + gmake -f jnigen.mk private_export + gmake -f csrcs.mk private_export + +libs:: + gmake -f jnigen.mk libs + gmake -f csrcs.mk libs + +program:: + gmake -f jnigen.mk program + gmake -f csrcs.mk program + +install:: + gmake -f jnigen.mk install + gmake -f csrcs.mk install + +release:: + gmake -f jnigen.mk release + gmake -f csrcs.mk release + +release_clean:: + gmake -f jnigen.mk release_clean + gmake -f csrcs.mk release_clean + +release_export:: + gmake -f jnigen.mk release_export + gmake -f csrcs.mk release_export + +release_classes:: + gmake -f jnigen.mk release_classes + gmake -f csrcs.mk release_classes + +ifneq ($(POLICY),) +release_policy:: + gmake -f jnigen.mk release_policy + gmake -f csrcs.mk release_policy +endif + +release_md:: + gmake -f jnigen.mk release_md + gmake -f csrcs.mk release_md + +release_jars:: + gmake -f jnigen.mk release_jars + gmake -f csrcs.mk release_jars + +release_cpdistdir:: + gmake -f jnigen.mk release_cpdistdir + gmake -f csrcs.mk release_cpdistdir + +tests:: + gmake -f jnigen.mk tests + gmake -f csrcs.mk tests diff --git a/mozilla/security/jss/cmd/jssjava/README b/mozilla/security/jss/cmd/jssjava/README new file mode 100644 index 00000000000..779f8c605e6 --- /dev/null +++ b/mozilla/security/jss/cmd/jssjava/README @@ -0,0 +1,387 @@ +The contents of this file are subject to the Mozilla Public +License Version 1.1 (the "License"); you may not use this file +except in compliance with the License. You may obtain a copy of +the License at http://www.mozilla.org/MPL/ + +Software distributed under the License is distributed on an "AS +IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +implied. See the License for the specific language governing +rights and limitations under the License. + +The Original Code is Netscape Security Services for Java. + +The Initial Developer of the Original Code is Netscape +Communications Corporation. Portions created by Netscape are +Copyright (C) 1998-2000 Netscape Communications Corporation. All +Rights Reserved. + +Contributor(s): + +Alternatively, the contents of this file may be used under the +terms of the GNU General Public License Version 2 or later (the +"GPL"), in which case the provisions of the GPL are applicable +instead of those above. If you wish to allow use of your +version of this file only under the terms of the GPL and not to +allow others to use your version of this file under the MPL, +indicate your decision by deleting the provisions above and +replace them with the notice and other provisions required by +the GPL. If you do not delete the provisions above, a recipient +may use your version of this file under either the MPL or the +GPL. +**************************************************************** + +Ninja 1.5 +Build 1998???? + +**************************************************************** +** +** Directory organization of this release +** +**************************************************************** + +The domestic version of this release is located under: +- /m/dist/ninja/domestic/JSS_1_5 + +The export version of this release is located under: +- /m/dist/ninja/export/JSS_1_5 + +Each version of the release consists of the following: +- a JAR file, xpclass.jar, that contains all of the public class files. + +- a JAR file, xpclass_g.jar, that contains all of the debuggable public class + files. + +- directories: where is of the form + [_][_]_.OBJ + For example, + IRIX6.2_DBG.OBJ (debug build) + SunOS5.5.1_OPT.OBJ (optimized build) + SunOS5.5.1_gcc_DBG.OBJ (built using the non-native compiler gcc) + OSF1V4.0_PTH_DBG.OBJ (PTH means the implementation uses pthreads.) + AIX4.1_PTH_USER_DBG.OBJ (PTH_USER means the implementation is + a combination of user-level threads and pthreads.) + + Under each directory is the file, mdbinary.jar. This is a + JAR file containing the compiled programs and libraries. + +************************************************************ +** +** Java Cross-platform code +** (Debug and Optimized, Domestic and Export) +** +************************************************************ + +All java code is built once per tree instance, and MUST be +built using the latest JDK available on all of the platforms. +At the current time, this is JDK 1.1.6. + +************************************************************ +** +** Platforms supported for Native JNI code +** (Debug and Optimized, Domestic and Export) +** +************************************************************ + +The following platforms are supported: +- Solaris on sparc: 2.5.1 (built with cc and JDK 1.1.6 libraries + running on native threads [Sun threads]) +- Solaris on sparc: 2.6 (symbolically linked to corresponding + Solaris 2.5.1 releases) +- WIN95: 4.0 (built with Visual C++ 5.0 and JDK 1.1.6 + libraries running on non-fiberous threads) +- WINNT: 4.0 (symbolically linked to corresponding + Windows 95 4.0 releases) +- HP-UX: B.11.00 (built with cc and JDK 1.1.5 libraries + running on native threads [pthreads]) + +************************************************************ +** +** Future platforms supported for Native JNI code +** (Debug and Optimized, Domestic and Export) +** +************************************************************ + +The following platforms will be supported in the near future: +- AIX: 4.3 (built with cc and JDK 1.1.6 libraries + running on native threads [pthreads]) +- IRIX: 6.2 (built with cc with "-n32" and JDK 1.1.5 + libraries running on native threads [pthreads]) +- OSF/1: 4.0D (built with cc and JDK 1.1.6 libraries + running on native threads [pthreads]) +- Linux: 2.1 (built with gcc and JDK 1.1.3 libraries + running on native threads [pthreads]) + +************************************************************ +** +** How to build Ninja yourself +** +************************************************************ + +To build this version of Ninja yourself, execute the following +instructions: + +On UNIX machines (assuming tcsh): + + For the FIRST INSTANCE of Ninja in your build tree: + + 1) IMPORTANT: If you have NOT built Ninja in your current tree, and + this is the FIRST platform that you are building it on, + then you MUST set the following environment variable + in order to build JAVA and JNI headers!!! Additionally, + this platform MUST utilize the latest "approved" version + of the JDK, since JAVA and JNI headers are only ever + built ONCE per instance of build tree!!! Note that at + the time of this writing, the only acceptible INITIAL + UNIX build platforms are Sun, AIX, and OSF/1. + + setenv NS_USE_JDK_TOOLSET 1 + + 2) You MAY need to set the following environment variables for this + platform: + + setenv CVSROOT /m/src + setenv USE_PTHREADS 1 + setenv USE_N32 1 + setenv JAVA_HOME [...] + + 3) You MAY need to unset the following environment variables for this + platform: + + unsetenv CVSREAD + unsetenv JAVAC + unsetenv JAVAH + unsetenv JMC + unsetenv USE_PTHREADS + unsetenv USE_N32 + + 4) Check out the following source code directories (FIRST TIME ONLY!) + + cvs co ns/coreconf + cvs co -r JSS_1_5 ns/ninja + cvs co ns/security/lib + cvs co -r JSS_1_5 ns/security/lib/manifest.mn + + 5) Setup ns/coreconf to reference the correct compiler paths for this + platform + + cd ns/coreconf + source ./.cshrc + + 6) Build "nsinstall" executable for this platform + + gmake + gmake BUILD_OPT=1 + + 7) Import Ninja support files for this platform + + cd ../ninja + gmake import + gmake BUILD_OPT=1 import + + 8) Change to the security directory + + cd ../security/lib + + 9) Build the security library + + gmake private_export + gmake + gmake BUILD_OPT=1 + + 10) Change back to the ninja directory + + cd ../../ninja + + 11) Create Ninja private exports (FIRST TIME ONLY!) + + gmake private_export + + 12) Begin building Ninja from a "fresh" tree (FIRST TIME ONLY!) + + gmake clean + gmake BUILD_OPT=1 clean + + 13) Build "standard debuggable" version for this UNIX + (e. g. - SunOS5.5.1_DBG.OBJ) + + gmake + + 14) Build "standard optimized" version for this UNIX + (e. g. - SunOS5.5.1_OPT.OBJ) + + gmake BUILD_OPT=1 + + 15) You MUST always ensure that the following environment variable + is UNSET for ALL of the remaining builds!!!: + + unsetenv NS_USE_JDK_TOOLSET + + 16) Build "_g debuggable" version for this UNIX + (e. g. - SunOS5.5.1_DBG.OBJ) + + gmake JDK_DEBUG=1 + + + For the FOLLOWING INSTANCES of Ninja in your build tree: + + 17) You MUST always ensure that the following environment variables + are UNSET for ALL of the remaining builds!!!: + + unsetenv NS_USE_JDK_TOOLSET + unsetenv USE_PTHREADS + unsetenv USE_N32 + + 18) You MAY need to set the following environment variables for this + platform: + + setenv CVSROOT /m/src + setenv USE_PTHREADS 1 (this MUST be set on IRIX ONLY!!!) + setenv USE_N32 1 (this MUST be set on IRIX ONLY!!!) + setenv JAVA_HOME [...] + + 19) You MAY need to unset the following environment variables for this + platform: + + unsetenv CVSREAD + unsetenv JAVAC + unsetenv JAVAH + unsetenv JMC + + 20) Setup ns/coreconf to reference the correct compiler paths for this + platform + + cd ns/coreconf + source ./.cshrc + + 21) Build "nsinstall" executable for this platform + + gmake + gmake BUILD_OPT=1 + + 22) Import Ninja support files for this platform + + cd ../ninja + gmake import + gmake BUILD_OPT=1 import + + 23) Change to the security directory + + cd ../security/lib + + 24) Build the security library + + gmake private_export + gmake + gmake BUILD_OPT=1 + + 25) Change back to the ninja directory + + cd ../../ninja + + 26) Build "standard debuggable" version for this UNIX + (e. g. - SunOS5.5.1_DBG.OBJ) + + gmake + + 27) Build "standard optimized" version for this UNIX + (e. g. - SunOS5.5.1_OPT.OBJ) + + gmake BUILD_OPT=1 + + 28) Build "_g debuggable" version for this UNIX + (e. g. - SunOS5.5.1_DBG.OBJ) + + gmake JDK_DEBUG=1 + + + +On Windows NT machines (assuming DOS shell): + + For the FIRST INSTANCE of Ninja in your build tree: + + 1) IMPORTANT: If you have NOT built Ninja in your current tree, and + this is the FIRST platform that you are building it on, + then you MUST set the following environment variable + in order to build JAVA and JNI headers!!! Additionally, + this platform MUST utilize the latest "approved" version + of the JDK, since JAVA and JNI headers are only ever + built ONCE per instance of build tree!!! + + set NS_USE_JDK_TOOLSET=1 + + 2) Set the following environment variables for this platform: + + set OS_TARGET=WIN95 + set CVSROOT=:pserver:@cvsserver:/m/src + set JAVA_HOME=[location of local JDK] (use UNIX forward slashes!) + + 3) You MAY need to unset the following environment variables for this + platform: + + unset CVSREAD + unset JAVAC + unset JAVAH + unset JMC + + 4) Check out the following source code directories (FIRST TIME ONLY!) + + cvs login + cvs co ns/coreconf + cvs co -r JSS_1_5 ns/ninja + cvs co ns/security/lib + cvs co -r JSS_1_5 ns/security/lib/manifest.mn + + 5) Import Ninja support files for this platform + + cd ..\ninja + gmake import + gmake BUILD_OPT=1 import + + 6) Change to the security directory + + cd ..\security\lib + + 7) Build the security library + + gmake private_export + gmake + gmake BUILD_OPT=1 + + 8) Change back to the ninja directory + + cd ..\..\ninja + + 9) Create Ninja private exports (FIRST TIME ONLY!) + + gmake private_export + + 10) HACK: Use the MKS toolkit shell (sh.exe) instead of shmsdos.exe!!! + + copy shmsdos.exe shmsdos.sav + copy [MKS home]\sh.exe shmsdos.exe + + 11) Begin building Ninja from a "fresh" tree (FIRST TIME ONLY!) + + gmake clean + gmake BUILD_OPT=1 clean + + 12) Build "standard debuggable" WIN954.0_DBG.OBJ version + + gmake + + 13) Build "standard optimized" WIN954.0_OPT.OBJ version + + gmake BUILD_OPT=1 + + 14) You MUST always ensure that the following environment variable + is UNSET for ALL of the remaining builds!!!: + + unset NS_USE_JDK_TOOLSET + + 15) Build "_g debuggable" WIN954.0_DBG.OBJ version + + gmake JDK_DEBUG=1 + + 16) IMPORTANT: Restore original shmsdos.exe!!! + + copy shmsdos.sav shmsdos.exe diff --git a/mozilla/security/jss/cmd/jssjava/README.NSS b/mozilla/security/jss/cmd/jssjava/README.NSS new file mode 100644 index 00000000000..261e748cd66 --- /dev/null +++ b/mozilla/security/jss/cmd/jssjava/README.NSS @@ -0,0 +1,67 @@ +The contents of this file are subject to the Mozilla Public +License Version 1.1 (the "License"); you may not use this file +except in compliance with the License. You may obtain a copy of +the License at http://www.mozilla.org/MPL/ + +Software distributed under the License is distributed on an "AS +IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +implied. See the License for the specific language governing +rights and limitations under the License. + +The Original Code is Netscape Security Services for Java. + +The Initial Developer of the Original Code is Netscape +Communications Corporation. Portions created by Netscape are +Copyright (C) 1998-2000 Netscape Communications Corporation. All +Rights Reserved. + +Contributor(s): + +Alternatively, the contents of this file may be used under the +terms of the GNU General Public License Version 2 or later (the +"GPL"), in which case the provisions of the GPL are applicable +instead of those above. If you wish to allow use of your +version of this file only under the terms of the GPL and not to +allow others to use your version of this file under the MPL, +indicate your decision by deleting the provisions above and +replace them with the notice and other provisions required by +the GPL. If you do not delete the provisions above, a recipient +may use your version of this file under either the MPL or the +GPL. + +********************************************************************** + +README.ninja contains instructions for building Ninja normally. +The following addenda tell how to build the version of Ninja that +is included with NSS 2.0. + +1. Checkout ns/ninja with the tag NSS2_0_RELEASE instead of JSS_1_3. + +2. Before building, do "setenv STANDALONE_LIBJSS 1". This will cause +libjss.so/jss.dll to have NSPR embedded in it. Normal Ninja builds do +not embed NSPR. + +3. To release to /m/dist, do NOT do "gmake release". First set the release +version to something suitable by doing something like +"setenv RELEASE_VERSION NSS_2_0". Then, in the top level directory of +ninja (ns/ninja), do "gmake nss_release". This will create one of the +following outputs in /m/dist/ninja/: + +UNIX +==== +unixjss.tar + - jss.zip + - contains JSS classes for SSL and initialization + - libjss.so + - native implementation library, consists of security, NSPR, DBM, + and the native JSS code. + +WINDOWS +======= +winjss.zip + - jss.zip + - same as in the UNIX version, contains JSS classes for SSL + and initialization + - jss.dll + - native implementation library, consists of security, NSPR, DBM, + and the native JSS code. diff --git a/mozilla/security/jss/cmd/jssjava/config.mk b/mozilla/security/jss/cmd/jssjava/config.mk new file mode 100644 index 00000000000..2c2b4825c43 --- /dev/null +++ b/mozilla/security/jss/cmd/jssjava/config.mk @@ -0,0 +1,109 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# +####################################################################### +# Adjust specific variables for specific platforms # +####################################################################### + +# We don't need static, import, or purify libraries +LIBRARY= +IMPORT_LIBRARY= +PURE_LIBRARY= + +# Get rid of embedded "32" in library names on Windows +ifeq ($(OS_ARCH),WINNT) +SHARED_LIBRARY := $(subst 32,,$(SHARED_LIBRARY)) +SHARED_LIBRARY_G := $(subst 32,,$(SHARED_LIBRARY_G)) +endif + +####################################################################### +# Adjust specific variables for all platforms # +####################################################################### + +OS_CFLAGS += -DNSPR20=1 + +ifeq ($(OS_ARCH),WINNT) +LDOPTS += -PDB:NONE +endif + +# Only used for "sanitizing" the release +STATIC_LIB_EXTENSION= +DYNAMIC_LIB_EXTENSION= +PURE_LIB_EXTENSION= + +# Include "funky" link path to pick up ALL native libraries for OSF/1. +ifeq ($(OS_ARCH), OSF1) + JAVA_LIBS += -L$(JAVA_HOME)/$(JAVA_LIBDIR).no +endif + +####################################################################### +# Set the LDFLAGS value to encompass all normal link options and all # +# special system linking options # +####################################################################### +ifneq ($(STANDALONE_LIBJSS),0) +LDFLAGS += $(LDOPTS) $(LIBJSSSSL) $(LIBJSSMANAGE) $(LIBSVRPLCY) $(LIBJSSPOLICY) $(LIBJSSPKCS11) $(LIBJSSMANAGE) $(LIBJSSCRYPTO) $(LIBJSSPKCS11) $(LIBJSSUTIL) $(LIBJSSMANAGE) $(LIBSSL) $(LIBPKCS7) $(LIBCERT) $(LIBKEY) $(LIBSECMOD) $(LIBJSSHCLHACKS) $(LIBCRYPTO) $(LIBSECUTIL) $(LIBSECMOD) $(LIBSSL) $(LIBPKCS12) $(LIBPKCS7) $(LIBCERT) $(LIBKEY) $(LIBCRYPTO) $(LIBSECUTIL) $(LIBHASH) $(LIBDBM) $(LIBPLDS) $(LIBPLC) $(LIBPR) $(JAVA_LIBS) $(DLLSYSTEM) +else +LDFLAGS += $(LDOPTS) $(LIBJSSSSL) $(LIBJSSMANAGE) $(LIBSVRPLCY) $(LIBJSSPOLICY) $(LIBJSSPKCS11) $(LIBJSSMANAGE) $(LIBJSSCRYPTO) $(LIBJSSPKCS11) $(LIBJSSUTIL) $(LIBJSSMANAGE) $(LIBSSL) $(LIBPKCS7) $(LIBCERT) $(LIBKEY) $(LIBSECMOD) $(LIBJSSHCLHACKS) $(LIBCRYPTO) $(LIBSECUTIL) $(LIBSECMOD) $(LIBSSL) $(LIBPKCS12) $(LIBPKCS7) $(LIBCERT) $(LIBKEY) $(LIBCRYPTO) $(LIBSECUTIL) $(LIBHASH) $(LIBDBM) $(DLLPLDS) $(DLLPLC) $(DLLPR) $(JAVA_LIBS) $(DLLSYSTEM) +endif + +####################################################################### +# Set the LD_LIBS value to encompass all static JSS, security, and # +# dbm libraries # +####################################################################### + +ifeq ($(OS_ARCH), OSF1) + LD_LIBS += $(LIBJSSSSL) $(LIBJSSMANAGE) $(LIBSVRPLCY) $(LIBJSSPOLICY) $(LIBJSSPKCS11) $(LIBJSSCRYPTO) $(LIBJSSUTIL) $(LIBJSSHCLHACKS) $(LIBSSL) $(LIBSECMOD) $(LIBPKCS12) $(LIBCERT) $(LIBPKCS7) $(LIBKEY) $(LIBCRYPTO) $(LIBHASH) $(LIBSECUTIL) $(LIBDBM) +else + LD_LIBS += $(LIBJSSSSL) $(LIBJSSMANAGE) $(LIBSVRPLCY) $(LIBJSSPOLICY) $(LIBJSSPKCS11) $(LIBJSSMANAGE) $(LIBJSSCRYPTO) $(LIBJSSUTIL) $(LIBJSSHCLHACKS) $(LIBJSSMANAGE) $(LIBSSL) $(LIBSECMOD) $(LIBPKCS12) $(LIBCERT) $(LIBPKCS7) $(LIBKEY) $(LIBCRYPTO) $(LIBHASH) $(LIBSECUTIL) $(LIBDBM) +endif + +####################################################################### +# Append additional LD_LIBS value to encompass all dynamic NSPR 2.0, # +# java, and system libraries # +####################################################################### +ifneq ($(STANDALONE_LIBJSS),0) +# NSPR is included in libjss +ifeq ($(OS_ARCH), WINNT) + LD_LIBS += $(LIBPLDS) $(LIBPLC) $(LIBPR) $(JAVA_LIBS) $(DLLSYSTEM) +else + LD_LIBS += -L$(SOURCE_LIB_DIR) $(LIBPLDS) $(LIBPLC) $(LIBPR) $(JAVA_LIBS) $(DLLSYSTEM) +endif + +else +# NSPR is not included in libjss +ifeq ($(OS_ARCH), WINNT) + LD_LIBS += $(DLLPLDS) $(DLLPLC) $(DLLPR) $(JAVA_LIBS) $(DLLSYSTEM) +else + LD_LIBS += -L$(SOURCE_LIB_DIR) -lplds3 -lplc3 -lnspr3 $(JAVA_LIBS) $(DLLSYSTEM) +endif + +endif diff --git a/mozilla/security/jss/cmd/jssjava/csrcs.mk b/mozilla/security/jss/cmd/jssjava/csrcs.mk new file mode 100644 index 00000000000..56b7d37f340 --- /dev/null +++ b/mozilla/security/jss/cmd/jssjava/csrcs.mk @@ -0,0 +1,96 @@ +#! gmake +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +####################################################################### +# (1) Include initial platform-independent assignments (MANDATORY). # +####################################################################### + +include manifest.mn + +PRIVATE_EXPORTS = registerNatives.h \ + $(NULL) + +REQUIRES = dbm \ + security \ + svrcore \ + $(NULL) + +CSRCS = registerNatives.c \ + jssjava.c \ + $(NULL) + +XP_FILES = README + +# NOTE: Beginning with JSS_2_1, we now ONLY create dynamic libraries . . . +# (e. g. - we no longer build the "jssjava" executable) + +LIBRARY_NAME = jss21 + +# PROGRAM = jssjava + +####################################################################### +# (2) Include "global" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/config.mk + +####################################################################### +# (3) Include "component" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/$(MODULE)/config/config.mk + +####################################################################### +# (4) Include "local" platform-dependent assignments (OPTIONAL). # +####################################################################### + +include config.mk + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/$(MODULE)/config/rules.mk + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### + +include rules.mk diff --git a/mozilla/security/jss/cmd/jssjava/jnigen.mk b/mozilla/security/jss/cmd/jssjava/jnigen.mk new file mode 100644 index 00000000000..f718bdf8e3f --- /dev/null +++ b/mozilla/security/jss/cmd/jssjava/jnigen.mk @@ -0,0 +1,126 @@ +#! gmake +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +####################################################################### +# (1) Include initial platform-independent assignments (MANDATORY). # +####################################################################### + +include manifest.mn + +JNI_GEN += com.netscape.jss.ssl.SSLInputStream \ + com.netscape.jss.ssl.SSLOutputStream \ + com.netscape.jss.ssl.SSLSocketImpl \ + com.netscape.jss.pkcs11.PrivateKeyProxy \ + com.netscape.jss.pkcs11.PublicKeyProxy \ + com.netscape.jss.CryptoManager \ + com.netscape.jss.NSSInit \ + com.netscape.jss.DatabaseCloser \ + com.netscape.jss.crypto.Algorithm \ + com.netscape.jss.crypto.EncryptionAlgorithm \ + com.netscape.jss.crypto.PQGParams \ + com.netscape.jss.pkcs11.PK11Token \ + com.netscape.jss.pkcs11.CertProxy \ + com.netscape.jss.pkcs11.CipherContextProxy \ + com.netscape.jss.pkcs11.ModuleProxy \ + com.netscape.jss.pkcs11.PK11RSAPublicKey \ + com.netscape.jss.pkcs11.PK11DSAPublicKey \ + com.netscape.jss.pkcs11.PK11KeyPairGenerator \ + com.netscape.jss.pkcs11.PK11KeyGenerator \ + com.netscape.jss.pkcs11.PK11Cert \ + com.netscape.jss.pkcs11.PK11Cipher \ + com.netscape.jss.pkcs11.PK11MessageDigest \ + com.netscape.jss.pkcs11.PK11Module \ + com.netscape.jss.pkcs11.PK11PrivKey \ + com.netscape.jss.pkcs11.PK11PubKey \ + com.netscape.jss.pkcs11.PK11SymKey \ + com.netscape.jss.pkcs11.SymKeyProxy \ + com.netscape.jss.pkcs11.SigContextProxy \ + com.netscape.jss.pkcs11.PK11Signature \ + com.netscape.jss.pkcs11.PK11Store \ + com.netscape.jss.pkcs11.PK11KeyWrapper \ + com.netscape.jss.util.Password \ + com.netscape.jss.util.Debug \ + com.netscape.jss.pkcs11.PK11SecureRandom \ + $(NULL) + +####################################################################### +# (2) Include "global" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/config.mk + +####################################################################### +# (3) Include "component" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/$(MODULE)/config/config.mk + +####################################################################### +# (4) Include "local" platform-dependent assignments (OPTIONAL). # +####################################################################### + +ALL_TRASH += nativeMethods.h + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/$(MODULE)/config/rules.mk + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### + +export:: + @if test ! -d nativeMethods.h; then \ + echo perl GenNativesToRegister.pl nativeMethods.h $(JNI_GEN) ; \ + perl GenNativesToRegister.pl nativeMethods.h $(JNI_GEN) ; \ + else \ + echo "Checking to see if nativeMethods.h file is out of date" ; \ + cmd="perl regen_nativeMethods.pl $(PERLARG) \ + -d $(JNI_GEN_DIR) nativeMethods.h $(JNI_GEN)"; \ + echo $$cmd; \ + list=`$$cmd`; \ + if test "$${list}x" != "x"; then \ + echo perl GenNativesToRegister.pl nativeMethods.h $(JNI_GEN) ; \ + perl GenNativesToRegister.pl nativeMethods.h $(JNI_GEN) ; \ + fi \ + fi + diff --git a/mozilla/security/jss/cmd/jssjava/jssjava.c b/mozilla/security/jss/cmd/jssjava/jssjava.c new file mode 100644 index 00000000000..43982043e3c --- /dev/null +++ b/mozilla/security/jss/cmd/jssjava/jssjava.c @@ -0,0 +1,489 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +/* + * Crypto VM - Java VM with statically linked crypto aka libsec routines. + * + * static routines are registered to VM using JNI API. + */ + +#include +#include "registerNatives.h" +#include "nspr.h" + +#include +#include +#include +#include + +PR_IMPLEMENT( SVRPLCYPolicyType ) +JSS_getExportControlPolicyType( void ); + +#if defined(_WINDOWS) +#define USAGE "Usage: %s [-version] [-debug] [-nojit] [-classpath classpath] [-ms] [-mx] [-D property] \n" +#else +#define USAGE "Usage: %s [-version] [-debug] [-classpath classpath] [-ms] [-mx] [-D property] \n" +#endif + +/* Unique "jssjava" version information */ +/* NOTE: Must be changed for ALL new releases!!! */ +#define JSSJAVA_MAJOR_VERSION "2" +#define JSSJAVA_MINOR_VERSION "1" +#define JDK_MAJOR_VERSION "1.2" +#define JDK_MINOR_VERSION "2" + +/* args & options */ +char * prog_name = 0; +char * classpath = 0; +char * javaclass = 0; +char ** javaArgs = 0; +int numJavaArgs = 0; +int debug = 0; +int jssjava_version = 0; + +/* set property to not load jdkcertsec10 from the beg */ +char ** userProps = 0; +int numUserProps = 0; +static int maxUserProps = 0; + + +static void errExit(int exitCode) +{ +#if defined(DEBUG) && defined(_WINDOWS) + _sleep(10); +#endif + exit(exitCode); +} + +static void addUserProp(char *keyval) +{ + char **newUserProps = 0; + char *val = 0; + + if (maxUserProps < numUserProps+2) { + newUserProps = (char **)calloc(numUserProps+4, sizeof(char *)); + maxUserProps = numUserProps+4; + memcpy(newUserProps, userProps, numUserProps*sizeof(char *)); + userProps = newUserProps; + } + if (val = (char *)strtok(keyval, (const char *)"=")) + *val++ = 0; + userProps[numUserProps++] = keyval; + userProps[numUserProps++] = val; +} + + +static void getArgs (int argc, char *argv[]) +{ + int i,j; + char* msptr; + char* mxptr; + +#ifdef DEBUG_nelsonb + for (i = 0; i < argc; ++i) + puts(argv[i]); +#endif + + prog_name = *argv++; argc--; + + for (i = 0; i < argc; i++) { + if (!strcmp(argv[i], "-version")) { + jssjava_version = 1; + } + else if (!strcmp(argv[i], "-debug")) { + debug = 1; + } + else if (!strcmp(argv[i], "-classpath")) { + if (++i == argc) + break; + classpath = argv[i]; + } + else if (!strcmp(argv[i], "-D")) { + if (++i == argc) + break; + addUserProp(argv[i]); + } +#if defined(_WINDOWS) + else if (!strcmp(argv[i], "-nojit")) { + addUserProp(argv[i]); + } +#endif + else if (!strncmp(argv[i], "-ms", 3)) { + msptr = (char*)malloc(strlen(argv[i]) + 5); + sprintf(msptr, "-X%s", argv[i] + 1); /* skip '-' */ + addUserProp(msptr); + } + else if (!strncmp(argv[i], "-mx", 3)) { + mxptr = (char*)malloc(strlen(argv[i]) + 5); + sprintf(mxptr, "-X%s", argv[i] + 1); /* skip '-' */ + addUserProp(mxptr); + } else if(!strcmp(argv[i], "-info")) { + /* -info is a dummy argument where information can be placed + * that will show up in a ps listing. Its argument is + * ignored. */ + if( i+1 < argc ) { + ++i; + } + } else { + javaclass = argv[i++]; + break; + } + } + if (jssjava_version == 1) { + SVRPLCYPolicyType policy; + char policyString[50]; + + /* First, initialize export control policy information. */ + if( SVRPLCY_InstallUtilityPolicy() != PR_SUCCESS ) { + errExit(-1); + } + + /* Second, establish which export control policy is being used. */ + policy = JSS_getExportControlPolicyType(); + + switch( policy ) { + case SVRPLCYNull: + strcpy( policyString, "null" ); + break; + case SVRPLCYDomestic: + strcpy( policyString, "domestic" ); + break; + case SVRPLCYExport: + strcpy( policyString, "export" ); + break; + case SVRPLCYFrance: + strcpy( policyString, "france" ); + break; + default: + strcpy( policyString, "none" ); + break; + } + + /* Third, print the export control policy & version information: */ + printf( "%s version \"%s.%s\" [%s]\n" + " (uses JDK \"%s.%s\")\n", + prog_name, JSSJAVA_MAJOR_VERSION, JSSJAVA_MINOR_VERSION, + policyString, JDK_MAJOR_VERSION, JDK_MINOR_VERSION ); + errExit(0); + } + if (javaclass == 0) { + printf(USAGE, prog_name); + errExit(1); + } + numJavaArgs = argc - i; + if (numJavaArgs > 0) + javaArgs = &argv[i]; + + for (j = strlen(javaclass)-1; j >= 0; j--) { + if (javaclass[j] == '.') + javaclass[j] = '/'; + } + +} + + +static int setUserProps(JNIEnv *env) +{ + jclass system_cls; + jobject system_props; + jmethodID getprop_mid; + jmethodID setprop_mid; + jclass prop_cls; + jmethodID put_mid; + jstring key, val; + jthrowable exc; + int i; + + /* get java.lang.System class and its get/setProperties methods */ + system_cls = (*env)->FindClass(env, "java/lang/System"); + if (system_cls == 0) { + fprintf(stderr, "Can't find java/lang/System.\n"); + return -1; + } + getprop_mid = (*env)->GetStaticMethodID(env, system_cls, "getProperties", + "()Ljava/util/Properties;"); + if (getprop_mid == 0) { + fprintf(stderr,"Can't find getProperties method in java.lang.System\n"); + return -1; + } + setprop_mid = (*env)->GetStaticMethodID(env, system_cls, "setProperties", + "(Ljava/util/Properties;)V"); + if (setprop_mid == 0) { + fprintf(stderr,"Can't find setProperties method in java.lang.System\n"); + return -1; + } + + /* get system properties, java.util.Properties class and its put method */ + system_props = (*env)->CallStaticObjectMethod(env, system_cls, getprop_mid); + exc = (*env)->ExceptionOccurred(env); + if (exc) { + (*env)->ExceptionDescribe(env); + return -1; + } + prop_cls = (*env)->GetObjectClass(env, system_props); + put_mid = (*env)->GetMethodID(env, prop_cls, "put", + "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); + if (put_mid == 0) { + fprintf(stderr, "Can't find put method in java.util.Properties\n"); + return -1; + } + + /* add default prop to not load JSS library */ + key = (*env)->NewStringUTF(env, "jss.load"); + if (key == 0) { + fprintf(stderr, "Out of memory\n"); + return -1; + } + val = (*env)->NewStringUTF(env, "no"); + if (val == 0) { + fprintf(stderr, "Out of memory\n"); + return -1; + } + (void)(*env)->CallObjectMethod(env, system_props, put_mid, + (jobject)key, (jobject)val); + exc = (*env)->ExceptionOccurred(env); + if (exc) { + (*env)->ExceptionDescribe(env); + return -1; + } + + /* add user properties */ + i = 0; + while (i < numUserProps) { + key = (*env)->NewStringUTF(env, userProps[i++]); + if (key == 0) { + fprintf(stderr, "Out of memory\n"); + errExit(1); + } + val = (*env)->NewStringUTF(env, userProps[i++]); + if (val == 0) { + fprintf(stderr, "Out of memory\n"); + errExit(1); + } + (void)(*env)->CallObjectMethod(env, system_props, put_mid, + (jobject)key, (jobject)val); + exc = (*env)->ExceptionOccurred(env); + if (exc) { + (*env)->ExceptionDescribe(env); + return -1; + } + } + + /* set new set of system properties */ + (*env)->CallStaticVoidMethod(env, system_cls, setprop_mid, system_props); + exc = (*env)->ExceptionOccurred(env); + if (exc) { + (*env)->ExceptionDescribe(env); + errExit(1); + } + + return 0; +} + + +static jobjectArray setJavaArgs(JNIEnv *env) +{ + jclass jstr_cls; + jstring jstr; + jobjectArray java_args; + int i; + + jstr_cls = (*env)->FindClass(env, "java/lang/String"); + if (numJavaArgs != 0) { + jstr = (*env)->NewStringUTF(env, javaArgs[0]); + if (jstr == 0) { + fprintf(stderr, "Out of memory\n"); + return 0; + } + java_args = (*env)->NewObjectArray(env, numJavaArgs, jstr_cls, jstr); + if (java_args == 0) { + fprintf(stderr, "Out of memory\n"); + return 0; + } + for (i=1; i < numJavaArgs; i++) { + jstr = (*env)->NewStringUTF(env, javaArgs[i]); + if (jstr == 0) { + fprintf(stderr, "Out of memory\n"); + return 0; + } + (*env)->SetObjectArrayElement(env, java_args, i, jstr); + } + } + else { + java_args = (*env)->NewObjectArray(env, 0, jstr_cls, 0); + if (java_args == 0) { + fprintf(stderr, "Out of memory\n"); + return 0; + } + } + return java_args; +} + + +int main (int argc, char *argv[]) +{ + JDK1_1InitArgs vm_args; + JNIEnv * env; + JavaVM * jvm; + jclass cls; + jmethodID mid; + jobjectArray java_args; + jthrowable exc; + jint res; + + /* get options, check usage */ + getArgs(argc, argv); + + /* initialize VM args */ + /* IMPORTANT: specify vm_args version # for JDK1.1.2 and beyond */ + vm_args.version = 0x00010001; + JNI_GetDefaultJavaVMInitArgs(&vm_args); + + /* set VM args from options */ + if (classpath || (classpath = getenv("CLASSPATH"))) + vm_args.classpath = classpath; + if (debug) + vm_args.debugging = JNI_TRUE; + + /* create Java VM */ + res = JNI_CreateJavaVM(&jvm, &env, &vm_args); + if (res < 0) { + fprintf(stderr, "Can't create Java VM\n"); + errExit(1); + } + + /* set additional system properties */ + if (setUserProps(env) < 0) { + fprintf(stderr, "Error setting system properties.\n"); + errExit(1); + } + + /* register all statically linked native methods. */ + if (registerNatives(env) < 0) { + fprintf(stderr,"Error registering statically linked native methods\n"); + errExit(1); + } + + /* set up java args */ + java_args = setJavaArgs(env); + if (java_args == 0) { + fprintf(stderr, "Error setting up arguments to Java class"); + errExit(1); + } + + PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 0); + + /* find the java class & main method to invoke */ + cls = (*env)->FindClass(env, javaclass); + if (cls == 0) { + fprintf(stderr, "Can't find %s class\n", javaclass); + errExit(1); + } + mid = (*env)->GetStaticMethodID(env,cls,"main","([Ljava/lang/String;)V"); + if (mid == 0) { + fprintf(stderr, "Can't find %s.main\n", javaclass); + errExit(1); + } + + /* call java main */ + (*env)->CallStaticVoidMethod(env, cls, mid, java_args); + exc = (*env)->ExceptionOccurred(env); + if (exc) { + (*env)->ExceptionDescribe(env); + } + +#ifdef DEBUG + /* Garbage collect to run finalizers before exiting. Also, try to + * verify the NativeProxy class, but keep in mind that it might not + * be loaded at all. */ + { + jclass systemClass; + jclass nativeProxyClass; + jmethodID gc; + jmethodID finalize; + jmethodID assertRegistryEmpty; + + /* + * garbage collect + */ + systemClass = (*env)->FindClass(env, "java/lang/System"); + PR_ASSERT(systemClass != NULL); + + /* This is hanging on Solaris for some reason :( */ +#if 0 + gc = (*env)->GetStaticMethodID(env, systemClass, "gc", "()V"); + PR_ASSERT( gc != NULL); + + (*env)->CallStaticVoidMethod(env, systemClass, gc); + PR_ASSERT( (*env)->ExceptionOccurred(env) == NULL ); +#endif + + finalize = (*env)->GetStaticMethodID(env, systemClass, "runFinalization", + "()V"); + PR_ASSERT( finalize != NULL ); + + (*env)->CallStaticVoidMethod(env, systemClass, finalize); + PR_ASSERT( (*env)->ExceptionOccurred(env) == NULL ); + + /* + * Make sure the registry is empty + */ + nativeProxyClass = (*env)->FindClass(env, + "com/netscape/jss/util/NativeProxy"); + /* If it's NULL, don't worry, maybe they just aren't using the class */ + (*env)->ExceptionClear(env); + + if(nativeProxyClass != NULL) { + /* OK, the class is loaded, so we should validate it */ + assertRegistryEmpty = (*env)->GetStaticMethodID(env, nativeProxyClass, + "assertRegistryEmpty", "()V"); + PR_ASSERT(assertRegistryEmpty != NULL); + (*env)->CallStaticVoidMethod(env, nativeProxyClass, + assertRegistryEmpty); + if( (*env)->ExceptionOccurred(env) != NULL ) { + (*env)->ExceptionDescribe(env); + } + } + + } +#endif + + (*jvm)->DestroyJavaVM(jvm); + + +#if defined(DEBUG) && defined(WIN32) + _sleep(10 * 1000); // milliseconds +#endif + return 0; +} + diff --git a/mozilla/security/jss/cmd/jssjava/manifest.mn b/mozilla/security/jss/cmd/jssjava/manifest.mn new file mode 100644 index 00000000000..d96a3c3940f --- /dev/null +++ b/mozilla/security/jss/cmd/jssjava/manifest.mn @@ -0,0 +1,39 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +CORE_DEPTH = ../../.. + +MODULE = ninja + +NS_USE_JDK = 1 + diff --git a/mozilla/security/jss/cmd/jssjava/regen_nativeMethods.pl b/mozilla/security/jss/cmd/jssjava/regen_nativeMethods.pl new file mode 100644 index 00000000000..8bfc00e651f --- /dev/null +++ b/mozilla/security/jss/cmd/jssjava/regen_nativeMethods.pl @@ -0,0 +1,89 @@ +#!/usr/local/bin/perl +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +# Input: -d dir generated_file foo1 foo2 . . . +# Compares generated file with "_jni/foo1.h", and +# generated file with "_jni/foo2.h", etc. +# +# (NOTE: unlike its closely related cousin, outofdate.pl, +# the "-d dir" must always be specified; also, unlike +# its closely related cousin, jniregen.pl, if the generated file +# is older than ANY "_jni/foo?.h", then the generated file will +# be regenerated in its entirety, rather than just the portions +# associated with the list of files returned by this script) +# +# Returns: list of headers which are NEWER than corresponding class +# files (non-existant header files are considered to be real old :-) + +$found = 1; + +if ($ARGV[0] eq '-d') +{ + $headerdir = $ARGV[1]; + $headerdir .= "/"; + shift; + shift; +} +else +{ + print STDERR "Usage: perl ", $0, " -d dir generated_file foo1 foo2 . . .\n"; + exit -1; +} + +$generatedfilename = $ARGV[0]; +shift; + +foreach $filename (@ARGV) +{ + $headerfilename = $headerdir; + $headerfilename .= $filename; + $headerfilename =~ s/\./_/g; + $headerfilename .= ".h"; + + ( $dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, $atime, $generatedmtime, + $ctime, $blksize, $blocks ) = stat( $generatedfilename ); + + ( $dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, $atime, $headermtime, + $ctime, $blksize, $blocks ) = stat( $headerfilename ); + + if( $headermtime > $generatedmtime ) + { + print $filename, " "; + $found = 0; + } +} + +print "\n"; +exit 0; + diff --git a/mozilla/security/jss/cmd/jssjava/registerNatives.c b/mozilla/security/jss/cmd/jssjava/registerNatives.c new file mode 100644 index 00000000000..2457e06b2d6 --- /dev/null +++ b/mozilla/security/jss/cmd/jssjava/registerNatives.c @@ -0,0 +1,86 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + + /* + * registerNatives.c - + * registers statically linked native methods with the VM. + */ + +#include +#include +#include + +#include "registerNatives.h" +#include "nativeMethods.h" + +int +registerNatives(JNIEnv *env) +{ + jclass c; + jint res; + jthrowable exc; + int j; + + if( (*env)->ExceptionOccurred(env) != NULL ) { + fprintf(stderr, + "ERROR: exception occurred before registering natives\n"); + exit(-1); + } + + for (j = 0; nativeMethods[j].classname != 0; j++) { + c = (*env)->FindClass(env, nativeMethods[j].classname); + if (c == 0) { + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + fprintf(stderr, "Can't find %s class\n", + nativeMethods[j].classname); + continue; + } + res = (*env)->RegisterNatives(env, c, + nativeMethods[j].nat_methods, + nativeMethods[j].nmethods); + exc = (*env)->ExceptionOccurred(env); + if (exc) { + (*env)->ExceptionDescribe(env); + return -1; + } + if (res < 0) { + fprintf(stderr, "Error in register statically linked native methods" + "for %s\n", nativeMethods[j].classname); + return -1; + } + } + + return 0; +} + diff --git a/mozilla/security/jss/cmd/jssjava/registerNatives.h b/mozilla/security/jss/cmd/jssjava/registerNatives.h new file mode 100644 index 00000000000..6eadcfcc503 --- /dev/null +++ b/mozilla/security/jss/cmd/jssjava/registerNatives.h @@ -0,0 +1,38 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + + /* + * registerNatives.h + */ + +int registerNatives(JNIEnv *env); diff --git a/mozilla/security/jss/cmd/jssjava/rules.mk b/mozilla/security/jss/cmd/jssjava/rules.mk new file mode 100644 index 00000000000..30b4ac76e21 --- /dev/null +++ b/mozilla/security/jss/cmd/jssjava/rules.mk @@ -0,0 +1,67 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +release_md:: release_sanitize + +release_sanitize:: + -rm $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)/$(LIB_PREFIX)jsscrypto$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX) + -rm $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)/$(LIB_PREFIX)jsshclhacks$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX) + -rm $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)/$(LIB_PREFIX)jssmanage$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX) + -rm $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)/$(LIB_PREFIX)jsspkcs11$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX) + -rm $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)/$(LIB_PREFIX)jsspolicy$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX) + -rm $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)/$(LIB_PREFIX)jssssl$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX) + -rm $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)/$(LIB_PREFIX)jssutil$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX) + -rm $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)/$(DLL_PREFIX)jsscrypto$(DYNAMIC_LIB_EXTENSION)$(DYNAMIC_LIB_SUFFIX) + -rm $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)/$(DLL_PREFIX)jsshclhacks$(DYNAMIC_LIB_EXTENSION)$(DYNAMIC_LIB_SUFFIX) + -rm $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)/$(DLL_PREFIX)jssmanage$(DYNAMIC_LIB_EXTENSION)$(DYNAMIC_LIB_SUFFIX) + -rm $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)/$(DLL_PREFIX)jsspkcs11$(DYNAMIC_LIB_EXTENSION)$(DYNAMIC_LIB_SUFFIX) + -rm $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)/$(DLL_PREFIX)jsspolicy$(DYNAMIC_LIB_EXTENSION)$(DYNAMIC_LIB_SUFFIX) + -rm $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)/$(DLL_PREFIX)jssssl$(DYNAMIC_LIB_EXTENSION)$(DYNAMIC_LIB_SUFFIX) + -rm $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)/$(DLL_PREFIX)jssutil$(DYNAMIC_LIB_EXTENSION)$(DYNAMIC_LIB_SUFFIX) +ifeq ($(OS_ARCH),WINNT) + -rm $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)/$(IMPORT_LIB_PREFIX)jsscrypto$(IMPORT_LIB_EXTENSION)$(IMPORT_LIB_SUFFIX) + -rm $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)/$(IMPORT_LIB_PREFIX)jsshclhacks$(IMPORT_LIB_EXTENSION)$(IMPORT_LIB_SUFFIX) + -rm $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)/$(IMPORT_LIB_PREFIX)jssmanage$(IMPORT_LIB_EXTENSION)$(IMPORT_LIB_SUFFIX) + -rm $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)/$(IMPORT_LIB_PREFIX)jsspkcs11$(IMPORT_LIB_EXTENSION)$(IMPORT_LIB_SUFFIX) + -rm $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)/$(IMPORT_LIB_PREFIX)jsspolicy$(IMPORT_LIB_EXTENSION)$(IMPORT_LIB_SUFFIX) + -rm $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)/$(IMPORT_LIB_PREFIX)jssssl$(IMPORT_LIB_EXTENSION)$(IMPORT_LIB_SUFFIX) + -rm $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)/$(IMPORT_LIB_PREFIX)jssutil$(IMPORT_LIB_EXTENSION)$(IMPORT_LIB_SUFFIX) +else + -rm $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)/$(PURE_LIB_PREFIX)jsscrypto$(PURE_LIB_EXTENSION)$(PURE_LIB_SUFFIX) + -rm $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)/$(PURE_LIB_PREFIX)jsshclhacks$(PURE_LIB_EXTENSION)$(PURE_LIB_SUFFIX) + -rm $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)/$(PURE_LIB_PREFIX)jssmanage$(PURE_LIB_EXTENSION)$(PURE_LIB_SUFFIX) + -rm $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)/$(PURE_LIB_PREFIX)jsspkcs11$(PURE_LIB_EXTENSION)$(PURE_LIB_SUFFIX) + -rm $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)/$(PURE_LIB_PREFIX)jsspolicy$(PURE_LIB_EXTENSION)$(PURE_LIB_SUFFIX) + -rm $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)/$(PURE_LIB_PREFIX)jssssl$(PURE_LIB_EXTENSION)$(PURE_LIB_SUFFIX) + -rm $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)/$(PURE_LIB_PREFIX)jssutil$(PURE_LIB_EXTENSION)$(PURE_LIB_SUFFIX) +endif diff --git a/mozilla/security/jss/cmd/manifest.mn b/mozilla/security/jss/cmd/manifest.mn new file mode 100644 index 00000000000..0ccd710ecff --- /dev/null +++ b/mozilla/security/jss/cmd/manifest.mn @@ -0,0 +1,39 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +CORE_DEPTH = ../.. + +MODULE = ninja + +DIRS = jssjava \ + $(NULL) diff --git a/mozilla/security/jss/config/config.mk b/mozilla/security/jss/config/config.mk new file mode 100644 index 00000000000..21f8c47a6a8 --- /dev/null +++ b/mozilla/security/jss/config/config.mk @@ -0,0 +1,103 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +# +# Configuration information unique to the "sectools" component +# + +####################################################################### +# [1.0] Local "sectools" component library names # +####################################################################### + +include $(CORE_DEPTH)/$(MODULE)/config/libnames.mk + +####################################################################### +# [2.0] Local "sectools" component library link options # +####################################################################### + +include $(CORE_DEPTH)/$(MODULE)/config/linkage.mk + +####################################################################### +# [3.0] Local "sectools" component STATIC system library names # +####################################################################### + +include $(CORE_DEPTH)/$(MODULE)/config/static.mk + +####################################################################### +# [4.0] Local "sectools" component DYNAMIC system library names # +####################################################################### + +include $(CORE_DEPTH)/$(MODULE)/config/dynamic.mk + +# Stricter semantic checking for SunOS compiler. This catches calling +# undeclared functions, a major headache during debugging. +ifeq ($(OS_ARCH), SunOS) + OS_CFLAGS += -v +endif + +# Unfortunately, since the DBM and SECURITY libraries were compiled with +# the "-taso" switch (in ns/coreconf/OSF1.mk), we must ALSO compile the +# JSS dynamic libraries with the "-taso" switch (unless USE_64 is specified) +ifeq ($(OS_ARCH), OSF1) + ifneq ($(USE_64), 1) + LD_LIBS += -taso + endif +endif + +# Add symbolic binding values to MKSHLIB and LINK_DLL to +# encompass special link options for dynamic libraries + +ifeq ($(OS_ARCH), AIX) +MKSHLIB += -bsymbolic +endif +ifeq ($(OS_ARCH), HP-UX) +MKSHLIB += -B symbolic +endif +ifeq ($(OS_ARCH), IRIX) +MKSHLIB += -B symbolic +endif +ifeq ($(OS_ARCH), Linux) +MKSHLIB += -Bsymbolic +endif +ifeq ($(OS_ARCH), OSF1) +MKSHLIB += -B symbolic +endif +ifeq ($(OS_ARCH), SunOS) +MKSHLIB += -B symbolic +endif +ifeq ($(OS_ARCH), WINNT) +LINK_DLL += -LIBPATH:$(SOURCE_LIB_DIR) +LINK_DLL += -LIBPATH:$(JAVA_HOME)/$(JAVA_LIBDIR) +LINK_DLL += $(foreach file,$(LD_LIBS),-DEFAULTLIB:"$(notdir $(file))") +endif + diff --git a/mozilla/security/jss/config/dynamic.mk b/mozilla/security/jss/config/dynamic.mk new file mode 100644 index 00000000000..0631d096fc4 --- /dev/null +++ b/mozilla/security/jss/config/dynamic.mk @@ -0,0 +1,146 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +####################################################################### +# Initialize DYNAMIC system library names on some platforms # +####################################################################### + +# +# AIX platforms +# + + +ifeq ($(OS_ARCH),AIX) +ifeq ($(OS_RELEASE),4.1) + DLLSYSTEM += -lsvld -lC_r -lC -lpthreads -lc_r -lm /usr/lib/libc.a +else + DLLSYSTEM += -ldl -lC_r -lC -lpthreads -lc_r -lm /usr/lib/libc.a +endif +endif + +# +# HP/UX platforms +# + +ifeq ($(OS_ARCH),HP-UX) + ifeq ($(USE_PTHREADS), 1) + DLLSYSTEM += -lpthread + endif + ifeq ($(PTHREADS_USER), 1) + DLLSYSTEM += -lpthread + endif + ifeq ($(OS_RELEASE),A.09.03) + DLLSYSTEM += -ldld -L/lib/pa1.1 -lm + else + DLLSYSTEM += -ldld -lm -lc + endif +endif + +# +# IRIX platforms +# + +ifeq ($(OS_ARCH), IRIX) + ifeq ($(USE_PTHREADS), 1) + DLLSYSTEM += -lpthread + endif +endif + +# +# Linux platforms +# + +ifeq ($(OS_ARCH), Linux) + DLLSYSTEM += -ldl -lpthread -lm +endif + +# +# NCR platforms +# + +ifeq ($(OS_ARCH), NCR) + DLLSYSTEM += -lsocket -ldl -lnsl -lc +endif + +# +# OSF 1 platforms +# + +ifeq ($(OS_ARCH),OSF1) + ifneq ($(OS_RELEASE),V2.0) + DLLSYSTEM += -lc_r + endif + ifeq ($(USE_PTHREADS), 1) + DLLSYSTEM += -lpthread -lrt + endif + ifeq ($(USE_IPV6), 1) + DLLSYSTEM += -lip6 + endif +endif + +# +# SCO platforms +# + +ifeq ($(OS_ARCH), SCO_SV) + DLLSYSTEM += -lsocket -ldl -lnsl -lc +endif + +# +# Solaris platforms +# + +ifeq ($(OS_ARCH), SunOS) + ifneq ($(OS_RELEASE), 4.1.3_U1) + DLLSYSTEM += -lthread -lposix4 -lsocket -lnsl -lintl -ldl + endif +endif + +# +# UNIXWARE platforms +# + +ifeq ($(OS_ARCH), UNIXWARE) + DLLSYSTEM += -lsocket +endif + +# +# Windows platforms +# + +ifeq ($(OS_ARCH),WINNT) + ifneq ($(OS_TARGET),WIN16) + DLLSYSTEM += wsock32.lib winmm.lib + endif +endif + diff --git a/mozilla/security/jss/config/libnames.mk b/mozilla/security/jss/config/libnames.mk new file mode 100644 index 00000000000..761e3e5a751 --- /dev/null +++ b/mozilla/security/jss/config/libnames.mk @@ -0,0 +1,300 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +####################################################################### +# Initialize variables containing STATIC component library names # +####################################################################### + +# +# legacy library +# + +LIBJDKCERTSEC10 = $(SOURCE_LIB_DIR)/$(LIB_PREFIX)jdkcertsec10$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX_FOR_LINKING) + +# +# jss hclhacks library +# + +LIBJSSHCLHACKS = $(SOURCE_LIB_DIR)/$(LIB_PREFIX)jsshclhacks$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX_FOR_LINKING) + +# +# jss library +# + +LIBJSS = $(SOURCE_LIB_DIR)/$(LIB_PREFIX)jss$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX_FOR_LINKING) + +# +# jss ssl jni library +# + +LIBJSSSSL = $(SOURCE_LIB_DIR)/$(LIB_PREFIX)jssssl$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX_FOR_LINKING) + +# +# jss util jni library +# + +LIBJSSUTIL = $(SOURCE_LIB_DIR)/$(LIB_PREFIX)jssutil$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX_FOR_LINKING) + +# +# jss pkcs #11 jni library +# + +LIBJSSPKCS11= $(SOURCE_LIB_DIR)/$(LIB_PREFIX)jsspkcs11$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX_FOR_LINKING) + +# +# jss pkcs #12 jni library +# + +LIBJSSPKCS12= $(SOURCE_LIB_DIR)/$(LIB_PREFIX)jsspkcs12$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX_FOR_LINKING) + +# +# jss crypto jni library +# + +LIBJSSCRYPTO= $(SOURCE_LIB_DIR)/$(LIB_PREFIX)jsscrypto$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX_FOR_LINKING) + +# +# jss manage jni library +# + +LIBJSSMANAGE = $(SOURCE_LIB_DIR)/$(LIB_PREFIX)jssmanage$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX_FOR_LINKING) + +# +# jss policy library +# + +LIBJSSPOLICY = $(SOURCE_LIB_DIR)/$(LIB_PREFIX)jsspolicy$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX_FOR_LINKING) + +# +# sectools library +# + +LIBSECTOOLS = $(SOURCE_LIB_DIR)/$(LIB_PREFIX)sectools$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX_FOR_LINKING) + +# +# sechlp library +# + +LIBSECHLP = $(SOURCE_LIB_DIR)/$(LIB_PREFIX)sechlp$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX_FOR_LINKING) + +# +# security libraries +# + +LIBSSL = $(SOURCE_LIB_DIR)/$(LIB_PREFIX)ssl$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX_FOR_LINKING) +LIBNSS = $(SOURCE_LIB_DIR)/$(LIB_PREFIX)nss$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX_FOR_LINKING) +LIBPKCS7 = $(SOURCE_LIB_DIR)/$(LIB_PREFIX)pkcs7$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX_FOR_LINKING) +LIBPKCS12 = $(SOURCE_LIB_DIR)/$(LIB_PREFIX)pkcs12$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX_FOR_LINKING) +LIBCERT = $(SOURCE_LIB_DIR)/$(LIB_PREFIX)cert$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX_FOR_LINKING) +LIBKEY = $(SOURCE_LIB_DIR)/$(LIB_PREFIX)key$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX_FOR_LINKING) +LIBSECMOD = $(SOURCE_LIB_DIR)/$(LIB_PREFIX)secmod$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX_FOR_LINKING) +LIBCRYPTO = $(SOURCE_LIB_DIR)/$(LIB_PREFIX)crypto$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX_FOR_LINKING) +LIBSECUTIL = $(SOURCE_LIB_DIR)/$(LIB_PREFIX)secutil$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX_FOR_LINKING) +LIBJAR = $(SOURCE_LIB_DIR)/$(LIB_PREFIX)jar$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX_FOR_LINKING) +LIBZLIB = $(SOURCE_LIB_DIR)/$(LIB_PREFIX)zlib$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX_FOR_LINKING) +LIBHASH = $(SOURCE_LIB_DIR)/$(LIB_PREFIX)hash$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX_FOR_LINKING) +LIBSECTOOL = $(SOURCE_LIB_DIR)/$(LIB_PREFIX)sectool$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX_FOR_LINKING) + +# +# DBM library +# + +LIBDBM = $(SOURCE_LIB_DIR)/$(LIB_PREFIX)dbm$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX_FOR_LINKING) + +# +# NSPR 2.0 libraries +# + + +ifeq ($(OS_ARCH),WINNT) + ifeq ($(OS_TARGET),WIN95) + LIBPLDS = $(SOURCE_LIB_DIR)/plds3_s$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX_FOR_LINKING) + LIBPLC = $(SOURCE_LIB_DIR)/plc3_s$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX_FOR_LINKING) + LIBPR = $(SOURCE_LIB_DIR)/nspr3_s$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX_FOR_LINKING) + else + LIBPLDS = $(SOURCE_LIB_DIR)/libplds3_s$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX_FOR_LINKING) + LIBPLC = $(SOURCE_LIB_DIR)/libplc3_s$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX_FOR_LINKING) + LIBPR = $(SOURCE_LIB_DIR)/libnspr3_s$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX_FOR_LINKING) + endif +else + LIBPLDS = $(SOURCE_LIB_DIR)/libplds3$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX_FOR_LINKING) + LIBPLC = $(SOURCE_LIB_DIR)/libplc3$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX_FOR_LINKING) + LIBPR = $(SOURCE_LIB_DIR)/libnspr3$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX_FOR_LINKING) +endif + +# +# svrcore libraries +# + + LIBSVRPLCY = $(SOURCE_LIB_DIR)/$(LIB_PREFIX)svrplcy$(STATIC_LIB_EXTENSION)$(STATIC_LIB_SUFFIX_FOR_LINKING) + + +####################################################################### +# Initialize variables containing DYNAMIC component library names # +####################################################################### + +# +# legacy library +# + +DLLJDKCERTSEC10 = $(SOURCE_LIB_DIR)/$(DLL_PREFIX)jdkcertsec10$(DYNAMIC_LIB_EXTENSION)$(JDK_DEBUG_SUFFIX)$(DYNAMIC_LIB_SUFFIX_FOR_LINKING) + +# +# jss hclhacks library +# + +DLLJSS = $(SOURCE_LIB_DIR)/$(DLL_PREFIX)jsshclhacks$(DYNAMIC_LIB_EXTENSION)$(JDK_DEBUG_SUFFIX)$(DYNAMIC_LIB_SUFFIX_FOR_LINKING) + +# +# jss library +# + +DLLJSS = $(SOURCE_LIB_DIR)/$(DLL_PREFIX)jss$(DYNAMIC_LIB_EXTENSION)$(JDK_DEBUG_SUFFIX)$(DYNAMIC_LIB_SUFFIX_FOR_LINKING) + +# +# jssutil library +# + +DLLJSSUTIL = $(SOURCE_LIB_DIR)/$(DLL_PREFIX)jssutil$(DYNAMIC_LIB_EXTENSION)$(JDK_DEBUG_SUFFIX)$(DYNAMIC_LIB_SUFFIX_FOR_LINKING) + +# +# jsspkcs11 library +# + +DLLJSSPKCS11 = $(SOURCE_LIB_DIR)/$(DLL_PREFIX)jsspkcs11$(DYNAMIC_LIB_EXTENSION)$(JDK_DEBUG_SUFFIX)$(DYNAMIC_LIB_SUFFIX_FOR_LINKING) + +# +# jsspkcs12 library +# + +DLLJSSPKCS12 = $(SOURCE_LIB_DIR)/$(DLL_PREFIX)jsspkcs12$(DYNAMIC_LIB_EXTENSION)$(JDK_DEBUG_SUFFIX)$(DYNAMIC_LIB_SUFFIX_FOR_LINKING) + +# +# jsscrypto library +# + +DLLJSSCRYPTO= $(SOURCE_LIB_DIR)/$(DLL_PREFIX)jsscrypto$(DYNAMIC_LIB_EXTENSION)$(JDK_DEBUG_SUFFIX)$(DYNAMIC_LIB_SUFFIX_FOR_LINKING) + +# +# jssmanage library +# + +DLLJSSMANAGE = $(SOURCE_LIB_DIR)/$(DLL_PREFIX)jssmanage$(DYNAMIC_LIB_EXTENSION)$(JDK_DEBUG_SUFFIX)$(DYNAMIC_LIB_SUFFIX_FOR_LINKING) + +# +# jsspolicy library +# + +DLLJSSPOLICY = $(SOURCE_LIB_DIR)/$(DLL_PREFIX)jsspolicy$(DYNAMIC_LIB_EXTENSION)$(JDK_DEBUG_SUFFIX)$(DYNAMIC_LIB_SUFFIX_FOR_LINKING) + +# +# jssssl library +# + +DLLJSSSSL = $(SOURCE_LIB_DIR)/$(DLL_PREFIX)jssssl$(DYNAMIC_LIB_EXTENSION)$(JDK_DEBUG_SUFFIX)$(DYNAMIC_LIB_SUFFIX_FOR_LINKING) + +# +# secttools library +# + +DLLSECTOOLS = $(SOURCE_LIB_DIR)/$(DLL_PREFIX)sectools$(DYNAMIC_LIB_EXTENSION)$(DYNAMIC_LIB_SUFFIX_FOR_LINKING) + +# +# sechlp library +# + +DLLSECHLP = $(SOURCE_LIB_DIR)/$(DLL_PREFIX)sechlp$(DYNAMIC_LIB_EXTENSION)$(DYNAMIC_LIB_SUFFIX_FOR_LINKING) + +# +# there are NO dynamic security libraries +# + +# +# DBM library +# + +DLLDBM = $(SOURCE_LIB_DIR)/$(DLL_PREFIX)dbm$(DYNAMIC_LIB_EXTENSION)$(DYNAMIC_LIB_SUFFIX_FOR_LINKING) + +# +# NSPR 2.0 libraries +# + +ifeq ($(OS_ARCH),WINNT) + ifeq ($(OS_TARGET),WIN95) + DLLPLDS = $(SOURCE_LIB_DIR)/plds3$(DYNAMIC_LIB_EXTENSION)$(DYNAMIC_LIB_SUFFIX_FOR_LINKING) + DLLPLC = $(SOURCE_LIB_DIR)/plc3$(DYNAMIC_LIB_EXTENSION)$(DYNAMIC_LIB_SUFFIX_FOR_LINKING) + DLLPR = $(SOURCE_LIB_DIR)/nspr3$(DYNAMIC_LIB_EXTENSION)$(DYNAMIC_LIB_SUFFIX_FOR_LINKING) + else + DLLPLDS = $(SOURCE_LIB_DIR)/libplds3$(DYNAMIC_LIB_EXTENSION)$(DYNAMIC_LIB_SUFFIX_FOR_LINKING) + DLLPLC = $(SOURCE_LIB_DIR)/libplc3$(DYNAMIC_LIB_EXTENSION)$(DYNAMIC_LIB_SUFFIX_FOR_LINKING) + DLLPR = $(SOURCE_LIB_DIR)/libnspr3$(DYNAMIC_LIB_EXTENSION)$(DYNAMIC_LIB_SUFFIX_FOR_LINKING) + endif +else + DLLPLDS = $(SOURCE_LIB_DIR)/libplds3$(DYNAMIC_LIB_EXTENSION)$(DYNAMIC_LIB_SUFFIX_FOR_LINKING) + DLLPLC = $(SOURCE_LIB_DIR)/libplc3$(DYNAMIC_LIB_EXTENSION)$(DYNAMIC_LIB_SUFFIX_FOR_LINKING) + DLLPR = $(SOURCE_LIB_DIR)/libnspr3$(DYNAMIC_LIB_EXTENSION)$(DYNAMIC_LIB_SUFFIX_FOR_LINKING) +endif + +# +# there are NO dynamic svrcore libraries +# + + +####################################################################### +# Tweak library names for windows and AIX. +####################################################################### + +ifndef BUILD_OPT + ifdef LIBRARY_NAME + ifeq ($(OS_ARCH), WINNT) + ifeq ($(OS_TARGET), WIN16) + SHARED_LIBRARY_G = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION)16_g.dll + IMPORT_LIBRARY_G = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION)16_g.lib + else + SHARED_LIBRARY_G = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION)32_g.dll + IMPORT_LIBRARY_G = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION)32_g.lib + endif + else + ifeq ($(OS_ARCH)$(OS_RELEASE), AIX4.1) + SHARED_LIBRARY_G = $(OBJDIR)/lib$(LIBRARY_NAME)$(LIBRARY_VERSION)_shr_g.a + else + SHARED_LIBRARY_G = $(OBJDIR)/lib$(LIBRARY_NAME)$(LIBRARY_VERSION)_g.$(DLL_SUFFIX) + endif + ifdef HAVE_PURIFY + ifdef DSO_BACKEND + PURE_LIBRARY_G = $(OBJDIR)/purelib$(LIBRARY_NAME)$(LIBRARY_VERSION)_g.$(DLL_SUFFIX) + endif + endif + endif + endif +endif diff --git a/mozilla/security/jss/config/linkage.mk b/mozilla/security/jss/config/linkage.mk new file mode 100644 index 00000000000..74b37267b68 --- /dev/null +++ b/mozilla/security/jss/config/linkage.mk @@ -0,0 +1,94 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +####################################################################### +# Adjust variables for component library linkage on some platforms # +####################################################################### + +# +# AIX platforms +# + +ifeq ($(OS_ARCH),AIX) + LDOPTS += -blibpath:.:$(PWD)/$(SOURCE_LIB_DIR):/usr/lib/threads:/usr/lpp/xlC/lib:/usr/lib:/lib +endif + +# +# HP/UX platforms +# + +ifeq ($(OS_ARCH), HP-UX) + LDOPTS += -Wl,+s,+b,$(PWD)/$(SOURCE_LIB_DIR) +endif + +# +# IRIX platforms +# + +ifeq ($(OS_ARCH), IRIX) + LDOPTS += -rpath $(PWD)/$(SOURCE_LIB_DIR) +endif + +# +# OSF 1 platforms +# + +ifeq ($(OS_ARCH), OSF1) + LDOPTS += -rpath $(PWD)/$(SOURCE_LIB_DIR) -lpthread +endif + +# +# Solaris platforms +# NOTE: Disable optimization on SunOS4.1.3 +# + +ifeq ($(OS_ARCH), SunOS) + ifneq ($(OS_RELEASE), 4.1.3_U1) + ifdef NS_USE_GCC + LDOPTS += -Xlinker -R -Xlinker $(PWD)/$(SOURCE_LIB_DIR) + else + LDOPTS += -R $(PWD)/$(SOURCE_LIB_DIR) + endif + else + OPTIMIZER = + endif +endif + +# +# Windows platforms +# + +ifeq ($(OS_ARCH), WINNT) + LDOPTS += -NOLOGO -DEBUG -DEBUGTYPE:CV -INCREMENTAL:NO +endif + diff --git a/mozilla/security/jss/config/rules.mk b/mozilla/security/jss/config/rules.mk new file mode 100644 index 00000000000..282936a70d3 --- /dev/null +++ b/mozilla/security/jss/config/rules.mk @@ -0,0 +1,52 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +####################################################################### +### ### +### R U L E S O F E N G A G E M E N T ### +### ### +####################################################################### + + +package:: + -$(NSINSTALL) -m 664 $(PACKAGE_FILES) $(PLATFORM) +ifeq ($(OS_ARCH),WINNT) + cd $(PLATFORM) ; \ + rm -f $(ARCHIVE_NAME).zip ; \ + zip $(ARCHIVE_NAME).zip $(PACKAGE_FILES) +else + cd $(PLATFORM) ; \ + rm -f $(ARCHIVE_NAME).tar $(ARCHIVE_NAME).tar.gz ; \ + tar cvf $(ARCHIVE_NAME).tar $(PACKAGE_FILES) ; \ + gzip $(ARCHIVE_NAME).tar +endif diff --git a/mozilla/security/jss/config/static.mk b/mozilla/security/jss/config/static.mk new file mode 100644 index 00000000000..a0bfc9af5a9 --- /dev/null +++ b/mozilla/security/jss/config/static.mk @@ -0,0 +1,138 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +####################################################################### +# Initialize STATIC system library names on some platforms # +####################################################################### + +# +# AIX platforms +# + +ifeq ($(OS_ARCH),AIX) +ifeq ($(OS_RELEASE),4.1) + LIBSYSTEM += /lib/libsvld.a /lib/libC_r.a /lib/libC.a /lib/libpthreads.a /lib/libc_r.a /lib/libm.a /lib/libc.a +else + LIBSYSTEM += -ldl /lib/libC_r.a /lib/libC.a /lib/libpthreads.a /lib/libc_r.a /lib/libm.a /lib/libc.a + endif +endif + + +# +# HP/UX platforms +# + +ifeq ($(OS_ARCH),HP-UX) + ifeq ($(USE_PTHREADS), 1) + LIBSYSTEM += -lpthread + endif + ifeq ($(PTHREADS_USER), 1) + LIBSYSTEM += -lpthread + endif + ifeq ($(OS_RELEASE),A.09.03) + LIBSYSTEM += -ldld -L/lib/pa1.1 -lm + else + LIBSYSTEM += -ldld -lm -lc + endif +endif + +# +# Linux platforms +# + +ifeq ($(OS_ARCH), Linux) + LIBSYSTEM += -ldl +endif + +# +# IRIX platforms +# + +ifeq ($(OS_ARCH), IRIX) + ifeq ($(USE_PTHREADS), 1) + LIBSYSTEM += -lpthread + endif +endif + +# +# OSF 1 platforms +# + +ifeq ($(OS_ARCH),OSF1) + ifneq ($(OS_RELEASE),V2.0) + LIBSYSTEM += -lc_r + endif + ifeq ($(USE_PTHREADS), 1) + LIBSYSTEM += -lpthread -lrt + endif + ifeq ($(USE_IPV6), 1) + LIBSYSTEM += -lip6 + endif +endif + +# +# Solaris platforms +# + +ifeq ($(OS_ARCH), SunOS) + ifneq ($(OS_RELEASE), 4.1.3_U1) + ifeq ($(OS_RELEASE), 5.5.1_i86pc) + LIBSYSTEM += -lsocket -lnsl -lintl -ldl + else + ifeq ($(OS_RELEASE), 5.6_i86pc) + LIBSYSTEM += -lsocket -lnsl -lintl -ldl + else + LIBSYSTEM += -lthread -lposix4 /lib/libsocket.a /lib/libnsl.a /lib/libintl.a -ldl + endif + endif + endif +endif + +# +# UNIXWARE platforms +# + +ifeq ($(OS_ARCH), UNIXWARE) + LIBSYSTEM += -lsocket +endif + +# +# Windows platforms +# + +ifeq ($(OS_ARCH),WINNT) + ifneq ($(OS_TARGET),WIN16) + LIBSYSTEM += wsock32.lib winmm.lib + endif +endif + diff --git a/mozilla/security/jss/jss.html b/mozilla/security/jss/jss.html new file mode 100644 index 00000000000..a23927b4857 --- /dev/null +++ b/mozilla/security/jss/jss.html @@ -0,0 +1,97 @@ + + + +Netscape Security Services for Java + + + + +

Netscape Security Services for Java

+ +Netscape Security Services for Java (JSS) is an interface allowing Java applications +to use the Secure Sockets Layer protocol. The interface is implemented with the +FIPS-validated Netscape Security Services library. +It consists of a system-dependent dynamic library (libjss.so +on UNIX, jss.dll on Windows) and a ZIP file +(jss.zip) containing system-independent Java classes. +These classes are compatible with JDK 1.1 or later using the native +thread implementation (not green threads). + +

Building Applications with JSS

+To construct Java applications that use JSS, you must: +
    +
  • Call the JSS classes from your application. +
  • When compiling your application, put jss.zip in your +CLASSPATH. +
  • When running your application, put libjss.so in your +LD_LIBRARY_PATH (on UNIX) or jss.dll +in your PATH (on Windows), and put +jss.zip in your CLASSPATH. +
+ +

Programming with JSS

+Before the SSL classes can be used, + +NSSInit.initialize must be called to open the security +databases and initialize the random number generator. + +NSSInit.setPasswordCallback may be called to change the password +callback; the default is to prompt for passwords on the command line. + +

The files in the examples directory illustrate the use of JSS +in an application: +

+
SSLClient.java +
An example of an SSL client application. +
SSLServer.java +
An example of an SSL server application. +To run, it requires certificate +and key databases that contain a certificate called "SSLServer". The sample +cert7.db and key3.db files, also in the +examples directory, +can be used for this purpose. When SSLServer is run, +it will ask for a password +for the "Internal Key Storage Token", which is the key database. +The password for the example key3.db file is "netscape". +
+These classes are in the com.netscape.jss.ssl package. +The .class files must be put in the subdirectory +com/netscape/jss/ssl of a CLASSPATH entry +in order to be located by the Java virtual machine. + +

Javadoc for the JSS Classes

+ + + + diff --git a/mozilla/security/jss/manifest.mn b/mozilla/security/jss/manifest.mn new file mode 100644 index 00000000000..f1c1adeef11 --- /dev/null +++ b/mozilla/security/jss/manifest.mn @@ -0,0 +1,50 @@ +# +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. + +CORE_DEPTH = .. + +MODULE = ninja + +IMPORTS = svrcore/SVRCORE_2_5_1 \ + security/NSS_2_8_4_RTM \ + dbm/DBM_1_54 \ + nspr20/v3.5.1 \ + $(NULL) + +DIRS = com \ + cmd \ + $(NULL) + +PACKAGE_DIR = _TOP + +RELEASE = ninja diff --git a/mozilla/security/jss/nss_release.pl b/mozilla/security/jss/nss_release.pl new file mode 100644 index 00000000000..a3af5f329c9 --- /dev/null +++ b/mozilla/security/jss/nss_release.pl @@ -0,0 +1,166 @@ +#! /usr/local/bin/perl +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +require('coreconf.pl'); + +############################################### +# Read in variables on command line into %var +############################################### + +$var{ZIP} = "zip"; + +&parse_argv; + + +############################ +# check variables +############################ + +if ($var{RELEASE_TREE} eq "") { exit; } +if ($var{RELEASE} eq "") { exit; } +if ($var{RELEASE_VERSION} eq "") { exit; } +if ($var{PLATFORM} eq "") { exit; } +if ($var{OS_ARCH} eq "") { exit; } + +############################ +# cd to the dist directory +############################ + +print STDERR "chdir ../dist/classes\n"; +chdir("../dist/classes"); + + +############################################################################### +# Specify all class files to be packaged, the load_library path, and the dest +############################################################################### + +$filelist = + 'com/netscape/jss/ssl/*.class '. + 'com/netscape/jss/crypto/AlreadyInitializedException.class '. + 'com/netscape/jss/pkcs11/TokenCallbackInfo.class '. + 'com/netscape/jss/NSSInit.class '. + 'com/netscape/jss/CertDatabaseException.class '. + 'com/netscape/jss/KeyDatabaseException.class '. + 'com/netscape/jss/util/Assert.class '. + 'com/netscape/jss/util/AssertionException.class '. + 'com/netscape/jss/util/ConsolePasswordCallback.class '. + 'com/netscape/jss/util/Debug.class '. + 'com/netscape/jss/util/Password.class '. + 'com/netscape/jss/util/PasswordCallback.class '. + 'com/netscape/jss/util/PasswordCallback?GiveUpException.class '. + 'com/netscape/jss/util/PasswordCallbackInfo.class '. + 'com/netscape/jss/util/UTF8Converter.class'; + +$load_library = "../$var{'PLATFORM'}/lib/"; + +$dest = "$var{'RELEASE_TREE'}/$var{'RELEASE'}/$var{'RELEASE_VERSION'}/$var{'PLATFORM'}"; + +##################################################################### +# Dependent upon platform, package the files into the proper format +##################################################################### + +if ($var{OS_ARCH} eq 'WINNT') { + $filelist =~ s/\//\\/; + $load_library =~ s/\//\\/; + $dest =~ s/\//\\/; + + $load_library .= 'jss.dll'; + + print STDERR "cp $load_library .\n"; + system("cp $load_library ."); + + print STDERR "zip -T -r jss.jar $filelist\n"; + system("zip -T -r jss.zip $filelist"); + + print STDERR "zip -T winjss.zip jss.zip jss.dll\n"; + system("zip -T winjss.zip jss.zip jss.dll"); + + if (! (-e "$dest" && -d "$dest")) { + print STDERR "making dir $dest \n"; + &rec_mkdir("$dest"); + } + + print STDERR "cp winjss.zip $dest\n"; + system("cp winjss.zip $dest"); + + print STDERR "rm winjss.zip jss.zip jss.dll\n"; + system("rm winjss.zip jss.zip jss.dll"); +} +elsif ($var{OS_ARCH} eq 'HP-UX') { + $load_library .= 'libjss.sl'; + + print STDERR "cp $load_library .\n"; + system("cp $load_library ."); + + print STDERR "zip -T -r jss.jar $filelist\n"; + system("zip -T -r jss.zip $filelist"); + + print STDERR "tar -cvf unixjss.tar jss.zip libjss.sl\n"; + system("tar -cvf unixjss.tar jss.zip libjss.sl"); + + if (! (-e "$dest" && -d "$dest")) { + print STDERR "making dir $dest \n"; + &rec_mkdir("$dest"); + } + + print STDERR "cp unixjss.tar $dest\n"; + system("cp unixjss.tar $dest"); + + print STDERR "rm unixjss.tar jss.zip libjss.so\n"; + system("rm unixjss.tar jss.zip libjss.so"); +} +else { + $load_library .= 'libjss.so'; + + print STDERR "cp $load_library .\n"; + system("cp $load_library ."); + + print STDERR "zip -T -r jss.jar $filelist\n"; + system("zip -T -r jss.zip $filelist"); + + print STDERR "tar -cvf unixjss.tar jss.zip libjss.so\n"; + system("tar -cvf unixjss.tar jss.zip libjss.so"); + + if (! (-e "$dest" && -d "$dest")) { + print STDERR "making dir $dest \n"; + &rec_mkdir("$dest"); + } + + print STDERR "cp unixjss.tar $dest\n"; + system("cp unixjss.tar $dest"); + + print STDERR "rm unixjss.tar jss.zip libjss.so\n"; + system("rm unixjss.tar jss.zip libjss.so"); +} + diff --git a/mozilla/security/jss/org/Makefile b/mozilla/security/jss/org/Makefile new file mode 100644 index 00000000000..8d818df89f2 --- /dev/null +++ b/mozilla/security/jss/org/Makefile @@ -0,0 +1,76 @@ +#! gmake +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +####################################################################### +# (1) Include initial platform-independent assignments (MANDATORY). # +####################################################################### + +include manifest.mn + +####################################################################### +# (2) Include "global" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/config.mk + +####################################################################### +# (3) Include "component" configuration information. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (4) Include "local" platform-dependent assignments (OPTIONAL). # +####################################################################### + + + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### + + + diff --git a/mozilla/security/jss/org/manifest.mn b/mozilla/security/jss/org/manifest.mn new file mode 100644 index 00000000000..37954adc393 --- /dev/null +++ b/mozilla/security/jss/org/manifest.mn @@ -0,0 +1,39 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +CORE_DEPTH = ../.. + +MODULE = ninja + +DIRS = netscape \ + $(NULL) diff --git a/mozilla/security/jss/org/mozilla/Makefile b/mozilla/security/jss/org/mozilla/Makefile new file mode 100644 index 00000000000..8d818df89f2 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/Makefile @@ -0,0 +1,76 @@ +#! gmake +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +####################################################################### +# (1) Include initial platform-independent assignments (MANDATORY). # +####################################################################### + +include manifest.mn + +####################################################################### +# (2) Include "global" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/config.mk + +####################################################################### +# (3) Include "component" configuration information. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (4) Include "local" platform-dependent assignments (OPTIONAL). # +####################################################################### + + + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### + + + diff --git a/mozilla/security/jss/org/mozilla/jss/Makefile b/mozilla/security/jss/org/mozilla/jss/Makefile new file mode 100644 index 00000000000..adc0925c06e --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/Makefile @@ -0,0 +1,77 @@ +#! gmake +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +####################################################################### +# (1) Include initial platform-independent assignments (MANDATORY). # +####################################################################### + +include manifest.mn + +####################################################################### +# (2) Include "global" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/config.mk + +####################################################################### +# (3) Include "component" configuration information. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (4) Include "local" platform-dependent assignments (OPTIONAL). # +####################################################################### + + + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### +include rules.mk + + + diff --git a/mozilla/security/jss/org/mozilla/jss/asn1/ANY.java b/mozilla/security/jss/org/mozilla/jss/asn1/ANY.java new file mode 100644 index 00000000000..5d873eb997d --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/asn1/ANY.java @@ -0,0 +1,287 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.asn1; + +import com.netscape.jss.util.Assert; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; + +/** + * Represents an ASN.1 ANY value. An ANY is just an arbitrary + * ASN.1 value. It can be thought of as the simplest implementation of the + * ASN1Value interface. Although they can be created + * from scratch (from raw BER), instances of ANY are usually + * found after decoding + * with a template that has an ANY field. + * + *

An ANY supports extracting the BER encoding, or decoding + * with a different template. + */ +public class ANY implements ASN1Value { + + private ANY() { } + + // The complete encoding of header + contents + private byte[] encoded; + private Tag tag; + + /** + * Creates an ANY value, which is just a generic ASN.1 value. + * This method is provided for efficiency if the tag is already known, + * so that we don't have to parse the encoding for it. + * @param tag The tag of this value. It must be the same as the actual tag + * contained in the encoding. + * @param encoded The complete BER encoding of this value, including + * tag, form, length, and contents. + */ + public ANY(Tag tag, byte[] encoded) { + this.encoded = encoded; + this.tag = tag; + } + + /** + * Creates an ANY value, which is just a generic ASN.1 value. + * @param encoded The complete BER encoding of this value, including + * tag, form, length, and contents. + */ + public ANY(byte[] encoded) throws InvalidBERException { + try { + this.encoded = encoded; + + ByteArrayInputStream bis = new ByteArrayInputStream(encoded); + ASN1Header head = new ASN1Header(bis); + this.tag = head.getTag(); + } catch(IOException e) { + throw new com.netscape.jss.util.AssertionException( + "IOException while creating ANY: "+e); + } + } + + /** + * Returns the tag of this value. + */ + public Tag getTag() { + return tag; + } + + /** + * Returns the complete encoding of header and contents, as passed into + * the constructor or read from a BER input stream. + */ + public byte[] getEncoded() { + return encoded; + } + + /** + * Returns the ASN.1 header from the encoding. + */ + public ASN1Header getHeader() throws InvalidBERException, IOException { + if( header == null ) { + ByteArrayInputStream bis = new ByteArrayInputStream(encoded); + header = new ASN1Header(bis); + } + return header; + } + private ASN1Header header=null; + + /** + * Strips out the header and returns just the contents octets of the + * encoding. + */ + private byte[] contents=null; + public byte[] getContents() throws InvalidBERException { + try { + if( contents==null ) { + ByteArrayInputStream bis = new ByteArrayInputStream(encoded); + header = new ASN1Header(bis); + contents = new byte[ bis.available() ]; + if( (contents.length != header.getContentLength()) && + ( header.getContentLength() != -1 ) ) { + throw new InvalidBERException("Length of contents was not the "+ + "same as the header predicted"); + } + ASN1Util.readFully(contents, bis); + } + + return contents; + + } catch( IOException e ) { + Assert.notReached("IOException reading from byte array"); + return null; + } + } + + public void encode(OutputStream ostream) throws IOException { + ostream.write(encoded); + } + + /** + * Decodes this ANY using the given template. This is useful if you + * originally decoded something as an ANY because you didn't know + * what it was, but now you know what it is supposed to be. + * + * @param template The template to use to decode this ANY. + * @return The output of the given template when it is fed the + * encoding of this ANY. + */ + public ASN1Value decodeWith(ASN1Template template) + throws InvalidBERException + { + try { + ByteArrayInputStream bis = new ByteArrayInputStream(encoded); + return template.decode(bis); + } catch( IOException e ) { + Assert.notReached("IOException while reading from byte array input"+ + " stream"); + return null; + } + } + + /** + * Decodes this ANY using the given template. This is useful if you + * originally decoded something as an ANY because you didn't know + * what it was, but now you know what it is supposed to be. + * + * @param implicitTag The implicit tag for the encoding. + * @param template The template to use to decode this ANY. + * @return The output of the given template when it is fed the + * encoding of this ANY. + */ + public ASN1Value decodeWith(Tag implicitTag, ASN1Template template) + throws IOException, InvalidBERException + { + ByteArrayInputStream bis = new ByteArrayInputStream(encoded); + return template.decode(implicitTag, bis); + } + + /** + * @param implicitTag This parameter is ignored, because + * ANY values cannot have implicit tags. + */ + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + if( ! implicitTag.equals(tag) ) { + Assert.notReached("No implicit tags allowed for ANY"); + } + ostream.write(encoded); + } + + /** + * Extracts the contents from the ANY and encodes them with + * the provided tag. + */ + public void encodeWithAlternateTag(Tag alternateTag, OutputStream ostream) + throws IOException, InvalidBERException + { + byte[] contents = getContents(); + ASN1Header oldHead = getHeader(); + Assert.assert( contents.length == oldHead.getContentLength() ); + + ASN1Header newHead = new ASN1Header( alternateTag, oldHead.getForm(), + contents.length); + newHead.encode(ostream); + ostream.write(contents); + } + + /** + * Returns a singleton instance of a decoding template. + */ + public static Template getTemplate() { + return templateInstance; + } + private static Template templateInstance = new Template(); + +/** + * A class for decoding ANY values from BER. + */ +public static class Template implements ASN1Template { + + public boolean tagMatch(Tag tag) { + return true; // wheeeeee...it's ANY! + + } + + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + try { + + ASN1Header head = ASN1Header.lookAhead(istream); + + if( head.getContentLength() == -1 ) { + // indefinite length encoding + ByteArrayOutputStream recording = new ByteArrayOutputStream(); + + // eat the header off the input stream + head = new ASN1Header(istream); + + // write the header to the recording stream + recording.write( head.encode() ); + + // write all objects from the input stream to the recording + // stream, until we hit an END-OF-CONTENTS tag + ANY any; + ANY.Template anyt = new ANY.Template(); + int count=0; + do { + any = (ANY) anyt.decode(istream); + recording.write( any.getEncoded() ); + } while( ! any.getTag().equals(Tag.EOC) ); + + return new ANY( head.getTag(), recording.toByteArray() ); + + } else { + // definite length encoding + byte[] data = new byte[ (int) head.getTotalLength() ]; + + ASN1Util.readFully(data, istream); + return new ANY(head.getTag(), data); + } + + } catch( InvalidBERException e ) { + throw new InvalidBERException(e, "ANY"); + } + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws IOException, InvalidBERException + { + throw new InvalidBERException("Implicit tag on ANY"); + } +} // End of Template + +} diff --git a/mozilla/security/jss/org/mozilla/jss/asn1/ASN1Header.java b/mozilla/security/jss/org/mozilla/jss/asn1/ASN1Header.java new file mode 100644 index 00000000000..eb01e308c64 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/asn1/ASN1Header.java @@ -0,0 +1,411 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.asn1; + +import java.math.BigInteger; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.ByteArrayOutputStream; +import java.util.Vector; +import com.netscape.jss.util.Assert; + +/** + * The portion of a BER encoding that precedes the contents octets. Consists + * of the tag, form, and length octets. + */ +public class ASN1Header { + + // This is set by the the decoding constructor, and by the encode() + // method. If it is set by the decoding constructor, it is supposed + // to represent what was actually read from the input stream, so it + // must not be overwritten later by the output of encode(), which could + // be a different encoding (DER vs. BER, for example). + private byte[] cachedEncoding = null; + + /** + * Returns the length of the header plus the length of the contents; + * the total length of the DER encoding of an ASN1 value. Returns + * -1 if indefinite length encoding was used. + */ + public long getTotalLength() { + if( contentLength == -1 ) { + return -1; + } else { + return encode().length + contentLength; + } + } + + private Tag tag; + public Tag getTag() { + return tag; + } + + // -1 means indefinite length encoding + private long contentLength; + /** + * Returns -1 for indefinite length encoding. + */ + public long getContentLength() { + return contentLength; + } + + // PRIMITIVE or CONSTRUCTED + public static final Form PRIMITIVE = Form.PRIMITIVE; + public static final Form CONSTRUCTED = Form.CONSTRUCTED; + private Form form; + + /** + * Returns the Form, PRIMITIVE or CONSTRUCTED. + */ + public Form getForm() { + return form; + } + + // This is the maximum size of ASN1 Header we support. + // 32 bytes is pretty huge, I've never seen anything bigger than 7. + private static final int MAX_LOOK_AHEAD = 32; + + /** + * Returns information about the next item in the stream, but does not + * consume any octets. + * @exception IOException If the input stream does not support look ahead. + */ + public static ASN1Header lookAhead(InputStream derStream) + throws IOException, InvalidBERException + { + if( ! derStream.markSupported() ) { + throw new IOException("Mark not supported on this input stream"); + } + + derStream.mark(MAX_LOOK_AHEAD); + ASN1Header info = new ASN1Header(derStream); + derStream.reset(); + + return info; + } + + /** + * Gets info about the next item in the DER stream, consuming the + * identifier and length octets. + */ + public ASN1Header(InputStream istream) + throws InvalidBERException, IOException + { + // default BAOS size is 32 bytes, which is plenty + ByteArrayOutputStream encoding = new ByteArrayOutputStream(); + int inInt = istream.read(); + if( inInt == -1 ) { + throw new InvalidBERException("End-of-file reached while "+ + "decoding ASN.1 header"); + } + encoding.write(inInt); + byte byte1 = (byte) inInt; + Tag.Class tagClass; + + // + // Get Tag Class + // + tagClass = Tag.Class.fromInt( (byte1 & 0xff) >>> 6 ); + + // + // Get form + // + if( (byte1 & 0x20) == 0x20 ) { + form = CONSTRUCTED; + } else { + form = PRIMITIVE; + } + + // + // Get Tag Number + // + long tagNum; + if( (byte1 & 0x1f) == 0x1f ) { + // long form + + // + // read all octets into a Vector of Bytes + // + byte next; + Vector bV = new Vector(); + + // last byte has MSB == 0. + do { + inInt = istream.read(); + if( inInt == -1 ) { + throw new InvalidBERException("End-of-file reached while" + +" decoding ASN.1 header"); + } + encoding.write(inInt); + next = (byte) inInt; + bV.addElement( new Byte(next) ); + } while( (next & 0x80) == 0x80 ); + Assert.assert( bV.size() > 0 ); + + // + // Copy Vector of 7-bit bytes into array of 8-bit bytes. + // + byte[] bA = new byte[ ( (bV.size()*7) + 7 ) / 8 ]; + int v; // vector index + int a; // array index + + // clear the target array + for( a = 0; a < bA.length; a++ ) { + bA[a] = 0; + } + int shift = 0; // the amount the Vector is shifted from the array + + // copy bits from the Vector to the array, going from the + // end (LSB) to the beginning (MSB). + a = bA.length - 1; + for( v=bV.size()-1 ; v >= 0; v--) { + Assert.assert( v >= 0 ); + Assert.assert( v < bV.size() ); + Assert.assert( a >= 0 ); + Assert.assert( a < bA.length ); + + // MSB is not part of the number + byte b = (byte) ( ((Byte)bV.elementAt(v)).byteValue() & 0x7f ); + bA[a] |= b << shift; + if( shift > 1 ) { + // The byte from the Vector falls across a byte boundary + // in the array. We've already got the less-significant + // bits, now copy the more-significant bits into + // the next element of the array. + Assert.assert( a > 0 ); + --a; + bA[a] |= b >>> (8-shift); + } + + shift = (shift+7)%8; // update shift + } + + // Create a new unsigned BigInteger from the byte array + tagNum = (new BigInteger( 1, bA )).longValue(); + + } else { + // short form + tagNum = byte1 & 0x1f; + } + + tag = new Tag(tagClass, tagNum); + + // + // Get Length + // + inInt = istream.read(); + if(inInt == -1) { + throw new InvalidBERException("End-of-file reached while "+ + "decoding ASN.1 header"); + } + encoding.write(inInt); + byte lenByte = (byte) inInt; + + if( (lenByte & 0x80) == 0 ) { + // short form + contentLength = lenByte; + } else { + // long form + if( (lenByte & 0x7f) == 0 ) { + // indefinite + contentLength = -1; + } else { + // definite + byte[] lenBytes = new byte[ lenByte & 0x7f ]; + ASN1Util.readFully(lenBytes, istream); + encoding.write( lenBytes ); + contentLength = (new BigInteger( 1, lenBytes )).longValue(); + } + } + + // save our encoding so we don't have to recompute it later + cachedEncoding = encoding.toByteArray(); + } + + /** + * This constructor is to be called when we are constructing an ASN1Value + * rather than decoding it. + * @param contentLength Must be >=0. Although indefinite length + * decoding is supported, indefinite length encoding + * is not. + */ + public ASN1Header( Tag tag, Form form, long contentLength) + { + this.tag = tag; + this.form = form; + Assert.assert(contentLength >= 0); + this.contentLength = contentLength; + } + + public void encode( OutputStream ostream ) + throws IOException + { + ostream.write( encode() ); + } + + public byte[] encode() { + // It's important that we not recompute the encoding if it was + // set by ASN1Header(InputStream), since in that case it represents + // the encoding that was actually read from the InputStream. + if( cachedEncoding != null ) { + return cachedEncoding; + } + + ByteArrayOutputStream cache = new ByteArrayOutputStream(); + + // + // Identifier octet(s) + // + + byte idOctet = 0; + idOctet |= tag.getTagClass().toInt() << 6; + + if( form == CONSTRUCTED ) { + idOctet |= 0x20; + } + + if( tag.getNum() <= 30 ) { + // short form + idOctet |= (tag.getNum() & 0x1f ); + + cache.write( idOctet ); + } else { + // long form + idOctet |= 0x1f; + BigInteger tagNum = BigInteger.valueOf(tag.getNum()); + + cache.write( idOctet ); + + int bitlength = tagNum.bitLength(); + int reps = (bitlength+6)/7; + + for( reps = reps-1; reps > 0 ; reps--) { + long shifted = tag.getNum() >>> ( 7*reps ); + cache.write( (((byte)shifted) & 0x7f) | 0x80 ); + } + + cache.write( ((byte)tag.getNum()) & 0x7f ); + } + + // + // Length Octets + // + if( contentLength == -1 ) { + // indefinite form + cache.write( (byte) 0x80 ); + } else if( contentLength <= 127 ) { + // short form + cache.write( (byte) contentLength ); + } else { + // long form + byte[] val = unsignedBigIntToByteArray( + BigInteger.valueOf(contentLength) ); + cache.write( ((byte)val.length) | 0x80 ); + cache.write( val, 0, val.length ); + } + + cachedEncoding = cache.toByteArray(); + + return cachedEncoding; + } + + /** + * Converts an unsigned BigInteger to a minimal-length byte array. + * This is necessary because BigInteger.toByteArray() attaches an extra + * sign bit, which could cause the size of the byte representation to + * be bumped up by an extra byte. + */ + public static byte[] unsignedBigIntToByteArray(BigInteger bi) { + // make sure it is not negative + Assert.assert( bi.compareTo(BigInteger.valueOf(0)) != -1 ); + + // find minimal number of bytes to hold this value + int bitlen = bi.bitLength(); // minimal number of bits, without sign + int bytelen; + if( bitlen == 0 ) { + // special case, since bitLength() returns 0 + bytelen = 1; + } else { + bytelen = (bitlen + 7) / 8; + } + + byte[] withSign = bi.toByteArray(); + + if( bytelen == withSign.length ) { + return withSign; + } else { + // trim off extra byte at the beginning + Assert.assert( bytelen == withSign.length - 1 ); + Assert.assert( withSign[0] == 0 ); + byte[] without = new byte[bytelen]; + System.arraycopy(withSign,1, without, 0, bytelen); + return without; + } + } + + /** + * Verifies that this header has the given tag and form. + * @exception InvalidBERException If the header's tag or form + * differ from those passed in. + */ + public void validate(Tag expectedTag, Form expectedForm) + throws InvalidBERException + { + validate(expectedTag); + if( getForm() != expectedForm ) { + throw new InvalidBERException("Incorrect form: expected ["+ + expectedForm+"], found ["+getForm()); + } + } + + /** + * Verifies that this head has the given tag. + * @exception InvalidBERException If the header's tag differs from that + * passed in. + */ + public void validate(Tag expectedTag) throws InvalidBERException { + if( ! getTag().equals( expectedTag ) ) { + throw new InvalidBERException("Incorrect tag: expected ["+ + expectedTag+"], found ["+getTag()+"]"); + } + } + + /** + * Returns true if this is a BER end-of-contents marker. + */ + public boolean isEOC() { + return( tag.equals(Tag.EOC) ); + } + +} diff --git a/mozilla/security/jss/org/mozilla/jss/asn1/ASN1Template.java b/mozilla/security/jss/org/mozilla/jss/asn1/ASN1Template.java new file mode 100644 index 00000000000..61744d57b62 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/asn1/ASN1Template.java @@ -0,0 +1,73 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.asn1; + +import java.io.OutputStream; +import java.io.InputStream; +import java.io.IOException; + +/** + * An interface for decoding ASN1Values from their BER encodings. + * + * @see ASN1Value + */ +public interface ASN1Template { + + /** + * Determines whether the given tag will satisfy this template. + */ + public boolean tagMatch(Tag tag); + + /** + * Decodes an ASN1Value from the InputStream without an implicit tag. + * @param istream Must support marking (markSupported() == true). + * For example, ByteArrayInputStream and BufferedInputStream + * support marking, but FileInputStream does not. If your source + * does not support marking, you can wrap it in a + * BufferedInputStream. + */ + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException; + + /** + * Decodes an ASN1Value from the InputStream with the given implicit + * tag. + * @param istream Must support marking (markSupported() == true). + * For example, ByteArrayInputStream and BufferedInputStream + * support marking, but FileInputStream does not. If your source + * does not support marking, you can wrap it in a + * BufferedInputStream. + */ + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws IOException, InvalidBERException; +} diff --git a/mozilla/security/jss/org/mozilla/jss/asn1/ASN1Util.java b/mozilla/security/jss/org/mozilla/jss/asn1/ASN1Util.java new file mode 100644 index 00000000000..bc012edfce8 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/asn1/ASN1Util.java @@ -0,0 +1,114 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.asn1; + +import java.io.*; +import com.netscape.jss.asn1.InvalidBERException; +import com.netscape.jss.util.Assert; + +public class ASN1Util { + + public static byte[] encode(ASN1Value val) { + return encode(val.getTag(), val); + } + + public static byte[] encode(Tag implicitTag, ASN1Value val) + { + try { + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + val.encode(implicitTag, bos); + return bos.toByteArray(); + + } catch( IOException e ) { + Assert.notReached("Encoding to byte array gave IOException"); + return null; + } + } + + public static ASN1Value decode(ASN1Template template, byte[] encoded) + throws InvalidBERException + { + try { + + ByteArrayInputStream bis = new ByteArrayInputStream(encoded); + return template.decode(bis); + + } catch( IOException e ) { + Assert.notReached("Decoding from byte array gave IOException"); + return null; + } + } + + public static ASN1Value decode(Tag implicitTag, ASN1Template template, + byte[] encoded) + throws InvalidBERException + { + try { + + ByteArrayInputStream bis = new ByteArrayInputStream(encoded); + return template.decode(implicitTag, bis); + + } catch( IOException e ) { + Assert.notReached("Decoding from byte array gave IOException"); + return null; + } + } + + + + /** + * Fills a byte array with bytes from an input stream. This method + * keeps reading until the array is filled, an IOException occurs, or EOF + * is reached. The byte array will be completely filled unless an + * exception is thrown. + * + * @param bytes A byte array which will be filled up. + * @param istream The input stream from which to read the bytes. + * @exception IOException If an IOException occurs reading from the + * stream, or EOF is reached before the byte array is filled. + */ + public static void readFully(byte[] bytes, InputStream istream) + throws IOException + { + + int numRead=0; + while(numRead < bytes.length) { + int nr = istream.read(bytes, numRead, bytes.length-numRead); + if( nr == -1 ) { + throw new EOFException(); + } + numRead += nr; + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/asn1/ASN1Value.java b/mozilla/security/jss/org/mozilla/jss/asn1/ASN1Value.java new file mode 100644 index 00000000000..ebf8633e8f3 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/asn1/ASN1Value.java @@ -0,0 +1,63 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.asn1; + +import java.io.OutputStream; +import java.io.IOException; + +/** + * A value that can be decoded from BER and encoded to DER. + * + * @see ASN1Template + */ +public interface ASN1Value { + + /** + * Returns the base tag for this type, not counting any tags + * that may be imposed on it by its context. + */ + public Tag getTag(); + + /** + * Write this value's DER encoding to an output stream using + * its own base tag. + */ + public void encode(OutputStream ostream) throws IOException; + + /** + * Write this value's DER encoding to an output stream using + * an implicit tag. + */ + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException; +} diff --git a/mozilla/security/jss/org/mozilla/jss/asn1/BIT_STRING.java b/mozilla/security/jss/org/mozilla/jss/asn1/BIT_STRING.java new file mode 100644 index 00000000000..96bfa77e193 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/asn1/BIT_STRING.java @@ -0,0 +1,257 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.asn1; + +import com.netscape.jss.util.Assert; +import java.math.BigInteger; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.ByteArrayOutputStream; +import java.util.BitSet; + +/** + * An ASN.1 BIT STRING, which is an ordered sequence of bits. + * The bits are stored the same way they are encoded in BER: as an array + * of bytes with 0-7 unused bits at the end. + */ +public class BIT_STRING implements ASN1Value { + + private BIT_STRING() { } + + private byte[] bits; + private int padCount; + + /** + * @param bits The bits packed into an array of bytes, with padding + * at the end. The array may be empty (but not null), in which case + * padCount must be zero. The array is referenced, + * not cloned. + * @param padCount The number of padding bits at the end of the array. + * Must be in the range [0,7]. + * @exception NumberFormatException If padCount is not in + * the range [0,7], or bits is + * empty and padCount is non-zero. + */ + public BIT_STRING(byte[] bits, int padCount) + throws NumberFormatException + { + if(padCount < 0 || padCount > 7) { + throw new NumberFormatException(); + } + if(bits.length == 0 && padCount != 0) { + throw new NumberFormatException(); + } + this.bits = bits; + this.padCount = padCount; + } + + /** + * Constructs a BIT_STRING from a BitSet. + * @param bs A BitSet. + * @param numBits The number of bits to copy from the BitSet. + * This is necessary because the size of a BitSet is always padded + * up to a multiple of 64, but not all of these bits may + * be significant. + * @exception NumberFormatException If numBits is larger + * than bs.size() or less than zero. + */ + public BIT_STRING(BitSet bs, int numBits) + throws NumberFormatException + { + if( numBits < 0 || numBits > bs.size() ) { + throw new NumberFormatException(); + } + // allocate enough bytes to hold all the bits + bits = new byte[(numBits+7) / 8]; + padCount = bits.length - numBits; + Assert.assert( padCount >= 0 ); + + for(int i=0; i < numBits; i++) { + if( bs.get(i) ) { + bits[i/8] |= 0x80 >>> (i%8); + } + } + } + + /** + * Returns the bits packed into an array of bytes, with padding + * at the end. The array may be empty (but not null), in which case + * padCount must be zero. The array is referenced, + * not cloned. + */ + public byte[] getBits() { + return bits; + } + + /** + * Copies this BIT STRING into a Java BitSet. Note that BitSet.size() + * will not accurately reflect the number of bits in the BIT STRING, + * because the size of a BitSet is always rounded up to the next multiple + * of 64. The extra bits will be set to 0. + */ + public BitSet toBitSet() { + BitSet bs = new BitSet(); + int numBits = (bits.length * 8) - padCount; + for( int i=0; i < numBits; i++) { + if( (bits[i/8] & (0x80 >>> (i%8))) != 0 ) { + bs.set(i); + } else { + bs.clear(i); + } + } + return bs; + } + + /** + * Copies this BIT STRING into a boolean array. Each element of the array + * represents one bit with true for 1 and false + * for 0. + */ + public boolean[] toBooleanArray() { + boolean[] array = new boolean[(bits.length*8) - padCount]; + // all elements are set to false by default + + for(int i=0; i < array.length; i++) { + if( (bits[i/8] & (0x80 >>> (i%8))) != 0 ) { + array[i] = true; + } + } + return array; + } + + /** + * Returns the number of padding bits at the end of the array. + * Must be in the range [0,7]. + */ + public int getPadCount() { + return padCount; + } + + public static final Tag TAG = new Tag(Tag.UNIVERSAL, 3); + public static final Form FORM = Form.PRIMITIVE; + + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + encode(TAG, ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + ASN1Header head = new ASN1Header(implicitTag, FORM, bits.length+1 ); + + head.encode(ostream); + + ostream.write(padCount); + ostream.write(bits); + } + + private static final Template templateInstance = new Template(); + public static Template getTemplate() { + return templateInstance; + } + +/** + * A class for decoding a BIT_STRING from its BER encoding. + */ +public static class Template implements ASN1Template { + + + public boolean tagMatch(Tag tag) { + return( TAG.equals(tag) ); + } + + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws IOException, InvalidBERException + { + try { + ASN1Header head = new ASN1Header( istream ); + head.validate( implicitTag ); + + if( head.getContentLength() == -1 ) { + // indefinite length encoding + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + int padCount=0; + ASN1Header ahead; + do { + ahead = ASN1Header.lookAhead(istream); + if( ! ahead.isEOC() ) { + if(padCount != 0 ) { + throw new InvalidBERException("Element of constructed "+ + "BIT STRING has nonzero unused bits, but is not\n"+ + "the last element of the construction."); + } + BIT_STRING.Template bst = new BIT_STRING.Template(); + BIT_STRING bs = (BIT_STRING) bst.decode(istream); + bos.write( bs.getBits() ); + padCount = bs.getPadCount(); + } + } while( ! ahead.isEOC() ); + + // consume the EOC + ahead = new ASN1Header(istream); + + return new BIT_STRING( bos.toByteArray(), padCount ); + } + + // First octet is the number of unused bits in last octet + int padCount = istream.read(); + if( padCount == -1 ) { + throw new InvalidBERException.EOF(); + } else if( padCount < 0 || padCount > 7 ) { + throw new InvalidBERException("Unused bits not in range [0,7]"); + } + + // get the rest of the octets + byte[] bits = new byte[ (int) head.getContentLength() - 1]; + ASN1Util.readFully(bits, istream); + + return new BIT_STRING(bits, padCount); + + } catch(InvalidBERException e) { + throw new InvalidBERException(e, "BIT STRING"); + } + } +} // end of Template + +} diff --git a/mozilla/security/jss/org/mozilla/jss/asn1/BMPString.java b/mozilla/security/jss/org/mozilla/jss/asn1/BMPString.java new file mode 100644 index 00000000000..7d021a4c52c --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/asn1/BMPString.java @@ -0,0 +1,143 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.asn1; + +import java.io.CharConversionException; +import java.io.UnsupportedEncodingException; +import com.netscape.jss.util.Assert; + +/** + * The ASN.1 type BMPString. BMPStrings use the Unicode character set. + * They are encoded and decoded in big-endian format using two octets. + */ +public class BMPString extends CharacterString implements ASN1Value { + + /** + * Creates a new BMPString from an array of Java characters. + */ + public BMPString(char[] chars) throws CharConversionException { + super(chars); + } + + /** + * Creates a new BMPString from a Java String. + */ + public BMPString(String s) throws CharConversionException { + super(s); + } + + /** + * Returns the conversion object for converting between an encoded byte + * array an an array of Java characters. + */ + CharConverter getCharConverter() { + return converterInstance; + } + private static final BMPConverter converterInstance = new BMPConverter(); + + static final Tag TAG = new Tag( Tag.UNIVERSAL, 30 ); + static final Form FORM = Form.PRIMITIVE; + + public Tag getTag() { + return TAG; + } + + /** + * Returns a singleton instance of BMPString.Template. This is more + * efficient than creating a new BMPString.Template. + */ + public static Template getTemplate() { + return templateInstance; + } + private static final Template templateInstance = new Template(); + +// nested class +public static class Template + extends CharacterString.Template implements ASN1Template +{ + protected Tag getTag() { + return TAG; + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + protected CharConverter getCharConverter() { + return new BMPConverter(); + } + + protected CharacterString generateInstance(char[] chars) + throws CharConversionException + { + return new BMPString(chars); + } + + protected String typeName() { + return "BMPString"; + } +} + +private static class BMPConverter implements CharConverter { + + public char[] byteToChar(byte[] bytes, int offset, int len) + throws CharConversionException + { + try { + String s = new String(bytes, offset, len, "UnicodeBig"); + return s.toCharArray(); + + } catch( UnsupportedEncodingException e ) { + String err = "Unable to find UnicodeBig encoding mechanism"; + Assert.notReached(err); + throw new CharConversionException(err); + } + } + + public byte[] charToByte(char[] chars, int offset, int len) + throws CharConversionException + { + try { + // We don't want the byte-order mark + String s = new String(chars, offset, len); + return s.getBytes("UnicodeBigUnmarked"); + + } catch( UnsupportedEncodingException e ) { + String err = "Unable to find UnicodeBigUnmarked encoding mechanism"; + Assert.notReached(err); + throw new CharConversionException(err); + } + } +} // end of char converter + +} diff --git a/mozilla/security/jss/org/mozilla/jss/asn1/BOOLEAN.java b/mozilla/security/jss/org/mozilla/jss/asn1/BOOLEAN.java new file mode 100644 index 00000000000..8146c20fd35 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/asn1/BOOLEAN.java @@ -0,0 +1,147 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.asn1; + +import java.io.OutputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * An ASN.1 BOOLEAN value. + */ +public class BOOLEAN implements ASN1Value { + + public static final Tag TAG = new Tag(Tag.Class.UNIVERSAL, 1); + public static final Form FORM = Form.PRIMITIVE; + + public Tag getTag() { + return TAG; + } + + private ASN1Header getHeader() { + return getHeader(TAG); + } + + private ASN1Header getHeader(Tag implicitTag) { + return new ASN1Header(implicitTag, FORM, 1 ); + } + + public void encode(OutputStream ostream) throws IOException { + encode(TAG, ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + getHeader(implicitTag).encode(ostream); + if( val ) { + ostream.write( 0xff ); + } else { + ostream.write( 0x00 ); + } + } + + private BOOLEAN() { } + + private boolean val; + /** + * Creates a BOOLEAN with the given value. + */ + public BOOLEAN(boolean val) { + this.val = val; + } + + /** + * Returns the boolean value of this BOOLEAN. + */ + public boolean toBoolean() { + return val; + } + + /** + * Returns "true" or "false". + */ + public String toString() { + if(val) { + return "true"; + } else { + return "false"; + } + } + + private static final Template templateInstance = new Template(); + public static Template getTemplate() { + return templateInstance; + } + + /** + * A Class for decoding BOOLEAN values from their BER + * encodings. + */ + public static class Template implements ASN1Template { + public boolean tagMatch(Tag tag) { + return( tag.equals( BOOLEAN.TAG ) ); + } + + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag tag, InputStream istream) + throws IOException, InvalidBERException + { + try { + ASN1Header head = new ASN1Header(istream); + + head.validate(tag, FORM); + + int b = istream.read(); + if( b == -1 ) { + throw new InvalidBERException("End-of-file reached while "+ + "decoding BOOLEAN"); + } + + if( b == 0x00 ) { + return new BOOLEAN(false); + } else { + return new BOOLEAN(true); + } + + } catch(InvalidBERException e) { + throw new InvalidBERException(e, "BOOLEAN"); + } + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/asn1/CHOICE.java b/mozilla/security/jss/org/mozilla/jss/asn1/CHOICE.java new file mode 100644 index 00000000000..f894956a89a --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/asn1/CHOICE.java @@ -0,0 +1,285 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.asn1; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Vector; +import com.netscape.jss.util.Assert; + +/** + * Objects of this class are generated by CHOICE.Template.decode(). It is + * not necessary to use them to encode a CHOICE. Since the encoding of a + * CHOICE is simply the encoding of the chosen element, it is easier + * to just write out the chosen element. + */ +public class CHOICE implements ASN1Value { + private CHOICE() { } + + private Tag tag; + private ASN1Value val; + + /** + * Create a CHOICE whose chosen element has an implicit tag. + */ + public CHOICE(Tag implicitTag, ASN1Value val) { + tag = implicitTag; + this.val = val; + } + + /** + * Create a CHOICE whose chosen element has no implicit tag. + */ + public CHOICE(ASN1Value val) { + this.tag = val.getTag(); + this.val = val; + } + + /** + * Returns the tag that the chosen element is encoded with, which is + * either the underlying tag of the element or an implicit tag. + */ + public Tag getTag() { + return tag; + } + + /** + * Returns the chosen value. + */ + public ASN1Value getValue() { + return val; + } + + public static CHOICE.Template getTemplate() { + return new CHOICE.Template(); + } + + /** + * Encodes this CHOICE. This merely consists of encoding the chosen + * element with an implicit tag, if one was given in the constructor, + * or with its own underlying tag. + */ + public void encode( OutputStream ostream ) throws IOException { + val.encode( tag, ostream ); + } + + /** + * Encodes this CHOICE. This merely consists of encoding the chosen + * element with an implicit tag, if one was given in the constructor, + * or with its own underlying tag. + * + * @param implicitTag This value is ignored. The tag of a CHOICE + * is merely the tag of the chosen element of the CHOICE. A + * CHOICE cannot itself have an implicit tag. + */ + public void encode( Tag implicitTag, OutputStream ostream ) + throws IOException + { + Assert.assert(implicitTag.equals(tag)); + val.encode( tag, ostream ); + } + +/** + * A Template for decoding ASN.1 CHOICEs + */ +public static class Template implements ASN1Template { + + // The the various possibilities in this CHOICE + private Vector templates = new Vector(); + + /** + * Creates an empty CHOICE template + */ + public Template() { } + + /** + * Adds a new sub-template to this CHOICE template with no implicit tag. + */ + public void addElement( ASN1Template template ) { + templates.addElement( new Element( template ) ); + } + + /** + * Adds a new sub-template to this CHOICE template with an implicit tag. + */ + public void addElement( Tag implicitTag, ASN1Template template) { + templates.addElement( new Element( implicitTag, template) ); + } + + /** + * Returns the number of elements in this CHOICE template. + */ + public int size() { + return templates.size(); + } + + /** + * Retrieves the element at the specified index. + */ + public ASN1Template elementAt(int index) { + return ((Element)templates.elementAt(index)).getTemplate(); + } + + /** + * Retrieves the implicit tag of the element at the specified index. + * Returns null if there is no implicit tag for this element. + */ + public Tag implicitTagAt(int index) { + return ((Element)templates.elementAt(index)).getImplicitTag(); + } + + /** + * Empties this CHOICE template. + */ + public void removeAllElements() { + templates.removeAllElements(); + } + + /** + * Removes the element at the specified index. + */ + public void removeElementAt(int index) { + templates.removeElementAt(index); + } + + /** + * Determines whether the given tag will satisfy this template. + * For a CHOICE, this is true if the tag satisfies any sub-template. + */ + public boolean tagMatch(Tag t) { + int size = size(); + for(int i = 0; i < size; i++) { + Tag impl = implicitTagAt(i); + if( impl != null ) { + // There is an implicit tag, if we match it we have a match + if( impl.equals(t) ) { + return true; + } + } else { + // no implicit tag, look at the sub-template itself + ASN1Template templ = elementAt(i); + if( templ.tagMatch(t) ) { + return true; + } + } + } + + // none of the elements matched + return false; + } + + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + ASN1Header head = ASN1Header.lookAhead(istream); + Tag tag = head.getTag(); + + // Loop over all the elements of the CHOICE template until we + // find one with a matching tag. + int size = size(); + for(int i=0; i < size; i++) { + if( implicitTagAt(i) != null ) { + if( implicitTagAt(i).equals(tag) ) { + // match by implicit tag! + ASN1Value val = elementAt(i).decode( implicitTagAt(i), + istream ); + //return elementAt(i).decode( implicitTagAt(i), istream ); + return new CHOICE( implicitTagAt(i), val ); + } + } else { + if( elementAt(i).tagMatch(tag) ) { + // match by base tag ! + //return elementAt(i).decode(istream); + return new CHOICE( elementAt(i).decode(istream) ); + } + } + } + + // we didn't find any match + throw new InvalidBERException("Unable to decode CHOICE"); + } + + // Implicit tags are illegal for CHOICE (and ANY) + /** + * Decodes a CHOICE. + * @param implicitTag This parameter is ignored. A choice + * cannot have an implicit tag. + */ + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws IOException, InvalidBERException + { + return decode(istream); + } + + /** + * An element in a CHOICE template, consisting of a nested template + * and, optionally, an implicit tag for that template. + */ + private static class Element { + private ASN1Template template; + private Tag implicitTag=null; + + /** + * Creates a CHOICE template element with no implicit tag. + */ + public Element(ASN1Template template) { + this.template = template; + } + + /** + * Creates a CHOICE template element with an implicit tag. + */ + public Element(Tag implicitTag, ASN1Template template) { + this.template = template; + this.implicitTag = implicitTag; + } + + /** + * Returns the template of this CHOICE template element. + */ + public ASN1Template getTemplate() { + return template; + } + + /** + * Returns the implicit tag for this CHOICE template element, + * if there is one. If not, returns null. + */ + public Tag getImplicitTag() { + return implicitTag; + } + } +} + +} diff --git a/mozilla/security/jss/org/mozilla/jss/asn1/CharConverter.java b/mozilla/security/jss/org/mozilla/jss/asn1/CharConverter.java new file mode 100644 index 00000000000..c64a400b4f1 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/asn1/CharConverter.java @@ -0,0 +1,45 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.asn1; + +import java.io.CharConversionException; + +interface CharConverter { + + public char[] byteToChar(byte[] bytes, int offset, int len) + throws CharConversionException; + + public byte[] charToByte(char[] chars, int offset, int len) + throws CharConversionException; + +} diff --git a/mozilla/security/jss/org/mozilla/jss/asn1/CharacterString.java b/mozilla/security/jss/org/mozilla/jss/asn1/CharacterString.java new file mode 100644 index 00000000000..9cba7463596 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/asn1/CharacterString.java @@ -0,0 +1,185 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.asn1; + +import java.io.CharConversionException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; +import java.io.ByteArrayOutputStream; + +/** + * An abstract base class for all character string types in ASN.1. + */ +public abstract class CharacterString implements ASN1Value { + + abstract CharConverter getCharConverter(); + + public abstract Tag getTag(); + static final Form FORM = Form.PRIMITIVE; + + private char[] chars; + + /** + * Converts this ASN.1 character string to a Java String. + */ + public String toString() { + return new String(chars); + } + + /** + * Converts this ASN.1 character string to an array of Java characters. + */ + public char[] toCharArray() { + return chars; + } + + protected CharacterString(char[] chars) throws CharConversionException { + this.chars = chars; + cachedContents = computeContents(); + } + + protected CharacterString(String s) throws CharConversionException { + this.chars = s.toCharArray(); + cachedContents = computeContents(); + } + + private byte[] cachedContents; + + private byte[] getEncodedContents() { + return cachedContents; + } + + private byte[] computeContents() throws CharConversionException { + CharConverter converter = getCharConverter(); + + byte[] contents = converter.charToByte(chars, 0, chars.length); + + return contents; + } + + public void encode(OutputStream ostream) throws IOException { + encode( getTag(), ostream ); + } + + public void encode( Tag implicitTag, OutputStream ostream ) + throws IOException + { + byte[] contents = getEncodedContents(); + ASN1Header head = new ASN1Header( implicitTag, FORM, contents.length); + + head.encode(ostream); + + ostream.write( contents ); + } + +public abstract static class Template implements ASN1Template { + + /** + * Must be overridden to return the tag for the subclass. + */ + protected abstract Tag getTag(); + + public abstract boolean tagMatch(Tag tag); + + /** + * Must be overridden to return the correct character converter + * for the subclass. + */ + protected abstract CharConverter getCharConverter(); + + /** + * Must be overridden to create an instance of the subclass given + * a char array. + */ + protected abstract CharacterString generateInstance(char[] chars) + throws CharConversionException; + + /** + * Must be overridden to provide the name of the subclass, for including + * into error messages. + */ + protected abstract String typeName(); + + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + return decode(getTag(), istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws IOException, InvalidBERException + { + try { + ASN1Header head = new ASN1Header(istream); + + head.validate(implicitTag); + + byte[] raw; // raw bytes, not translated to chars yet + + if( head.getContentLength() == -1 ) { + // indefinite length encoding + ASN1Header ahead; + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + do { + ahead = ASN1Header.lookAhead( istream ); + if( ! ahead.isEOC() ) { + OCTET_STRING.Template ot = new OCTET_STRING.Template(); + OCTET_STRING os = (OCTET_STRING) ot.decode(istream); + bos.write( os.toByteArray() ); + } + } while( ! ahead.isEOC() ); + + // consume EOC + ahead = new ASN1Header(istream); + + raw = bos.toByteArray(); + } else { + // definite length + raw = new byte[ (int) head.getContentLength() ]; + ASN1Util.readFully(raw, istream); + } + + char[] chars = getCharConverter().byteToChar(raw, 0, raw.length); + + return generateInstance(chars); + + } catch( CharConversionException e ) { + throw new InvalidBERException(e.getMessage()); + } catch( InvalidBERException e ) { + throw new InvalidBERException(e, typeName()); + } + } +} + +} diff --git a/mozilla/security/jss/org/mozilla/jss/asn1/CountingStream.java b/mozilla/security/jss/org/mozilla/jss/asn1/CountingStream.java new file mode 100644 index 00000000000..c4d38da32d0 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/asn1/CountingStream.java @@ -0,0 +1,134 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.asn1; + +import java.io.*; + +/** + * This class keeps track of the number of bytes that have been read from + * a stream. It will be incremented by the number of bytes read or skipped. + * If the stream is marked and then reset, the number of bytes read will + * be reset as well. + */ +class CountingStream extends InputStream { + + private int count=0; + private int markpos; + private InputStream source; + + private static final boolean DEBUG = false; + + private CountingStream() { } + + public CountingStream(InputStream source) { + this.source = source; + } + + public int available() throws IOException { + return source.available(); + } + + public void mark(int readlimit) { + source.mark(readlimit); + markpos = count; + if(DEBUG) { + System.out.println("Marked at position "+markpos); + } + } + + public boolean markSupported() { + return source.markSupported(); + } + + public int read() throws IOException { + int n = source.read(); + if( n != -1 ) { + count++; + if(DEBUG) { + System.out.println("read() 1 byte, count="+count); + } + } + return n; + } + + public int read(byte[] buffer) throws IOException { + int n = source.read(buffer); + if( n != -1 ) { + count += n; + } + if(DEBUG) { + System.out.println("read([]) "+n+" bytes, count="+count); + } + return n; + } + + public int read(byte[] buffer, int offset, int count) throws IOException { + int n = source.read(buffer, offset, count); + if( n != -1 ) { + this.count += n; + } + if(DEBUG) { + System.out.println("read(...) "+n+" bytes, count="+this.count); + } + return n; + } + + public void reset() throws IOException { + source.reset(); + if(DEBUG) { + System.out.println("reset from "+count+" to "+markpos); + } + count = markpos; + } + + public long skip(long count) throws IOException { + this.count += count; + if(DEBUG) { + System.out.println("skipped "+count+", now at "+this.count); + } + return source.skip(count); + } + + public int getNumRead() { + return count; + } + + public void resetNumRead() { + count = 0; + markpos = 0; + if(DEBUG) { + System.out.println("resetting count to 0"); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/asn1/ENUMERATED.java b/mozilla/security/jss/org/mozilla/jss/asn1/ENUMERATED.java new file mode 100644 index 00000000000..7c2db309db2 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/asn1/ENUMERATED.java @@ -0,0 +1,107 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.asn1; + +import java.io.IOException; +import java.io.InputStream; + +/** + * Represents an ASN.1 ENUMERATED value. This has the same + * interface as INTEGER + */ +public class ENUMERATED extends INTEGER implements ASN1Value { + + public static final Tag TAG = new Tag(Tag.Class.UNIVERSAL, 10); + public Tag getTag() { + return TAG; + } + + /** + * Creates a new ENUMERATED value from a long. + */ + public ENUMERATED( long val ) { + super( val ); + } + + ENUMERATED( byte[] valBytes ) { + super( valBytes ); + } + + /** + * Returns the value as a long. + */ + public long getValue() { + return longValue(); + } + +/** + * A template for decoding ENUMERATED values from their BER encodings. + * The template reads the value as an INTEGER. It does not check that it + * is a valid value for the ENUMERATED type. + */ +public static class Template + extends INTEGER.Template implements ASN1Template +{ + Tag getTag() { + return ENUMERATED.TAG; + } + public boolean tagMatch(Tag tag) { + return( tag.equals(ENUMERATED.TAG) ); + } + + public ASN1Value + decode(Tag tag, InputStream derStream) + throws InvalidBERException, IOException + { + try { + ASN1Header wrapper = new ASN1Header(derStream); + + wrapper.validate(tag, FORM); + + // Is length < 1 ? + if( wrapper.getContentLength() < 1 ) { + throw new InvalidBERException("Invalid 0 length for ENUMERATED"); + } + + byte[] valBytes = new byte[ (int) wrapper.getContentLength() ]; + ASN1Util.readFully(valBytes, derStream); + return new ENUMERATED( valBytes ); + + } catch(InvalidBERException e) { + throw new InvalidBERException(e, "ENUMERATED"); + } + } + +} // end of Template + +} diff --git a/mozilla/security/jss/org/mozilla/jss/asn1/EXPLICIT.java b/mozilla/security/jss/org/mozilla/jss/asn1/EXPLICIT.java new file mode 100644 index 00000000000..3a8def58967 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/asn1/EXPLICIT.java @@ -0,0 +1,175 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.asn1; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.ByteArrayOutputStream; +import com.netscape.jss.util.Assert; + +/** + * An explicit tag. + */ +public class EXPLICIT implements ASN1Value { + + public static final Form FORM = Form.CONSTRUCTED; + + private ASN1Value content; + private Tag tag; + + private EXPLICIT() { } + + /** + * Creates an EXPLICIT tag wrapping some other ASN1Value. For example, + * for the following ASN.1 snippet: + *

+     * MyType [3] EXPLICIT INTEGER
+     * 
+ * assuming a sample value of 5 for the INTEGER, a MyType could be + * created with: + *
+     *  EXPLICIT myValue = new EXPLICIT( new Tag(3), new INTEGER(5) );
+     * 
+ */ + public EXPLICIT( Tag tag, ASN1Value content ) { + Assert.assert(tag!=null && content!=null); + this.content = content; + this.tag = tag; + } + + /** + * Returns the ASN1Value that is wrapped by this EXPLICIT tag. + */ + public ASN1Value getContent() { + return content; + } + + /** + * Returns the Tag of this EXPLICIT tag. + */ + public Tag getTag() { + return tag; + } + + public void encode(OutputStream ostream) throws IOException { + encode(tag, ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + content.encode(bos); + byte[] contentBytes = bos.toByteArray(); + ASN1Header head = new ASN1Header(implicitTag, FORM, + contentBytes.length ); + head.encode(ostream); + ostream.write(contentBytes); + } + + public static Template getTemplate( Tag tag, ASN1Template content) { + return new Template(tag, content); + } + +/** + * A template for decoding an object wrapped in an EXPLICIT tag. + */ +public static class Template implements ASN1Template { + + private ASN1Template content; + private Tag tag; + + private Template() { } + + /** + * Creates a template for unwrapping an object wrapped in an explicit tag. + * For example, to decode: + *
+     * MyValue ::= [3] EXPLICIT INTEGER
+     * 
+ * use: + *
+     * EXPLICIT.Template myTemplate = new EXPLICIT.Template( new Tag(3),
+     *      new INTEGER.Template() );
+     * 
+ * + * @param tag The tag value of the EXPLICIT tag. + * @param content The template for decoding the object that is wrapped + * in the explicit tag. + */ + public Template(Tag tag, ASN1Template content) { + this.content = content; + this.tag = tag; + } + + public boolean tagMatch(Tag tag) { + return( this.tag.equals(tag) ); + } + + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + return decode(tag, istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws IOException, InvalidBERException + { + try { + ASN1Header head = new ASN1Header(istream); + + head.validate( implicitTag, FORM.CONSTRUCTED ); + + ASN1Value val = content.decode(istream); + + EXPLICIT e = new EXPLICIT(tag, val); + + // if indefinite content length, consume the end-of-content marker + if( head.getContentLength() == -1 ) { + head = new ASN1Header(istream); + + if( ! head.isEOC() ) { + throw new InvalidBERException("No end-of-contents marker"); + } + } + + return e; + + } catch(InvalidBERException e) { + throw new InvalidBERException(e, "EXPLICIT"); + } + } +} // end of Template + +} diff --git a/mozilla/security/jss/org/mozilla/jss/asn1/FieldNotPresentException.java b/mozilla/security/jss/org/mozilla/jss/asn1/FieldNotPresentException.java new file mode 100644 index 00000000000..3ef0aa96bf9 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/asn1/FieldNotPresentException.java @@ -0,0 +1,48 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.asn1; + +/** + * An exception thrown when an optional field is not present. + */ +public class FieldNotPresentException extends java.lang.Exception +{ + public FieldNotPresentException() { + super(); + } + + public FieldNotPresentException(String msg) { + super(msg); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/asn1/Form.java b/mozilla/security/jss/org/mozilla/jss/asn1/Form.java new file mode 100644 index 00000000000..b620533e9fb --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/asn1/Form.java @@ -0,0 +1,54 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.asn1; + +/** + * An enumerated type representing the forms of an ASN.1 value. + * The possibilities are PRIMITIVE and CONSTRUCTED. + */ +public class Form { + private String name; + + private Form() { } + + private Form(String name) { + this.name = name; + } + + public static final Form PRIMITIVE = new Form("PRIMITIVE"); + public static final Form CONSTRUCTED = new Form("CONSTRUCTED"); + + public String toString() { + return name; + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/asn1/GeneralizedTime.java b/mozilla/security/jss/org/mozilla/jss/asn1/GeneralizedTime.java new file mode 100644 index 00000000000..d6514461bc5 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/asn1/GeneralizedTime.java @@ -0,0 +1,92 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.asn1; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; +import java.util.Calendar; +import java.util.Date; +import java.util.TimeZone; +import com.netscape.jss.util.Assert; + +/** + * The ASN.1 type GeneralizedTime + */ +public class GeneralizedTime extends TimeBase implements ASN1Value { + + public static final Tag TAG = new Tag(Tag.UNIVERSAL, 24); + public Tag getTag() { + return TAG; + } + + /** + * Creates a GeneralizedTime from a Date. + */ + public GeneralizedTime(Date date) { + super(date); + } + + protected boolean isUTC() { + return false; + } + + private static final GeneralizedTime.Template templateInstance = + new GeneralizedTime.Template(); + public static GeneralizedTime.Template getTemplate() { + return templateInstance; + } + + /** + * A class for decoding GeneralizedTimes. + */ + public static class Template extends TimeBase.Template + implements ASN1Template + { + protected Tag getTag() { + return TAG; + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + protected boolean isUTC() { + return false; + } + + protected TimeBase generateInstance(Date date) { + return new GeneralizedTime(date); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/asn1/IA5String.java b/mozilla/security/jss/org/mozilla/jss/asn1/IA5String.java new file mode 100644 index 00000000000..67a880d69d4 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/asn1/IA5String.java @@ -0,0 +1,127 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.asn1; + +import java.io.CharConversionException; + +public class IA5String extends CharacterString implements ASN1Value { + + public IA5String(char[] chars) throws CharConversionException { + super(chars); + } + + public IA5String(String s) throws CharConversionException { + super(s); + } + + CharConverter getCharConverter() { + return new IA5Converter(); + } + + public static final Tag TAG = new Tag( Tag.Class.UNIVERSAL, 22 ); + + public Tag getTag() { + return TAG; + } + + public static Template getTemplate() { + return templateInstance; + } + private static final Template templateInstance = new Template(); + +// nested class +public static class Template + extends CharacterString.Template implements ASN1Template +{ + public Tag getTag() { + return IA5String.TAG; + } + public boolean tagMatch(Tag tag) { + return( tag.equals( IA5String.TAG )); + } + + protected CharConverter getCharConverter() { + return new IA5Converter(); + } + + protected CharacterString generateInstance(char[] chars) + throws CharConversionException + { + return new IA5String(chars); + } + + protected String typeName() { + return "IA5String"; + } +} + +// nested class +private static class IA5Converter implements CharConverter { + + public char[] byteToChar(byte[] bytes, int offset, int len) + throws CharConversionException + { + char[] chars = new char[len]; + + int c; // char index + int b; // byte index + for(b = offset, c=0; c < len; b++, c++) { + if( (bytes[b] & 0x80) != 0 ) { + throw new CharConversionException("Invalid character: "+ + bytes[b]); + } + chars[c] = (char) (bytes[b] & 0x7f); + } + return chars; + } + + public byte[] charToByte(char[] chars, int offset, int len) + throws CharConversionException + { + byte[] bytes = new byte[len]; + + int c; // char index + int b; // byte index + for(c = offset, b = 0; b < len; c++, b++) { + if( (chars[c] & 0x7f) != chars[c] ) { + throw new CharConversionException("Invalid character: "+ + chars[c]); + } + bytes[b] = (byte) (chars[c] & 0x7f); + } + + return bytes; + } +} + +} diff --git a/mozilla/security/jss/org/mozilla/jss/asn1/INTEGER.java b/mozilla/security/jss/org/mozilla/jss/asn1/INTEGER.java new file mode 100644 index 00000000000..fb290b7af9c --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/asn1/INTEGER.java @@ -0,0 +1,250 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.asn1; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.InputStream; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.math.BigInteger; +import java.util.Random; + +/** + * The ASN.1 type INTEGER. This class extends BigInteger. + */ +public class INTEGER extends BigInteger implements ASN1Value { + + private byte[] encodedContents = null; + private byte[] getEncodedContents() { + if( encodedContents == null ) { + encodedContents = toByteArray(); + } + return encodedContents; + } + + private ASN1Header getHeader(Tag t) { + return new ASN1Header( t, FORM, getContentLength() ); + } + + public INTEGER(String s) throws NumberFormatException { + super(s); + } + + public INTEGER(String s, int r) throws NumberFormatException { + super(s, r); + } + + public INTEGER(byte[] bval) throws NumberFormatException { + super(bval); + } + + public INTEGER(int sign, byte[] mag) throws NumberFormatException { + super(sign, mag); + } + + public INTEGER(int numBits, Random rnd) throws NumberFormatException { + super(numBits, rnd); + } + + public INTEGER(int bitLength, int certainty, Random rnd) { + super(bitLength, certainty, rnd); + } + + public INTEGER(long val) { + super( BigInteger.valueOf(val).toByteArray() ); + } + + public static final Tag TAG = new Tag(Tag.Class.UNIVERSAL, 2); + public Tag getTag() { + return TAG; + } + public static final Form FORM = Form.PRIMITIVE; + + public void encode(OutputStream outStream) throws IOException { + encode(getTag(), outStream); + } + + public void encode(Tag implicitTag, OutputStream outStream) + throws IOException + { + // write header + getHeader(implicitTag).encode( outStream ); + + // write contents + outStream.write( getEncodedContents() ); + } + + public long getContentLength() { + return getEncodedContents().length; + } + + public byte[] encode() throws IOException { + ByteArrayOutputStream b = new ByteArrayOutputStream(); + encode(b); + return b.toByteArray(); + } + + private static final INTEGER.Template templateInstance = + new INTEGER.Template(); + public static ASN1Template getTemplate() { + return templateInstance; + } + + /** + * Tests the DER encoding and decoding of the INTEGER class. + */ + public static void main(String args[]) { + try { + int[] Is = new int[11]; + int[][] Bs = new int[11][]; + int i = 0; + + Is[i] = 0; + Bs[i++] = new int[]{ 0x02, 0x01, 0x00 }; + + Is[i] = 1; + Bs[i++] = new int[]{ 0x02, 0x01, 0x01 }; + + Is[i] = -1; + Bs[i++] = new int[]{ 0x02, 0x01, 0xff }; + + Is[i] = 127; + Bs[i++] = new int[]{ 0x02, 0x01, 0x7f }; + + Is[i] = 128; + Bs[i++] = new int[]{ 0x02, 0x02, 0x00, 0x80 }; + + Is[i] = 255; + Bs[i++] = new int[]{ 0x02, 0x02, 0x00, 0xff }; + + Is[i] = 256; + Bs[i++] = new int[]{ 0x02, 0x02, 0x01, 0x00 }; + + Is[i] = -128; + Bs[i++] = new int[]{ 0x02, 0x01, 0x80 }; + + Is[i] = -129; + Bs[i++] = new int[]{ 0x02, 0x02, 0xff, 0x7f }; + + Is[i] = 43568; + Bs[i++] = new int[]{ 0x02, 0x03, 0x00, 0xaa, 0x30 }; + + Is[i] = -43568; + Bs[i++] = new int[]{ 0x02, 0x03, 0xff, 0x55, 0xd0 }; + + for( i = 0; i < Is.length; i++) { + INTEGER I = new INTEGER( Is[i] ); + byte[] compare = I.encode(); + if( ! arraysEqual(compare, Bs[i]) ) { + System.err.println("Encoding FAILED: "+Is[i]); + System.exit(-1); + } + + ByteArrayInputStream bis = new ByteArrayInputStream(compare); + Template template = new Template(); + INTEGER create = (INTEGER) template.decode(bis); + if( create.intValue() != Is[i] ) { + System.err.println("Decoding FAILED: "+Is[i]); + System.exit(-1); + } + } + System.out.println("PASS"); + + } catch( Exception e ) { + e.printStackTrace(); + } + } + + private static boolean arraysEqual(byte[] bytes, int[] ints) { + if(bytes == null || ints == null) { + return false; + } + + if(bytes.length != ints.length) { + return false; + } + + for( int i=0; i < bytes.length; i++) { + if( bytes[i] != (byte)ints[i] ) { + return false; + } + } + return true; + } + +/////////////////////////////////////////////////////////////////////// +// INTEGER.Template +// This is a nested class. +// +public static class Template implements ASN1Template { + + Tag getTag() { + return INTEGER.TAG; + } + public boolean tagMatch(Tag tag) { + return( tag.equals(INTEGER.TAG)); + } + + public ASN1Value + decode(InputStream derStream) + throws InvalidBERException, IOException + { + return decode( getTag(), derStream ); + } + + public ASN1Value + decode(Tag tag, InputStream derStream) + throws InvalidBERException, IOException + { + try { + ASN1Header wrapper = new ASN1Header(derStream); + + wrapper.validate(tag, FORM); + + // Is length < 1 ? + if( wrapper.getContentLength() < 1 ) { + throw new InvalidBERException("Invalid 0 length for INTEGER"); + } + + byte[] valBytes = new byte[ (int) wrapper.getContentLength() ]; + ASN1Util.readFully(valBytes, derStream); + return new INTEGER( valBytes ); + + } catch(InvalidBERException e) { + throw new InvalidBERException(e, "INTEGER"); + } + } +} // end of class Template + +} diff --git a/mozilla/security/jss/org/mozilla/jss/asn1/InvalidBERException.java b/mozilla/security/jss/org/mozilla/jss/asn1/InvalidBERException.java new file mode 100644 index 00000000000..350a3d29d56 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/asn1/InvalidBERException.java @@ -0,0 +1,89 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.asn1; + +/** + * An exception thrown when BER decoding fails. + */ +public class InvalidBERException extends java.lang.Exception { + + private InvalidBERException child=null; + + public InvalidBERException(String mesg) { + super(mesg); + } + + public InvalidBERException(InvalidBERException e, String mesg) { + super(mesg); + child = e; + } + + /** + * Prints out the exception class and error message, including + * all the nested exceptions. + */ + public String toString() { + if(child != null) { + return (super.toString()+ " >> " + child.toStringNested()); + } else { + return super.toString(); + } + } + + /** + * Prints out the error message of this exception, including all the + * nested exceptions. + */ + public String toStringNested() { + if(child != null) { + return ( getMessage() + " >> " + child.toStringNested()); + } else { + return getMessage(); + } + } + + public static class EOF extends InvalidBERException { + public EOF() { + super("Unexpected end-of-file encountered"); + } + } + + public static class InvalidChar extends InvalidBERException { + public InvalidChar(byte b, int offset) { + super("Invalid character ("+b+") encountered at offset "+offset); + } + public InvalidChar(char c, int offset) { + super("Invalid character ("+c+") encountered at offset"+offset); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/asn1/Makefile b/mozilla/security/jss/org/mozilla/jss/asn1/Makefile new file mode 100644 index 00000000000..98d1f72faa9 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/asn1/Makefile @@ -0,0 +1,79 @@ +#! gmake +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +####################################################################### +# (1) Include initial platform-independent assignments (MANDATORY). # +####################################################################### + +include manifest.mn + +####################################################################### +# (2) Include "global" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/config.mk + +####################################################################### +# (3) Include "component" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/$(MODULE)/config/config.mk + + +####################################################################### +# (4) Include "local" platform-dependent assignments (OPTIONAL). # +####################################################################### +#include config.mk + + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### + + + +run: + $(DEBUG_CMD) /share/builds/components/jdk/1.2.2_05a/SunOS/jre/bin/java -classpath $(JAVA_HOME)/lib/classes.zip:$(SOURCE_CLASSES_DIR)_DBG com.netscape.jss.asn1.SEQUENCE /tmp/p10 + diff --git a/mozilla/security/jss/org/mozilla/jss/asn1/NULL.java b/mozilla/security/jss/org/mozilla/jss/asn1/NULL.java new file mode 100644 index 00000000000..09719f0967b --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/asn1/NULL.java @@ -0,0 +1,103 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.asn1; + +import java.io.OutputStream; +import java.io.InputStream; +import java.io.IOException; + +public class NULL implements ASN1Value { + + public static final Tag TAG = new Tag(Tag.Class.UNIVERSAL, 5); + public Tag getTag() { + return TAG; + } + public static final Form FORM = Form.PRIMITIVE; + + public void encode(OutputStream ostream) throws IOException { + encode(TAG, ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + ASN1Header head = new ASN1Header(implicitTag, FORM, 0); + head.encode(ostream); + } + + private static final NULL instance = new NULL(); + public static NULL getInstance() { + return instance; + } + + private static final Template templateInstance = new Template(); + public static Template getTemplate() { + return templateInstance; + } + +public static class Template implements ASN1Template { + + public Tag getTag() { + return NULL.TAG; + } + public boolean tagMatch(Tag tag) { + return( tag.equals(NULL.TAG) ); + } + + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + return decode(getTag(), istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws IOException, InvalidBERException + { + try { + ASN1Header head = new ASN1Header(istream); + + head.validate(implicitTag, FORM); + if( head.getContentLength() != 0 ) { + throw new InvalidBERException("Invalid length ("+ + head.getContentLength()+") for NULL; only 0 is permitted"); + } + + return new NULL(); + + } catch(InvalidBERException e) { + throw new InvalidBERException(e, "NULL"); + } + } +} // end of Template + +} diff --git a/mozilla/security/jss/org/mozilla/jss/asn1/OBJECT_IDENTIFIER.java b/mozilla/security/jss/org/mozilla/jss/asn1/OBJECT_IDENTIFIER.java new file mode 100644 index 00000000000..5a02b2a5514 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/asn1/OBJECT_IDENTIFIER.java @@ -0,0 +1,514 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.asn1; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import com.netscape.jss.util.Assert; +import java.util.Vector; +import java.util.StringTokenizer; + +public class OBJECT_IDENTIFIER implements ASN1Value { + + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + // Standard object identifiers + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + + /** + * The OID space for RSA Data Security, Inc. + */ + public static final OBJECT_IDENTIFIER RSADSI = + new OBJECT_IDENTIFIER( new long[]{1, 2, 840, 113549} ); + + /** + * The OID space for RSA's PKCS (public key cryptography standards). + */ + public static final OBJECT_IDENTIFIER PKCS = + RSADSI.subBranch(1); + + /** + * The OID space for RSA's PKCS #1. + */ + public static final OBJECT_IDENTIFIER PKCS1 = + PKCS.subBranch(1); + + /** + * The OID space for RSA's PKCS #2, which has since been folded into + * PKCS #1. + */ + public static final OBJECT_IDENTIFIER PKCS2 = + PKCS.subBranch(2); + + /** + * The OID space for RSA's message digest algorithms. + */ + public static final OBJECT_IDENTIFIER RSA_DIGEST = RSADSI.subBranch(2); + + /** + * The OID space for RSA's password-based encryption standard. + */ + public static final OBJECT_IDENTIFIER PKCS5 = PKCS.subBranch(5); + + /** + * The OID space for RSA's Selected Attribute Types standard, PKCS #9. + */ + public static final OBJECT_IDENTIFIER PKCS9 = PKCS.subBranch(9); + + /** + * The OID space for RSA's personal information exchange syntax standard. + */ + public static final OBJECT_IDENTIFIER PKCS12 = PKCS.subBranch(12); + + /** + * The OID space for RSA's ciphers. + */ + public static final OBJECT_IDENTIFIER RSA_CIPHER = RSADSI.subBranch(3); + + /** + * The OID space for FIPS standardized algorithms. + */ + public static final OBJECT_IDENTIFIER ALGORITHM = + new OBJECT_IDENTIFIER( new long[] { 1, 3, 14, 3, 2 } ); + + /** + * The OID space for PKIX. + */ + public static final OBJECT_IDENTIFIER PKIX = + new OBJECT_IDENTIFIER( new long[] { 1, 3, 6, 1, 5, 5, 7 } ); + + public static final OBJECT_IDENTIFIER + id_cmc = PKIX.subBranch( 7 ); + + /** + * CMC control attributes + */ + public static final OBJECT_IDENTIFIER + id_cmc_cMCStatusInfo = id_cmc.subBranch(1); + public static final OBJECT_IDENTIFIER + id_cmc_identification = id_cmc.subBranch(2); + public static final OBJECT_IDENTIFIER + id_cmc_identityProof = id_cmc.subBranch(3); + public static final OBJECT_IDENTIFIER + id_cmc_dataReturn = id_cmc.subBranch(4); + public static final OBJECT_IDENTIFIER + id_cmc_transactionId = id_cmc.subBranch(5); + public static final OBJECT_IDENTIFIER + id_cmc_senderNonce = id_cmc.subBranch(6); + public static final OBJECT_IDENTIFIER + id_cmc_recipientNonce = id_cmc.subBranch(7); + public static final OBJECT_IDENTIFIER + id_cmc_addExtensions = id_cmc.subBranch(8); + public static final OBJECT_IDENTIFIER + id_cmc_encryptedPOP = id_cmc.subBranch(9); + public static final OBJECT_IDENTIFIER + id_cmc_decryptedPOP = id_cmc.subBranch(10); + public static final OBJECT_IDENTIFIER + id_cmc_lraPOPWitness = id_cmc.subBranch(11); + public static final OBJECT_IDENTIFIER + id_cmc_getCert = id_cmc.subBranch(15); + public static final OBJECT_IDENTIFIER + id_cmc_getCRL = id_cmc.subBranch(16); + public static final OBJECT_IDENTIFIER + id_cmc_revokeRequest = id_cmc.subBranch(17); + public static final OBJECT_IDENTIFIER + id_cmc_regInfo = id_cmc.subBranch(18); + public static final OBJECT_IDENTIFIER + id_cmc_responseInfo = id_cmc.subBranch(19); + public static final OBJECT_IDENTIFIER + id_cmc_QueryPending = id_cmc.subBranch(21); + public static final OBJECT_IDENTIFIER + id_cmc_idPOPLinkRandom = id_cmc.subBranch(22); + public static final OBJECT_IDENTIFIER + id_cmc_idPOPLinkWitness = id_cmc.subBranch(23); + public static final OBJECT_IDENTIFIER + id_cmc_idConfirmCertAcceptance = id_cmc.subBranch(24); + + public static final OBJECT_IDENTIFIER + id_cct = PKIX.subBranch( 12 ); + + public static final OBJECT_IDENTIFIER + id_cct_PKIData = id_cct.subBranch( 2 ); + + public static final OBJECT_IDENTIFIER + id_cct_PKIResponse = id_cct.subBranch( 3 ); + + + public static final Tag TAG = new Tag(Tag.Class.UNIVERSAL, 6); + public Tag getTag() { + return TAG; + } + public static final Form FORM = Form.PRIMITIVE; + + private long[] numbers; + + /** + * Creates an OBJECT_IDENTIFIER from an array of longs, which constitute + * the numbers that make up the OBJECT IDENTIFIER. + */ + public OBJECT_IDENTIFIER( long[] numbers ) { + checkLongArray(numbers); + this.numbers = numbers; + } + + /** + * Checks the given array of numbers to see if it is a valid OID. + * This is not an exhaustive test, it just looks for obvious problems. + * It will throw an assertion if a problem is found. With DEBUG turned + * off, it just checks for null. + */ + private static void checkLongArray(long[] numbers) { + Assert.assert(numbers != null); + if(numbers == null) { + throw new NullPointerException(); + } + Assert.assert(numbers.length >= 2); + Assert.assert( numbers[0]==0 || numbers[0]==1 || numbers[0]==2 ); + } + + + /** + * Creates an OBJECT_IDENTIFIER from a String version. The proper format + * for the OID string is dotted numbers, for example: + * "3.2.456.53.23.64". + * + * @exception NumberFormatException If the given string cannot be + * parsed into an OID. + */ + public OBJECT_IDENTIFIER( String dottedOID ) throws NumberFormatException { + + if( dottedOID == null || dottedOID.length()==0 ) { + throw new NumberFormatException("OID string is zero-length"); + } + + StringTokenizer stok = new StringTokenizer(dottedOID, "."); + numbers = new long[ stok.countTokens() ]; + int i = 0; + while(stok.hasMoreElements()) { + numbers[i++] = Long.parseLong( stok.nextToken() ); + } + Assert.assert( i == numbers.length ); + checkLongArray(numbers); + } + + public long[] getNumbers() { + return numbers; + } + + public int hashCode() { + int code = 1; + for(int i = 0; i < numbers.length; i++) { + code = (int) (code + numbers[i])*10; + } + return code; + } + + /** + * Creates a new OBJECT_IDENTIFIER that is a sub-branch of this one. + * For example, if OBJECT_IDENTIFIER oid has the value + * { 1 3 5 6 }, + * then calling oid.subBranch(4) would return a new + * OBJECT_IDENTIFIER with the value { 1 3 5 6 4 }. + */ + public OBJECT_IDENTIFIER subBranch(long num) { + long[] nums = new long[ numbers.length + 1]; + System.arraycopy(numbers, 0, nums, 0, numbers.length); + nums[numbers.length] = num; + return new OBJECT_IDENTIFIER(nums); + } + + /** + * Creates a new OBJECT_IDENTIFIER that is a sub-branch of this one. + * For example, if OBJECT_IDENTIFIER oid has the value + * { 1 3 5 6 }, + * then calling oid.subBranch(new long[]{ 4, 3}) + * would return a new + * OBJECT_IDENTIFIER with the value { 1 3 5 6 4 3}. + */ + public OBJECT_IDENTIFIER subBranch(long[] newNums) { + long[] nums = new long[ numbers.length + newNums.length]; + System.arraycopy(numbers, 0, nums, 0, numbers.length); + System.arraycopy(newNums, 0, nums, numbers.length, newNums.length); + return new OBJECT_IDENTIFIER(nums); + } + + public boolean equals(Object obj) { + if(obj == null || ! (obj instanceof OBJECT_IDENTIFIER)) { + return false; + } + long[] nums = ((OBJECT_IDENTIFIER)obj).numbers; + if( nums.length != numbers.length ) { + return false; + } + for(int i = 0; i < nums.length; i++) { + if( nums[i] != numbers[i] ) { + return false; + } + } + return true; + } + + public String toString() { + String ret = "{" + String.valueOf(numbers[0]); + for(int i=1; i < numbers.length; i++) { + ret = ret + " " + numbers[i]; + } + ret += "}"; + return ret; + } + + public void encode(OutputStream ostream) throws IOException { + encode(TAG, ostream); + } + + private byte[] encodedContents = null; + /** + * Gets the encoding of the contents, or a cached copy. + * Since the content encoding is the same regardless of the Tag, + * this only needs to be computed once. + */ + private byte[] getEncodedContents() { + if( encodedContents == null ) { + encodedContents = computeEncodedContents(); + } + return encodedContents; + } + + // We cache our encoding for a given tag. 99% of the time, only + // one tag will be used for an instance, so we will get a cache hit. + // In the remaining 1%, we'll have to recompute the encoding. + byte[] cachedEncoding=null; + Tag tagForCache=null; + /** + * Returns the encoding for the given tag. If the encoding for + * this tag was previously computed (and no encoding for a different + * tag has since been computed), this method returns a cached copy. + * Otherwise, the encoding will be recomputed. + */ + private byte[] getEncoding(Tag tag) { + if( ! tag.equals(tagForCache) ) { + // recompute for new tag + ByteArrayOutputStream out = new ByteArrayOutputStream(); + + ASN1Header head = getHeader(tag); + try { + head.encode(out); + } catch( IOException e ) { + // should never happen on a byte array output stream + Assert.notReached("exception while encoding ASN.1 header"); + } + + out.write( getEncodedContents(), 0, getEncodedContents().length ); + + tagForCache = tag; + cachedEncoding = out.toByteArray(); + } + return cachedEncoding; + } + + /** + * Compute the ASN1 header for this tag. + */ + private ASN1Header getHeader(Tag implicitTag) { + return new ASN1Header( implicitTag, FORM, getEncodedContents().length ); + } + + /** + * Actually computes the encoding of this object identifier. + */ + private byte[] computeEncodedContents() { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + + // handle first number + Assert.assert(numbers.length >= 2); + long n = numbers[0]; + Assert.assert( n == 0 || n == 1 || n == 2 ); + long outb = ( numbers[0] * 40 ) + numbers[1]; + Assert.assert( ((byte)outb) == outb ); + out.write( (byte)outb ); + + // handle consecutive numbers + for( int i = 2; i < numbers.length; i++ ) { + n = numbers[i]; + Assert.assert( n >= 0 ); + + // array of output bytes, in reverse order. 10 bytes, at 7 bits + // per byte, is 70 bits, which is more than enough to handle + // the maximum value of a long, which takes up 63 bits. + byte[] rev = new byte[10]; + int idx=0; // index into reversed bytes + + // Create reversed byte list + do { + rev[idx++] = (byte) (n % 128); + n = n / 128; + } while( n > 0 ); + idx--; // backup to point to last element + + // now print them in reverse order + while( idx > 0 ) { + // all but last byte have MSB==1 + out.write( rev[idx--] | 0x80 ); + } + Assert.assert(idx == 0); + // last byte has MSB==0 + out.write( rev[0] ); + } + + return out.toByteArray(); + } + + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + ostream.write( getEncoding(implicitTag) ); + } + + private static final Template templateInstance = new Template(); + public static Template getTemplate() { + return templateInstance; + } + +/////////////////////////////////////////////////////////////////////// +// OBJECT_IDENTIFIER.Template +// +public static class Template implements ASN1Template { + + public Tag getTag() { + return OBJECT_IDENTIFIER.TAG; + } + public boolean tagMatch(Tag tag) { + return( tag.equals(OBJECT_IDENTIFIER.TAG) ); + } + + public Form getForm() { + return OBJECT_IDENTIFIER.FORM; + } + public boolean formMatch(Form form) { + return( form == OBJECT_IDENTIFIER.FORM ); + } + + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + return decode(getTag(), istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws IOException, InvalidBERException + { + try { + ASN1Header head = new ASN1Header(istream); + long remainingContent = head.getContentLength(); + + // Check the information gleaned from the header + if( ! head.getTag().equals( implicitTag ) ) { + throw new InvalidBERException("Incorrect tag for "+ + "OBJECT IDENTIFIER: "+ head.getTag() ); + } + if( head.getForm() != getForm() ) { + throw new InvalidBERException("Incorrect form for OBJECT "+ + "IDENTIFIER"); + } + if( remainingContent < 1 ) { + throw new InvalidBERException("Invalid 0 length for OBJECT"+ + " IDENTIFIER"); + } + + Vector numberV = new Vector(); + + // handle first byte, which contains first two numbers + byte b = readByte(istream); + remainingContent--; + long num = b % 40; + numberV.addElement( new Long( b % 40 ) ); // second number + numberV.insertElementAt( new Long( b / 40 ), 0); // first number + + // handle the rest of the numbers + while( remainingContent > 0 ) { + num = 0; + + // keep reading until MSB == 0 + int bitcount=0; + do { + if( (bitcount+=7) > 63 ) { + // we're about to overflow our long + throw new InvalidBERException("OBJECT IDENTIFIER "+ + "element too long; max is 63 bits"); + } + b = readByte(istream); + remainingContent--; + num <<= 7; + num |= (b & 0x7f); + } while( (b & 0x80) != 0 ); + + numberV.addElement( new Long( num ) ); + } + + // convert Vector to array + long numbers[] = new long[ numberV.size() ]; + for(int i = 0; i < numbers.length; i++) { + numbers[i] = ((Long)numberV.elementAt(i)).longValue(); + } + + // create OBJECT_IDENTIFIER from array + return new OBJECT_IDENTIFIER(numbers); + + } catch(InvalidBERException e) { + throw new InvalidBERException(e, "OBJECT IDENTIFIER"); + } + } + + /** + * Reads in a byte from the stream, throws an InvalidBERException + * if EOF is reached. + */ + private static byte readByte(InputStream istream) + throws InvalidBERException, IOException + { + int n = istream.read(); + if( n == -1 ) { + throw new InvalidBERException("End-of-file reached while "+ + "decoding OBJECT IDENTIFIER"); + } + Assert.assert( (n & 0xff) == n ); + return (byte) n; + } + +} // end of OBJECT_IDENTIFIER.Template + +} diff --git a/mozilla/security/jss/org/mozilla/jss/asn1/OCTET_STRING.java b/mozilla/security/jss/org/mozilla/jss/asn1/OCTET_STRING.java new file mode 100644 index 00000000000..3094dd4d62c --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/asn1/OCTET_STRING.java @@ -0,0 +1,147 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.asn1; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; +import java.io.ByteArrayOutputStream; + +public class OCTET_STRING implements ASN1Value { + + public static final Tag TAG = new Tag(Tag.Class.UNIVERSAL, 4); + public Tag getTag() { + return TAG; + } + public static final Form FORM = Form.PRIMITIVE; + + byte[] data; + + private OCTET_STRING() { } + + public OCTET_STRING( byte[] data ) { + this.data = data; + } + + public byte[] toByteArray() { + return data; + } + + public void encode(OutputStream ostream) throws IOException { + // use getTag() so we can be subclassed + encode(getTag(), ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + ASN1Header head = new ASN1Header(implicitTag, FORM, data.length); + + head.encode(ostream); + + ostream.write(data); + } + + private static final Template templateInstance = new Template(); + public static Template getTemplate() { + return templateInstance; + } + +public static class Template implements ASN1Template { + + public Tag getTag() { + return TAG; + } + + public boolean tagMatch(Tag tag) { + return( TAG.equals(tag) ); + } + + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + return decode(getTag(), istream); + } + + // this can be overridden by subclasses + protected ASN1Value generateInstance(byte[] bytes) { + return new OCTET_STRING( bytes ); + } + + // this can be overridden by subclasses + protected String getName() { + return "OCTET_STRING"; + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws IOException, InvalidBERException + { + try { + ASN1Header head = new ASN1Header(istream); + + head.validate(implicitTag); + + byte[] data; + + if( head.getContentLength() == -1 ) { + // indefinite length encoding + ASN1Header ahead; + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + do { + ahead = ASN1Header.lookAhead( istream ); + if( ! ahead.isEOC() ) { + OCTET_STRING.Template ot = new OCTET_STRING.Template(); + OCTET_STRING os = (OCTET_STRING) ot.decode(istream); + bos.write( os.toByteArray() ); + } + } while( ! ahead.isEOC() ); + + // consume EOC + ahead = new ASN1Header(istream); + + data = bos.toByteArray(); + } else { + data = new byte[ (int) head.getContentLength() ]; + ASN1Util.readFully(data, istream); + } + + return generateInstance(data); + + } catch( InvalidBERException e ) { + throw new InvalidBERException(e, getName()); + } + } + +} // end of Template + +} diff --git a/mozilla/security/jss/org/mozilla/jss/asn1/PrintableString.java b/mozilla/security/jss/org/mozilla/jss/asn1/PrintableString.java new file mode 100644 index 00000000000..335f20d7e45 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/asn1/PrintableString.java @@ -0,0 +1,157 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.asn1; + +import java.io.CharConversionException; + +public class PrintableString extends CharacterString implements ASN1Value { + + public PrintableString(char[] chars) throws CharConversionException { + super(chars); + } + + public PrintableString(String s) throws CharConversionException { + super(s); + } + + CharConverter getCharConverter() { + return new PrintableConverter(); + } + + public static final Tag TAG = new Tag( Tag.UNIVERSAL, 19 ); + public static final Form FORM = Form.PRIMITIVE; + + public Tag getTag() { + return TAG; + } + + /** + * Returns a singleton instance of the decoding template for this class. + */ + public static Template getTemplate() { + return templateInstance; + } + private static final Template templateInstance = new Template(); + +// nested class +public static class Template + extends CharacterString.Template implements ASN1Template +{ + protected Tag getTag() { + return TAG; + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + protected CharConverter getCharConverter() { + return new PrintableConverter(); + } + + protected CharacterString generateInstance(char[] chars) + throws CharConversionException + { + return new PrintableString(chars); + } + + protected String typeName() { + return "PrintableString"; + } +} + +private static class PrintableConverter implements CharConverter { + + private static boolean[] isPrintable = new boolean[128]; + static { + char b; + for(b='A'; b <= 'Z'; b++) { + isPrintable[b] = true; + } + for(b='a'; b <= 'z'; b++) { + isPrintable[b] = true; + } + for(b='0'; b <= '9'; b++) { + isPrintable[b] = true; + } + isPrintable[' '] = true; + isPrintable['\''] = true; + isPrintable['('] = true; + isPrintable[')'] = true; + isPrintable['+'] = true; + isPrintable[','] = true; + isPrintable['-'] = true; + isPrintable['.'] = true; + isPrintable['/'] = true; + isPrintable[':'] = true; + isPrintable['='] = true; + isPrintable['?'] = true; + } + + public char[] byteToChar(byte[] bytes, int offset, int len) + throws CharConversionException + { + char[] chars = new char[len]; + int c; // char index + int b; // byte index + for(c=0, b=offset; c < len; b++, c++) { + if( (bytes[b] & 0x80) != 0 || !isPrintable[bytes[b]] ) { + /* fix for bug 359010 - don't throw, just skip + * throw new CharConversionException(bytes[b]+ " is not "+ + * "a valid character for a PrintableString"); + */ + } else { + chars[c] = (char) bytes[b]; + } + } + return chars; + } + + public byte[] charToByte(char[] chars, int offset, int len) + throws CharConversionException + { + byte[] bytes = new byte[len]; + int c; // char index + int b; // byte index + for(c=0, b=0; b < len; b++, c++) { + if( (chars[c] & 0xff80) != 0 || !isPrintable[chars[c]] ) { + throw new CharConversionException(chars[c]+ " is not "+ + "a valid character for a PrintableString"); + } + bytes[b] = (byte) (chars[c] & 0x7f); + } + return bytes; + } +} // end of char converter + +} diff --git a/mozilla/security/jss/org/mozilla/jss/asn1/SEQUENCE.java b/mozilla/security/jss/org/mozilla/jss/asn1/SEQUENCE.java new file mode 100644 index 00000000000..0271084d982 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/asn1/SEQUENCE.java @@ -0,0 +1,725 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.asn1; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; +import java.io.FileInputStream; +import java.io.BufferedInputStream; +import java.util.Vector; +import com.netscape.jss.util.Assert; +import java.math.BigInteger; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; + +/** + * An ASN.1 SEQUENCE. This class is an ordered collection of ASN.1 values. + * It has an interface similar to a Java Vector. + * Null entries may be added; they will be skipped when encoded. + */ +public class SEQUENCE extends SET implements ASN1Value { + + public static final Tag TAG = new Tag(Tag.Class.UNIVERSAL, 16); + public Tag getTag() { + return TAG; + } + + public static Template getTemplate() { + return new Template(); + } + + /** + * Writes the DER encoding to the given output stream, + * using the given implicit tag. + */ + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + BERencode(implicitTag, ostream); + } + + // SET.Element and SEQUENCE.Element are identical types. We could + // have just reused SET.Element, but that would have been a bit + // confusing for users. + private static class Element extends SET.Element { + public Element( ASN1Value val ) { + super(val); + } + public Element( Tag implicitTag, ASN1Value val) { + super(implicitTag, val); + } + } + +/** + * A class for constructing a SEQUENCE from its BER encoding. + * It is an ordered collection of sub-templates. Each sub-template can be + * marked optional, or a default value can be given. + */ +public static class Template implements ASN1Template { + + private Vector elements = new Vector(); + + private void addElement(Element el) { + elements.addElement( el ); + } + + private void insertElementAt(Element e, int index) { + elements.insertElementAt(e, index); + } + + /** + * Adds a sub-template to the end of this SEQUENCE template. For example, + * if the ASN.1 included: + *
+     * MySequence ::= SEQUENCE {
+     *      item        SubType,
+     *      ... }
+     * 
+ * the "item" element would be added to the MySequence template with: + *
+     *  mySequence.addElement( new SubType.Template() );
+     * 
+ */ + public void addElement( ASN1Template t ) { + addElement( new Element(null, t, false) ); + } + + /** + * Inserts the template at the given index. + */ + public void insertElementAt( ASN1Template t, int index ) + { + insertElementAt( new Element(null, t, false), index ); + } + + /** + * Adds a sub-template to the end of this SEQUENCE template, with the + * given implicit tag. For example, if the ASN.1 were: + *
+     * MySequence ::= SEQUENCE {
+     *      item        [0] IMPLICIT  SubType,
+     *      ... }
+     * 
+ * the "item" element would be added to the MySequence template with: + *
+     *  mySequence.addElement( new Tag(0), new SubType.Template());
+     * 
+ */ + public void addElement( Tag implicitTag, ASN1Template t ) { + addElement( new Element(implicitTag, t, false) ); + } + + /** + * Inserts the template with the given implicit tag at the given index. + */ + public void insertElementAt( Tag implicit, ASN1Template t, + int index ) + { + insertElementAt( new Element(implicit, t, false), index ); + } + + /** + * Adds an optional sub-template. For example, if the ASN.1 were: + *
+     * MySequence ::= SEQUENCE {
+     *      item        SubType OPTIONAL,
+     *      ... }
+     * 
+ * the "item" element would be added to the MySequence template with: + *
+     *  mySequence.addOptionalElement( new SubType.Template() );
+     * 
+ */ + public void addOptionalElement( ASN1Template t ) { + addElement( new Element(null, t, true) ); + } + + /** + * Inserts the optional template at the given index. + */ + public void insertOptionalElementAt( ASN1Template t, int index ) + { + insertElementAt( new Element(null, t, true), index ); + } + + /** + * Adds an optional sub-template with an implicit tag. For example, + * if the ASN.1 were: + *
+     * MySequence ::= SEQUENCE {
+     *      item        [0] IMPLICIT SubType OPTIONAL,
+     *      ... }
+     * 
+ * the "item" element would be added to the MySequence template with: + *
+     *  mySequence.addOptionalElement( new SubType.Template() );
+     * 
+ */ + public void addOptionalElement( Tag implicitTag, ASN1Template t ) { + addElement( new Element(implicitTag, t, true) ); + } + + /** + * Inserts the optional template with the given default + * value at the given index. + */ + public void insertOptionalElementAt( Tag implicit, ASN1Template t, + int index ) + { + insertElementAt( new Element(implicit, t, true), index ); + } + + /** + * Adds a sub-template with a default value. For example, + * if the ASN.1 were: + *
+     * MySequence ::= SEQUENCE {
+     *      version     INTEGER DEFAULT 1,
+     *      ... }
+     * 
+ * the "item" element would be added to the MySequence template with: + *
+     *  mySequence.addElement( new INTEGER.Template(), new INTEGER(1) );
+     * 
+ * @param def The default value for this field, which will be used if + * no value is supplied by the encoded structure. It must be of + * the same type as what the template would produce. + */ + public void addElement( ASN1Template t, ASN1Value def ) { + addElement( new Element(null, t, def) ); + } + + /** + * Inserts the template with the given default + * value at the given index. + */ + public void insertElementAt( ASN1Template t, ASN1Value def, int index ) + { + insertElementAt( new Element(null, t, def), index ); + } + + /** + * Adds a sub-template with a default value and an implicit tag. + * For example, if the ASN.1 were: + *
+     * MySequence ::= SEQUENCE {
+     *      version     [0] IMPLICIT INTEGER DEFAULT 1,
+     *      ... }
+     * 
+ * the "item" element would be added to the MySequence template with: + *
+     *  mySequence.addElement( new Tag(0), new INTEGER.Template(),
+     *      new INTEGER(1) );
+     * 
+ * @param def The default value for this field, which will be used if + * no value is supplied by the encoded structure. It must be of + * the same type as what the template would produce. + */ + public void addElement( Tag implicitTag, ASN1Template t, ASN1Value def) { + addElement( new Element(implicitTag, t, def) ); + } + + /** + * Inserts the template with the given implicit tag and given default + * value at the given index. + */ + public void insertElementAt( Tag implicit, ASN1Template t, ASN1Value def, + int index ) + { + insertElementAt( new Element(implicit, t, def), index ); + } + + /** + * Returns the implicit tag of the item stored at the given index. + * May be NULL if no implicit tag was specified. + */ + public Tag implicitTagAt( int index ) { + return ((Element)elements.elementAt(index)).getImplicitTag(); + } + + /** + * Returns the sub-template stored at the given index. + */ + public ASN1Template templateAt( int index ) { + return ((Element)elements.elementAt(index)).getTemplate(); + } + + /** + * Returns whether the sub-template at the given index is optional. + */ + public boolean isOptionalAt( int index ) { + return ((Element)elements.elementAt(index)).isOptional(); + } + + /** + * Returns the default value for the sub-template at the given index. + * May return NULL if no default value was specified. + */ + public ASN1Value defaultAt( int index ) { + return ((Element)elements.elementAt(index)).getDefault(); + } + + /** + * Returns the number of elements in this SEQUENCE template. + */ + public int size() { + return elements.size(); + } + + /** + * Removes all sub-templates from this SEQUENCE template. + */ + public void removeAllElements() { + elements.removeAllElements(); + } + + /** + * Removes the sub-template at the given index. + */ + public void removeElementAt(int index) { + elements.removeElementAt(index); + } + + Tag getTag() { + return SEQUENCE.TAG; + } + + public boolean tagMatch(Tag tag) { + return( tag.equals(SEQUENCE.TAG) ); + } + + /** + * Decodes a SEQUENCE from its BER encoding. + */ + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + return decode(getTag(), istream); + } + + /** + * Decodes a SEQUENCE from its BER encoding, where the SEQUENCE itself has + * an implicit tag. + */ + public ASN1Value decode(Tag tag, InputStream istream) + throws IOException, InvalidBERException + { + int index = 0; + + try { + ASN1Header header = new ASN1Header(istream); + + header.validate( tag, Form.CONSTRUCTED ); + + // will be -1 for indefinite encoding + long remainingContent = header.getContentLength(); + + boolean repeatableElement=false; + SEQUENCE seq = new SEQUENCE(); + ASN1Header lookAhead=null; + + // go through the whole template + for( index = 0; index < size(); index++ ) { + + // find out about the next item + if( remainingContent == 0 ) { + lookAhead = null; + } else { + // remainingContent > 0 or remainingContent == -1, which means + // indefinite encoding. + lookAhead = ASN1Header.lookAhead(istream); + } + + // skip over items that don't match. Hopefully they are + // optional or have a default. Otherwise, it's an error. + Element e = (Element) elements.elementAt(index); + if( (lookAhead == null) || lookAhead.isEOC() || + ! e.tagMatch( lookAhead.getTag() ) ) + { + if( e.isRepeatable() ) { + repeatableElement = true; + } else if( e.isOptional() ) { + // put an empty entry into the SEQUENCE + SEQUENCE.Element se = new SEQUENCE.Element(null, null ); + seq.addElement( null ); + } else if( e.getDefault() != null ) { + // use the default + seq.addElement( e.getDefault() ); + } else { + throw new InvalidBERException("Missing item #"+index+ + " need tag " + lookAhead.getTag() + " element tag " + e.getImplicitTag() + " in SEQUENCE"); + } + continue; + } + + // Decode this element + ASN1Template t = e.getTemplate(); + ASN1Value val; + CountingStream countstream = new CountingStream(istream); + if( e.getImplicitTag() == null ) { + val = t.decode(countstream); + } else { + val = t.decode(e.getImplicitTag(), countstream); + } + + // Decrement remaining count + long len = countstream.getNumRead(); + if( remainingContent != -1 ) { + if( remainingContent < len ) { + // this item went past the end of the SEQUENCE + throw new InvalidBERException("Item went "+ + (len-remainingContent)+" bytes past the end of"+ + " the SEQUENCE"); + } + remainingContent -= len; + } + + // Store this element in the SEQUENCE + if( e.getImplicitTag() == null ) { + // no implicit tag + seq.addElement( val ); + } else { + // there is an implicit tag + seq.addElement( e.getImplicitTag(), val ); + } + + // If this element is repeatable, don't go on to the next element + if( e.isRepeatable() ) { + repeatableElement = true; + index--; + } + } + + if( remainingContent > 0 ) { + throw new InvalidBERException("SEQUENCE is longer than expected "+remainingContent+" expected"); + } + Assert.assert( remainingContent == 0 || remainingContent == -1 ); + + // If this was indefinite-length encoding, consume the end-of-contents + if( remainingContent == -1 ) { + lookAhead = new ASN1Header(istream); + if( ! lookAhead.isEOC() ) { + throw new InvalidBERException("No end-of-contents marker"); + } + } + + // Make sure we stayed in sync + if( ! repeatableElement ) { + Assert.assert(index == seq.size()); + } + + return seq; + + } catch(InvalidBERException e) { + throw new InvalidBERException(e, "SEQUENCE(item #"+index+")"); + } + } + + /** + * An element of a SEQUENCE template. For each sub-template, contains the + * template, its optionality, its implicit tag, and its default value. + */ + static class Element { + + /** + * Creates a new element, which may or may not be optional. + */ + public Element(Tag implicitTag, ASN1Template type, boolean optional) + { + this.type = type; + defaultVal = null; + this.optional = optional; + this.implicitTag = implicitTag; + } + + /** + * Creates a new element with a default value. + */ + public Element(Tag implicitTag, ASN1Template type, ASN1Value defaultVal) + { + this.type = type; + this.defaultVal = defaultVal; + optional = false; + this.implicitTag = implicitTag; + } + + // repeatability is provided to allow for SEQUENCE OF SIZE + // constructs. It is package private. + private boolean repeatable; + void makeRepeatable() { + repeatable = true; + } + boolean isRepeatable() { + return repeatable; + } + + private boolean optional; + public boolean isOptional() { + return optional; + } + + private Tag implicitTag=null; + public Tag getImplicitTag() { + return implicitTag; + } + + public boolean tagMatch(Tag tag) { + if( implicitTag != null ) { + return( implicitTag.equals(tag) ); + } else { + return type.tagMatch(tag); + } + } + + private ASN1Template type; + public ASN1Template getTemplate() { + return type; + } + + private ASN1Value defaultVal=null; + public ASN1Value getDefault() { + return defaultVal; + } + } +} // End of SEQUENCE.Template + +/** + * A Template for decoding SEQUENCE OF values. The main difference between + * a SEQUENCE.Template and a SEQUENCE.OF_Template is that a regular template + * specifies the exact ordering, number, and type of elements of the sequence, + * while + * an OF_Template has an indefinite number of elements, all the same type. + * For example, given: + *
+ * MyType ::= SEQUENCE OF Extension
+ * 
+ * a MyType could be decoded with: + *
+ *  SEQUENCE.OF_Template myTypeTemplate = new SEQUENCE.OF_Template( new
+ *      Extension.Template) );
+ *  SEQUENCE seq = (SEQUENCE) myTypeTemplate.decode(someInputStream);
+ * 
+ * The number of Extensions actually decoded could be found + * with seq.size(). + */ +public static class OF_Template implements ASN1Template { + + private OF_Template() { } + + Template template; // a normal SEQUENCE template + + public OF_Template(ASN1Template type) { + template = new Template(); + Template.Element el = new Template.Element(null, type, true); //optional + el.makeRepeatable(); + template.addElement( el ); + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + /** + * Decodes a SEQUENCE OF from an input stream. + */ + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + return template.decode(istream); + } + + /** + * Decodes a SEQUENCE OF with an implicit tag from an input stream. + */ + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws IOException, InvalidBERException + { + return template.decode(implicitTag, istream); + } +} + + public static void main(String args[]) { + + try { + + if(args.length > 0) { + // input + + Template type = new Template(); + type.addOptionalElement( new Tag(15), new INTEGER.Template() ); + type.addElement( new Tag(16), new INTEGER.Template(), + new INTEGER(42) ); + type.addElement( new INTEGER.Template() ); + type.addElement( new BOOLEAN.Template() ); + type.addElement( new INTEGER.Template() ); + type.addOptionalElement( new Tag(12), new INTEGER.Template() ); + type.addElement( new BOOLEAN.Template() ); + type.addElement( new Tag(13), new INTEGER.Template(), + new INTEGER(53) ); + type.addElement( new INTEGER.Template() ); + type.addElement( new INTEGER.Template() ); + type.addOptionalElement( new Tag(14), new INTEGER.Template() ); + type.addElement( new OBJECT_IDENTIFIER.Template() ); + type.addElement( new NULL.Template() ); + type.addElement( new EXPLICIT.Template( + new Tag(27), new INTEGER.Template())); + type.addElement( new ENUMERATED.Template() ); + type.addElement( new OCTET_STRING.Template() ); + type.addElement( new IA5String.Template() ); + + CHOICE.Template choice = new CHOICE.Template(); + choice.addElement( new Tag(23), new INTEGER.Template() ); + choice.addElement( new BOOLEAN.Template() ); + type.addElement( choice ); + type.addElement( new BIT_STRING.Template() ); + type.addElement( new ANY.Template() ); + type.addElement( new PrintableString.Template() ); + type.addElement( new OF_Template( new INTEGER.Template() ) ); + type.addElement( new OF_Template( new INTEGER.Template() ) ); + + FileInputStream fin = new FileInputStream(args[0]); + System.out.println("Available: "+fin.available()); + byte[] stuff = new byte[ fin.available() ]; + ASN1Util.readFully(stuff, fin); + SEQUENCE s=null; + for( int i = 0; i < 1; i++) { + s = (SEQUENCE) type.decode( new ByteArrayInputStream(stuff) ); + } + + for(int i=0; i < s.size(); i ++ ) { + ASN1Value v = s.elementAt(i); + if(v instanceof ENUMERATED) { + ENUMERATED en = (ENUMERATED) v; + System.out.println("ENUMERATED: "+en); + } else if( v instanceof INTEGER ) { + INTEGER in = (INTEGER) v; + System.out.println("INTEGER: "+in); + } else if(v instanceof BOOLEAN ) { + BOOLEAN bo = (BOOLEAN) v; + System.out.println("BOOLEAN: "+bo); + } else if(v instanceof OBJECT_IDENTIFIER) { + OBJECT_IDENTIFIER oid = (OBJECT_IDENTIFIER) v; + System.out.println("OID: "+oid); + } else if(v instanceof NULL) { + NULL n = (NULL) v; + System.out.println("NULL"); + } else if(v instanceof EXPLICIT) { + EXPLICIT ex = (EXPLICIT) v; + INTEGER in = (INTEGER) ex.getContent(); + System.out.println("EXPLICIT ["+ex.getTag()+"]: "+ + "INTEGER: "+in); + } else if(v instanceof OCTET_STRING) { + OCTET_STRING os = (OCTET_STRING) v; + byte[] bytes = os.toByteArray(); + System.out.print("OCTET_STRING: "); + for(int j = 0; j < bytes.length; j++) { + System.out.print(bytes[j]+" "); + } + System.out.println(""); + } else if( v instanceof CharacterString ) { + CharacterString cs = (CharacterString) v; + System.out.println("String: "+cs); + } else if( v instanceof BIT_STRING ) { + BIT_STRING bs = (BIT_STRING) v; + System.out.print("BIT_STRING: padCount="+ + bs.getPadCount()+" : "); + byte[] bits = bs.getBits(); + for(int j = 0; j < bits.length; j++) { + System.out.print(bits[j]+" "); + } + System.out.println(""); + } else if( v instanceof ANY ) { + ANY any = (ANY) v; + Tag tag = any.getTag(); + System.out.println("Got ANY, tag is "+tag); + ByteArrayInputStream bos = + new ByteArrayInputStream( any.getEncoded() ); + INTEGER in = (INTEGER) new INTEGER.Template().decode(bos); + System.out.println(" INTEGER: "+in); + } else if(v instanceof SEQUENCE ) { + SEQUENCE seq = (SEQUENCE)v; + System.out.println("SEQUENCE: "); + for(int j=0; j < seq.size(); j++ ) { + INTEGER in = (INTEGER) seq.elementAt(j); + System.out.println(" INTEGER: "+in); + } + } else { + System.out.println("Unknown value"); + } + } + + + } else { + // output + + SEQUENCE seq = new SEQUENCE(); + seq.addElement( new INTEGER(5) ); + seq.addElement( new BOOLEAN(true) ); + seq.addElement( new INTEGER(-322) ); + seq.addElement( new BOOLEAN(false) ); + seq.addElement( new INTEGER(0) ); + seq.addElement( new INTEGER("2934293834242") ); + seq.addElement( new OBJECT_IDENTIFIER( + new long[] { 1, 2, 127, 563, 1231982 } ) ); + seq.addElement( new NULL() ); + seq.addElement( new EXPLICIT( new Tag(27), new INTEGER(39) )); + seq.addElement( new ENUMERATED(983) ); + seq.addElement( new OCTET_STRING( new byte[] { + (byte)0x0, (byte)0xff, (byte)0xcc} ) ); + seq.addElement( new IA5String("foobar") ); + seq.addElement( new Tag(23), new INTEGER(234) ); + //seq.addElement( new BOOLEAN(false) ); + byte[] bits = new byte[]{ (byte)0x80, (byte)0xff, (byte)0x0f }; + seq.addElement( new BIT_STRING( bits, 3 ) ); + seq.addElement( new INTEGER(82734) ); + seq.addElement( new PrintableString("I'm printable??") ); + + SEQUENCE nested = new SEQUENCE(); + nested.addElement( new INTEGER( 5 ) ); + nested.addElement( new INTEGER( 6 ) ); + seq.addElement( nested ); + + nested = new SEQUENCE(); + seq.addElement( nested ); + + + seq.encode(System.out); + System.out.flush(); + } + } catch( Exception e) { + e.printStackTrace(); + } + } + +} diff --git a/mozilla/security/jss/org/mozilla/jss/asn1/SET.java b/mozilla/security/jss/org/mozilla/jss/asn1/SET.java new file mode 100644 index 00000000000..c74ea2f2c04 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/asn1/SET.java @@ -0,0 +1,930 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.asn1; + +import java.math.BigInteger; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Vector; +import com.netscape.jss.util.Assert; +import java.io.FileInputStream; +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; + +/** + * An ASN.1 SET, which is an unordered collection of ASN.1 values. + * It has an interface like a Java Vector, but the ordering is arbitrary. + * Null entries may be added; they will be skipped when encoding. + */ +public class SET implements ASN1Value { + + public static final Tag TAG = new Tag(Tag.Class.UNIVERSAL, 17); + + public Tag getTag() { + return TAG; + } + protected static final Form FORM = Form.CONSTRUCTED; + + // The elements of the set + protected Vector elements = new Vector(); + + private void addElement( Element e ) { + elements.addElement(e); + } + + private void insertElementAt( Element e, int index ) { + elements.insertElementAt(e, index); + } + + /** + * Adds an element to this SET. + */ + public void addElement( ASN1Value v ) { + addElement( new Element(v) ); + } + + /** + * Adds an element to this SET with the given implicit tag. For example, + * if the ASN.1 were: + *
+     *  MyType ::= SET {
+     *      item        [0] IMPLICIT INTEGER,
+     *      ... }
+     * 
+ * then the "item" element could be added (with a sample value of 45) + * to the SET with: + *
+     * myTypeInstance.addElement( new Tag(0), new INTEGER(45) );
+     * 
+ */ + public void addElement( Tag implicitTag, ASN1Value v ) { + addElement( new Element(implicitTag, v) ); + } + + /** + * Inserts an element at the given index. + */ + public void insertElementAt( ASN1Value v, int index ) { + insertElementAt( new Element(v), index ); + } + + /** + * Inserts an element with the given implicit tag at the given index. + */ + public void insertElementAt( Tag implicitTag, ASN1Value v, int index ) { + insertElementAt( new Element(implicitTag, v), index ); + } + + /** + * Returns the element at the given index in the SET. + */ + public ASN1Value elementAt( int index ) { + return ((Element)elements.elementAt(index)).getValue(); + } + + /** + * Returns the tag of the element at the given index. If the element + * has an implicit tag, that is returned. Otherwise, the tag of the + * underlying type is returned. + */ + public Tag tagAt( int index ) { + Tag implicit = ((Element)elements.elementAt(index)).getImplicitTag(); + if( implicit != null ) { + return implicit; + } else { + return elementAt(index).getTag(); + } + } + + /** + * Returns the element with the given Tag, or null if no element exists + * with the given tag. + */ + public ASN1Value elementWithTag( Tag tag ) { + // hmmm...linear search for now, should use hashtable later + + int size = elements.size(); + for( int i=0; i < size; i++ ) { + Element e = (Element) elements.elementAt(i); + if( e.getTag().equals(tag) ) { + return e.getValue(); + } + } + return null; + } + + /** + * Returns the number of elements in this SET. + */ + public int size() { + return elements.size(); + } + + /** + * Removes all elements from this SET. + */ + public void removeAllElements() { + elements.removeAllElements(); + } + + /** + * Removes the element from the specified index. + */ + public void removeElementAt(int index) { + elements.removeElementAt(index); + } + + /** + * Writes the DER encoding to the given output stream. + */ + public void encode(OutputStream ostream) + throws IOException + { + encode(getTag(), ostream); + } + + /** + * Writes the DER encoding to the given output stream, + * using the given implicit tag. To satisfy DER encoding rules, + * the elements will be re-ordered either by tag or lexicographically. + */ + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + // what ordering method? + boolean lexOrdering; + if( elements.size() < 2 ) { + // doesn't matter, only one element + lexOrdering = true; + } else if( tagAt(0).equals(tagAt(1)) ) { + // tags are the same, lexicographic ordering + lexOrdering = true; + } else { + // tags are different, order by tag + lexOrdering = false; + } + + // compute and order contents + int numElements = elements.size(); + int totalBytes = 0; + Vector encodings = new Vector(numElements); + Vector tags = new Vector(numElements); + int i; + for(i = 0; i < numElements; i++ ) { + + // if an entry is null, just skip it + if( elementAt(i) != null ) { + byte[] enc = ASN1Util.encode(tagAt(i), elementAt(i)); + + totalBytes += enc.length; + + if( lexOrdering ) { + insertInOrder(encodings, enc); + } else { + insertInOrder(encodings, enc, tags, (int) tagAt(i).getNum()); + } + } + } + + // write header + ASN1Header header = new ASN1Header( implicitTag, FORM, totalBytes ); + header.encode(ostream); + + // write contents in order + for(i=0; i < numElements; i++ ) { + ostream.write( (byte[]) encodings.elementAt(i) ); + } + } + + /** + * Encodes this SET without re-ordering it. This may violate + * DER, but it is within BER. + */ + public void BERencode(Tag implicitTag, OutputStream ostream) + throws IOException + { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + + // compute contents + int size = elements.size(); + for(int i = 0; i < size; i++ ) { + ASN1Value el = elementAt(i); + if(el!=null) { + el.encode(tagAt(i), bos); + } + } + + byte[] bytes = bos.toByteArray(); + + // write header + ASN1Header header = new ASN1Header( implicitTag, FORM, bytes.length ); + header.encode(ostream); + + // write contents + ostream.write(bytes); + } + + // performs ascending lexicographic ordering + // linear search, but number of items is usually going to be small. + private static void insertInOrder(Vector encs, byte[] enc) { + int size = encs.size(); + + // find the lowest item that we are less than or equal to + int i; + for(i=0; i < size; i++) { + if( compare(enc, (byte[])encs.elementAt(i)) < 1 ) { + break; + } + } + + // insert ourself before this item + encs.insertElementAt(enc, i); + } + + // performs ascending ordering by tag + // linear search, but number of items is usually going to be small. + private static void insertInOrder(Vector encs, byte[] enc, Vector tags, + int tag) + { + int size = encs.size(); + + // find the lowest item that we are less than or equal to + int i; + for(i = 0; i < size; i++) { + if( tag <= ((Integer)tags.elementAt(i)).intValue() ) { + break; + } + } + + // insert ourself before this item + encs.insertElementAt(enc, i); + tags.insertElementAt(new Integer(i), i ); + } + + + // compares two byte arrays + // returns 1 if left > right, -1 if left < right, 0 if left == right + private static int compare(byte[] left, byte[] right) { + int min = (left.length < right.length) ? left.length : right.length; + + for(int i=0; i < min; i++) { + if( (left[i]&0xff) < (right[i]&0xff) ) { + return -1; + } else if( (left[i]&0xff) > (right[i]&0xff) ) { + return 1; + } + } + + // equal up to the minimal endpoint + if( left.length > min ) { + Assert.assert(right.length==min); + return 1; + } + if( right.length > min ) { + Assert.assert(left.length==min); + return -1; + } + return 0; + } + + /** + * An element of a SET + */ + static class Element { + + /** + * Makes a new SET element from the given value. + */ + public Element( ASN1Value val ) { + this.val = val; + } + + /** + * Makes a new SET element from the given value with the given + * implicit tag. + */ + public Element( Tag implicitTag, ASN1Value val ) + { + this.val = val; + this.implicitTag = implicitTag; + } + + private ASN1Value val; + /** + * Returns the value of this SET element. + */ + public ASN1Value getValue() { + return val; + } + + /** + * Returns the tag that actually shows up in the encoding. + * If there is an implicit tag, it will be used. Otherwise, + * it will be the base tag for the value. + */ + public Tag getTag() { + if(implicitTag!=null) { + return implicitTag; + } else { + return val.getTag(); + } + } + + private Tag implicitTag=null; + /** + * Returns the implicit tag for this value, if there is one. + * If not, returns null. + */ + public Tag getImplicitTag() { + return implicitTag; + } + } + +/** + * SET.Template + * This class is used for decoding DER-encoded SETs. + */ +public static class Template implements ASN1Template { + + private Vector elements = new Vector(); + + private void addElement( Element e ) { + elements.addElement(e); + } + + private void insertElementAt( Element e, int index ) { + elements.insertElementAt(e, index); + } + + /** + * Adds a sub-template to the end of this SET template. For example, + * if the ASN.1 included: + *
+     * MySet ::= SET {
+     *      item        SubType,
+     *      ... }
+     * 
+ * the "item" element would be added to the MySet template with: + *
+     *  mySet.addElement( new SubType.Template() );
+     * 
+ */ + public void addElement( ASN1Template t ) { + addElement( new Element(TAG, t, false) ); + } + + /** + * Inserts the template at the given index. + */ + public void insertElementAt( ASN1Template t, int index ) + { + insertElementAt( new Element(TAG, t, false), index ); + } + + /** + * Adds a sub-template with the given implicit tag to the end of this + * SET template. For example, if the ASN.1 included: + *
+     * MySet ::= SET {
+     *      item        [0] IMPLICIT SubType,
+     *      ... }
+     * 
+ * the "item" element would be added to the MySet template with: + *
+     *  mySet.addElement( new Tag(0), new SubType.Template() );
+     * 
+ */ + public void addElement( Tag implicit, ASN1Template t ) { + addElement( new Element(implicit, t, false) ); + } + + /** + * Inserts the template with the given implicit tag at the given index. + */ + public void insertElementAt( Tag implicit, ASN1Template t, + int index ) + { + insertElementAt( new Element(implicit, t, false), index ); + } + + /** + * Adds an optional sub-template to the end + * of this SET template. For example, if the ASN.1 included: + *
+     * MySet ::= SET {
+     *      item        SubType OPTIONAL,
+     *      ... }
+     * 
+ * the "item" element would be added to the MySet template with: + *
+     *  mySet.addOptionalElement( new SubType.Template() );
+     * 
+ */ + public void addOptionalElement( ASN1Template t ) { + addElement( new Element(TAG, t, true) ); + } + + /** + * Inserts the optional template at the given index. + */ + public void insertOptionalElementAt( ASN1Template t, int index ) + { + insertElementAt( new Element(null, t, true), index ); + } + + /** + * Adds an optional sub-template with the given implicit tag to the end + * of this SET template. For example, if the ASN.1 included: + *
+     * MySet ::= SET {
+     *      item        [0] IMPLICIT SubType OPTIONAL,
+     *      ... }
+     * 
+ * the "item" element would be added to the MySet template with: + *
+     *  mySet.addOptionalElement( new Tag(0), new SubType.Template() );
+     * 
+ */ + public void addOptionalElement( Tag implicit, ASN1Template t ) { + addElement( new Element(implicit, t, true) ); + } + + /** + * Inserts the optional template with the given default + * value at the given index. + */ + public void insertOptionalElementAt( Tag implicit, ASN1Template t, + int index ) + { + insertElementAt( new Element(implicit, t, true), index ); + } + + + /** + * Adds a sub-template with the given default value to the end + * of this SET template. For example, if the ASN.1 included: + *
+     * MySet ::= SET {
+     *      item        INTEGER DEFAULT (5),
+     *      ... }
+     * 
+ * the "item" element would be added to the MySet template with: + *
+     *  mySet.addElement( new SubType.Template(), new INTEGER(5) );
+     * 
+ */ + public void addElement( ASN1Template t, ASN1Value def ) { + addElement( new Element(TAG, t, def) ); + } + + /** + * Inserts the template with the given default + * value at the given index. + */ + public void insertElementAt( ASN1Template t, ASN1Value def, int index ) + { + insertElementAt( new Element(null, t, def), index ); + } + + /** + * Adds a sub-template with the given default value and implicit tag to + * the end of this SET template. For example, if the ASN.1 included: + *
+     * MySet ::= SET {
+     *      item        [0] IMPLICIT INTEGER DEFAULT (5),
+     *      ... }
+     * 
+ * the "item" element would be added to the MySet template with: + *
+     *  mySet.addElement( new Tag(0), new SubType.Template(), new INTEGER(5) );
+     * 
+ */ + public void addElement( Tag implicit, ASN1Template t, ASN1Value def ) { + addElement( new Element(implicit, t, def) ); + } + + /** + * Inserts the template with the given implicit tag and given default + * value at the given index. + */ + public void insertElementAt( Tag implicit, ASN1Template t, ASN1Value def, + int index ) + { + insertElementAt( new Element(implicit, t, def), index ); + } + + /** + * Returns the implicit tag of the item stored at the given index. + * May be NULL if no implicit tag was specified. + */ + public Tag implicitTagAt(int index) { + return ((Element)elements.elementAt(index)).getImplicitTag(); + } + + /** + * Returns the sub-template stored at the given index. + */ + public ASN1Template templateAt(int index) { + return ((Element)elements.elementAt(index)).getTemplate(); + } + + /** + * Returns true if the sub-template at the given index + * is optional. + */ + public boolean isOptionalAt(int index) { + return ((Element)elements.elementAt(index)).isOptional(); + } + + private boolean isRepeatableAt(int index) { + return ((Element)elements.elementAt(index)).isRepeatable(); + } + + /** + * Returns the default value for the sub-template at the given index. + * May return NULL if no default value was specified. + */ + public ASN1Value defaultAt(int index) { + return ((Element)elements.elementAt(index)).getDefault(); + } + + /** + * Returns the number of elements in the SET. + */ + public int size() { + return elements.size(); + } + + public void removeAllElements() { + elements.removeAllElements(); + } + + public void removeElementAt(int index) { + elements.removeElementAt(index); + } + + private Tag getTag() { + return SET.TAG; + } + + /** + * Determines whether the given tag satisfies this template. + */ + public boolean tagMatch(Tag tag) { + return( tag.equals(SET.TAG) ); + } + + /** + * Decodes the input stream into a SET value. + */ + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + return decode(getTag(), istream); + } + + /** + * Decodes the input stream into a SET value with the given implicit + * tag. + */ + public ASN1Value decode(Tag tag, InputStream istream) + throws IOException, InvalidBERException + { + try { + ASN1Header header = new ASN1Header(istream); + + header.validate( tag, Form.CONSTRUCTED ); + + // remainingContent will be -1 for indefinite length encoding + long remainingContent = header.getContentLength(); + SET set = new SET(); + ASN1Header lookAhead; + boolean[] found = new boolean[ elements.size() ]; + + // while content remains, try to decode it + while( remainingContent > 0 || remainingContent == -1) { + + // find out about the next item + lookAhead = ASN1Header.lookAhead(istream); + + // if we found the end-of-content marker, we're done + if( lookAhead.isEOC() ) { + if( remainingContent != -1 ) { + throw new InvalidBERException("Unexpected end-of-content"+ + "marker"); + } + lookAhead = new ASN1Header(istream); + break; + } + + // Find the element with the matching tag + int index = findElementByTag( lookAhead.getTag() ); + if( index == -1 ) { + // element not found + throw new InvalidBERException("Unexpected Tag in SET: "+ + lookAhead.getTag() ); + } + Element e = (Element) elements.elementAt(index); + if( found[index] && ! e.isRepeatable() ) { + // element already found, and it's not repeatable + throw new InvalidBERException("Duplicate Tag in SET: "+ + lookAhead.getTag() ); + } + + // mark this element as found + found[index] = true; + + // Decode this element + ASN1Template t = e.getTemplate(); + ASN1Value val; + CountingStream countstream = new CountingStream(istream); + if( e.getImplicitTag() == null ) { + val = t.decode(countstream); + } else { + val = t.decode(e.getImplicitTag(), countstream); + } + + // Decrement remaining count + long len = countstream.getNumRead(); + if( remainingContent != -1 ) { + if( remainingContent < len ) { + // this item went past the end of the SET + throw new InvalidBERException("Item went "+ + (len-remainingContent)+" bytes past the end of"+ + " the SET"); + } + remainingContent -= len; + } + + // Store this element in the SET + SET.Element se; + if( e.getImplicitTag() == null ) { + // no implicit tag + se = new SET.Element(val); + } else { + // there is an implicit tag + se = new SET.Element( e.getImplicitTag(), val ); + } + set.addElement(se); + } + + // We check for this after we read in each item, so this shouldn't + // happen + Assert.assert( remainingContent == 0 || remainingContent == -1); + + // Deal with elements that weren't present. + int size = elements.size(); + for(int i = 0; i < size; i++) { + if( !found[i] ) { + if( isOptionalAt(i) || isRepeatableAt(i) ) { + // no problem + } else if( defaultAt(i) != null ) { + set.addElement( new SET.Element(defaultAt(i)) ); + } else { + throw new InvalidBERException("Field not found in SET"); + } + } + } + + return set; + + } catch(InvalidBERException e) { + throw new InvalidBERException(e, "SET"); + } + } + + + /** + * Returns the index in the vector of the type with this tag and class, + * or -1 if not found. + * lame linear search - but we're dealing with small numbers of elements, + * so it's probably not worth it to use a hashtable + */ + private int findElementByTag(Tag tag) { + int size = elements.size(); + + for( int i = 0; i < size ; i++ ) { + Element e = (Element) elements.elementAt(i); + if( e.tagMatch( tag ) ) { + // match! + return i; + } + } + + // no match + return -1; + } + + /** + * An element of a SET template. + */ + public static class Element { + + public Element(Tag implicitTag, ASN1Template type, boolean optional) + { + this.type = type; + defaultVal = null; + this.optional = optional; + this.implicitTag = implicitTag; + } + + public Element(Tag implicitTag, ASN1Template type, ASN1Value defaultVal) + { + this.type = type; + this.defaultVal = defaultVal; + optional = false; + this.implicitTag = implicitTag; + } + + // Repeatability is used for SET OF. It is package private. + private boolean repeatable; + void makeRepeatable() { + repeatable = true; + } + boolean isRepeatable() { + return repeatable; + } + + private boolean optional; + public boolean isOptional() { + return optional; + } + + private Tag implicitTag=null; + public Tag getImplicitTag() { + return implicitTag; + } + + /** + * Determines whether the given tag satisfies this SET element. + */ + public boolean tagMatch(Tag tag) { + if( implicitTag != null ) { + return( implicitTag.equals(tag) ); + } else { + return type.tagMatch(tag); + } + } + + private ASN1Template type; + /** + * Returns the template for this element. + */ + public ASN1Template getTemplate() { + return type; + } + + private ASN1Value defaultVal=null; + /** + * Returns the default value for this element, if one exists. + * Otherwise, returns null. + */ + public ASN1Value getDefault() { + return defaultVal; + } + } +} // End of SET.Template + +/** + * A Template for decoding SET OF values. + * Use this if you have a SIZE qualifier on your SET OF. + * The SET will consume as many instances of type as it can, rather than + * stopping after the first one. This is equivalent to SIZE (0..MAX). + * If you need something more restrictive, you can look at what gets parsed + * and decide whether it's OK or not yourself. + */ +public static class OF_Template implements ASN1Template { + + private OF_Template() { } + + private Template template; // a normal SET template + + /** + * Creates an OF_Template with the given type. For example: + *
+     * MySet ::= SET OF INTEGER;
+     * 
+ * A MySet template would be constructed with: + *
+     * SET.OF_Template mySetTemplate = new SET.OF_Template( new
+     *                                          INTEGER.Template() );
+     * 
+ */ + public OF_Template(ASN1Template type) { + template = new Template(); + Template.Element el = new Template.Element( null, type, false ); + el.makeRepeatable(); + template.addElement( el ); + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + /** + * Decodes a SET OF from its BER encoding. + */ + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + return template.decode(istream); + } + + /** + * Decodes a SET OF with an implicit tag from its BER + * encoding. + */ + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws IOException, InvalidBERException + { + return template.decode(implicitTag, istream); + } +} + + // Test driver for SET + public static void main(String args[]) { + + try { + + if(args.length > 0) { + + FileInputStream fin = new FileInputStream( args[0] ); + + Template t = new SET.Template(); + + t.addElement(new Tag(0), new INTEGER.Template() ); + t.addElement( new Tag(3), new INTEGER.Template() ); + t.addOptionalElement( new Tag(4), new INTEGER.Template() ); + t.addElement( new Tag(5), new INTEGER.Template(), new INTEGER(67) ); + t.addElement( new Tag(29), new BOOLEAN.Template() ); + t.addElement( new Tag(30), new BOOLEAN.Template(), new BOOLEAN(false) ); + t.addElement( new Tag(1), new INTEGER.Template() ); + t.addElement( new Tag(2), new INTEGER.Template() ); + + SET st = (SET) t.decode(new BufferedInputStream(fin) ); + + for(int i=0; i < st.size(); i++) { + ASN1Value v = st.elementAt(i); + if( v instanceof INTEGER ) { + INTEGER in = (INTEGER) st.elementAt(i); + System.out.println("INTEGER: "+in); + } else if( v instanceof BOOLEAN ) { + BOOLEAN bo = (BOOLEAN) st.elementAt(i); + System.out.println("BOOLEAN: "+bo); + } else { + System.out.println("Unknown value"); + } + } + + } else { + + + SET s = new SET(); + s.addElement( new Tag(0), new INTEGER(255) ); + s.addElement( new Tag(29), new BOOLEAN(true) ); + s.addElement( new Tag(1), new INTEGER(-322) ); + s.addElement( new Tag(2), new INTEGER(0) ); + s.addElement( new Tag(3), new INTEGER("623423948273") ); + + s.encode(System.out); + + } + + } catch( Exception e ) { + e.printStackTrace(); + } + + } + +} diff --git a/mozilla/security/jss/org/mozilla/jss/asn1/Tag.java b/mozilla/security/jss/org/mozilla/jss/asn1/Tag.java new file mode 100644 index 00000000000..7c611ad1e0a --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/asn1/Tag.java @@ -0,0 +1,211 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.asn1; + +import java.math.BigInteger; + +/** + * Represents an ASN.1 Tag. A tag consists of a class and a number. + */ +public class Tag { + + private long num; + /** + * Returns the tag number. + */ + public long getNum() { + return num; + } + + private Class tClass; + /** + * Returns the tag class. + */ + public Class getTagClass() { + return tClass; + } + + private Tag() { } + + /** + * A tag class. + */ + public static final Class UNIVERSAL = Class.UNIVERSAL; + /** + * A tag class. + */ + public static final Class APPLICATION = Class.APPLICATION; + /** + * A tag class. + */ + public static final Class CONTEXT_SPECIFIC = Class.CONTEXT_SPECIFIC; + /** + * A tag class. + */ + public static final Class PRIVATE = Class.PRIVATE; + + /** + * The end-of-contents marker for indefinite length encoding. + * It is encoded the same as an ASN.1 header whose tag is [UNIVERSAL 0]. + */ + public static final Tag END_OF_CONTENTS = new Tag( UNIVERSAL, 0 ); + + /** + * An alias for END_OF_CONTENTS. + */ + public static final Tag EOC = END_OF_CONTENTS; + + /** + * Creates a tag with the given class and number. + * @param clazz The class of the tag. + * @param num The tag number. + */ + public Tag(Class clazz, long num) { + tClass = clazz; + this.num = num; + } + + /** + * Creates a CONTEXT-SPECIFIC tag with the given tag number. + * @param num The tag number. + */ + public Tag(long num) { + this(Class.CONTEXT_SPECIFIC, num); + } + + /////////////////////////////////////////////////////////////////////// + // Tag Instances + // + // Since grabbing a context-specific tag is a very common operation, + // let's make singletons of the most frequently used tags. + /////////////////////////////////////////////////////////////////////// + private static final int numTagInstances = 10; + private static Tag tagInstances[] = new Tag[numTagInstances]; + static { + for(int i=0; i < numTagInstances; i++) { + tagInstances[i] = new Tag(i); + } + } + + /** + * Returns an instance of a context-specific tag with the given number. + * The returned instance may be singleton. It is usually more efficient to + * call this method than create your own context-specific tag. + */ + public static Tag get(long num) { + if( num >= 0 && num < numTagInstances ) { + return tagInstances[(int)num]; + } else { + return new Tag(num); + } + } + + public int hashCode() { + return (tClass.toInt() * 131) + (int)num; + } + + /** + * Compares two tags for equality. Tags are equal if they have + * the same class and tag number. + */ + public boolean equals(Object obj) { + if(obj == null) { + return false; + } + if(! (obj instanceof Tag) ) { + return false; + } + + Tag t = (Tag) obj; + if( num == t.num && tClass == t.tClass ) { + return true; + } else { + return false; + } + } + + /** + * Returns a String representation of the tag. For example, a tag + * whose class was UNIVERSAL and whose number was 16 would return + * "UNIVERSAL 16". + */ + public String toString() { + return tClass+" "+num; + } + + /** + * An enumeration of the ASN.1 tag classes. + */ + public static class Class { + + private Class() { } + private Class(int enc, String name) { + encoding = enc; + this.name = name; + } + private int encoding; + private String name; + + public static final Class UNIVERSAL = new Class(0, "UNIVERSAL"); + public static final Class APPLICATION = new Class(1, "APPLICATION"); + public static final Class CONTEXT_SPECIFIC = + new Class(2, "CONTEXT-SPECIFIC"); + public static final Class PRIVATE = new Class(3, "PRIVATE"); + + public int toInt() { + return encoding; + } + + public String toString() { + return name; + } + + /** + * @exception InvalidBERException If the given int does not correspond + * to any tag class. + */ + public static Class fromInt(int i) throws InvalidBERException { + if( i == 0 ) { + return UNIVERSAL; + } else if(i == 1) { + return APPLICATION; + } else if(i == 2) { + return CONTEXT_SPECIFIC; + } else if(i == 3) { + return PRIVATE; + } else { + throw new InvalidBERException("Invalid tag class: " + i); + } + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/asn1/TeletexString.java b/mozilla/security/jss/org/mozilla/jss/asn1/TeletexString.java new file mode 100644 index 00000000000..dd124ee025f --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/asn1/TeletexString.java @@ -0,0 +1,127 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.asn1; + +import java.io.CharConversionException; + +/** + * The ASN.1 type TeletexString. + */ +public class TeletexString extends CharacterString implements ASN1Value { + + public static final Tag TAG = new Tag(Tag.UNIVERSAL, 20); + public Tag getTag() { + return TAG; + } + + public TeletexString(char[] chars) throws CharConversionException { + super(chars); + } + + public TeletexString(String s) throws CharConversionException { + super(s); + } + + CharConverter getCharConverter() { + return new TeletexConverter(); + } + + /** + * Returns a singleton instance of the decoding template for this class. + */ + public static Template getTemplate() { + return templateInstance; + } + private static final Template templateInstance = new Template(); + +// nested class +public static class Template + extends CharacterString.Template implements ASN1Template +{ + + protected Tag getTag() { + return TAG; + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + protected CharConverter getCharConverter() { + return new TeletexConverter(); + } + + protected CharacterString generateInstance(char[] bytes) + throws CharConversionException + { + return new TeletexString( bytes ); + } + + protected String typeName() { + return "TeletexString"; + } +} // end of Template + + private static class TeletexConverter implements CharConverter { + + public char[] byteToChar(byte[] bytes, int offset, int len) + throws CharConversionException + { + char[] chars = new char[len]; + + int b; + int c; + for(b=offset, c=0; c < len; b++, c++) { + chars[c] = (char) (bytes[b] & 0xff); + } + return chars; + } + + public byte[] charToByte(char[] chars, int offset, int len) + throws CharConversionException + { + byte[] bytes = new byte[len]; + + int b; + int c; + for(b=0, c=offset; b < len; b++, c++) { + if( (chars[c]&0xff00) != 0 ) { + throw new CharConversionException("Invalid character for"+ + " TeletexString"); + } + bytes[b] = (byte) (chars[c] & 0xff); + } + return bytes; + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/asn1/TimeBase.java b/mozilla/security/jss/org/mozilla/jss/asn1/TimeBase.java new file mode 100644 index 00000000000..659c3cd563e --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/asn1/TimeBase.java @@ -0,0 +1,317 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.asn1; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; +import java.util.Calendar; +import java.util.Date; +import java.util.TimeZone; +import com.netscape.jss.util.Assert; + +public abstract class TimeBase implements ASN1Value { + + public static final Form FORM = Form.PRIMITIVE; + abstract public Tag getTag(); + + private Date date; + + public Date toDate() { + return date; + } + + abstract protected boolean isUTC(); + + private TimeBase() { } + + public TimeBase(Date date) { + this.date = date; + } + + public void encode(OutputStream ostream) throws IOException { + encode(getTag(), ostream); + } + + /** + * Write the DER-encoding of this TimeBase. + */ + public void encode(Tag implicit, OutputStream ostream) throws IOException { + + if( isUTC() ) { + // length will always be 13 + (new ASN1Header(implicit, FORM, 13)).encode(ostream); + } else { + // length will always be 15 + (new ASN1Header(implicit, FORM, 15)).encode(ostream); + } + + int i=0, val; + + // DER-encoding mandates GMT time zone + Calendar cal = Calendar.getInstance( TimeZone.getTimeZone("GMT") ); + cal.setTime( date ); + + if( isUTC() ) { + val = cal.get(Calendar.YEAR); + ostream.write( ((val % 100) / 10) + '0' ); + ostream.write( (val % 10) + '0' ); + } else { + val = cal.get(Calendar.YEAR); + ostream.write( ((val % 10000) / 1000) + '0' ); + ostream.write( ((val % 1000) / 100) + '0' ); + ostream.write( ((val % 100) / 10) + '0' ); + ostream.write( (val % 10) + '0' ); + } + + val = cal.get(Calendar.MONTH) + 1; + Assert.assert( val >= 1 && val <= 12 ); + ostream.write( (val / 10) + '0' ); + ostream.write( (val % 10) + '0' ); + + val = cal.get(Calendar.DAY_OF_MONTH); + Assert.assert( val >=1 && val <= 31 ); + ostream.write( (val / 10) + '0' ); + ostream.write( (val % 10) + '0' ); + + val = cal.get(Calendar.HOUR_OF_DAY); + Assert.assert( val >= 0 && val <= 23 ); + ostream.write( (val / 10) + '0' ); + ostream.write( (val % 10) + '0' ); + + val = cal.get(Calendar.MINUTE); + Assert.assert( val >=0 && val <= 59 ); + ostream.write( (val / 10) + '0' ); + ostream.write( (val % 10) + '0' ); + + val = cal.get(Calendar.SECOND); + Assert.assert( val >= 0 && val <= 59 ); + ostream.write( (val / 10) + '0' ); + ostream.write( (val % 10) + '0' ); + + ostream.write('Z'); + } + + public abstract static class Template { + + protected abstract boolean isUTC(); + + protected abstract Tag getTag(); + + protected abstract TimeBase generateInstance(Date date); + + public boolean tagMatch(Tag tag) { + return getTag().equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + return decode(getTag(), istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws IOException, InvalidBERException + { + PrintableString.Template pst = new PrintableString.Template(); + PrintableString ps = (PrintableString) + pst.decode(implicitTag, istream); + char[] chars = ps.toCharArray(); + int i=0; + int year, month, day, hour, minute, second, hourOff, minOff; + + ////////////////////////////////////////// + // Get year + // + if( isUTC() ) { + checkBounds(i, 2, chars.length); + year = (chars[i] - '0') * 10; + year += chars[i+1] - '0'; + + // Y2K HACK!!!!! But this is what the spec says to do. + // The range is 1970 to 2069 + if( year < 70 ) { + year += 2000; + } else { + year += 1900; + } + i += 2; + } else { + checkBounds(i, 4, chars.length); + year = (chars[i] - '0') * 1000; + year += (chars[i+1] - '0') * 100; + year += (chars[i+2] - '0') * 10; + year += (chars[i+3] - '0'); + checkRange(year, 0, 9999, "year"); + i += 4; + } + + ////////////////////////////////////////// + // get month + // + month = 0; + checkBounds(i, 2, chars.length); + month = (chars[i] - '0') * 10; + month += chars[i+1] - '0'; + checkRange(month, 1, 12, "month"); + month--; // Java months start at 0 + i += 2; + + ////////////////////////////////////////// + // get day + // + checkBounds(i, 2, chars.length); + day = (chars[i] - '0') * 10; + day += chars[i+1] - '0'; + checkRange(day, 1, 31, "day"); + i += 2; + + ////////////////////////////////////////// + // get hour + // + checkBounds(i, 2, chars.length); + hour = (chars[i] - '0') * 10; + hour += chars[i+1] - '0'; + checkRange(hour, 0, 23, "hour"); + i += 2; + + ////////////////////////////////////////// + // get minute + // + checkBounds(i, 2, chars.length); + minute = (chars[i] - '0') * 10; + minute += chars[i+1] - '0'; + checkRange(minute, 0, 59, "minute"); + i += 2; + + ////////////////////////////////////////// + // get second, if it's there + // + if( i < chars.length && chars[i] >= '0' && chars[i] <= '9' ) { + checkBounds(i, 2, chars.length); + second = (chars[i] - '0') * 10; + second += chars[i+1] - '0'; + checkRange(second, 0, 59, "second"); + i += 2; + } else { + second = 0; + } + + ////////////////////////////////////////// + // Skip milliseconds for GeneralizedTime. There are no + // milliseconds in UTCTime. + // + if( ! isUTC() ) { + while( i < chars.length && + chars[i] != '+' && + chars[i] != '-' && + chars[i] != 'Z' ) + { + i++; + } + } + + ////////////////////////////////////////// + // get time zone + // + TimeZone tz; + if( i < chars.length ) { + checkBounds(i, 1, chars.length); + if( chars[i] == '+' || chars[i] == '-') { + checkBounds(i+1, 4, chars.length); + hourOff = (chars[i+1] - '0') * 10; + hourOff += chars[i+2] - '0'; + minOff = (chars[i+3] - '0') * 10; + minOff += chars[i+4] - '0'; + i += 5; + checkRange(hourOff, 0, 23, "hour offset"); + checkRange(minOff, 0, 59, "minute offset"); + if( chars[i] == '-' ) { + hourOff = -hourOff; + minOff = -minOff; + } + tz = (TimeZone) TimeZone.getTimeZone("GMT").clone(); + tz.setRawOffset( ((hourOff*60)+minOff)*60*1000 ); + } else if( chars[i] == 'Z' ) { + i += 1; + hourOff = minOff = 0; + tz = (TimeZone) TimeZone.getTimeZone("GMT").clone(); + } else { + throw new InvalidBERException("Invalid character "+ + chars[i]); + } + } else { + if( isUTC() ) { + // Only UTC requires timezone + throw new InvalidBERException("no timezone specified for"+ + " UTCTime"); + } + // No timezone specified, use local time. + // This is generally a bad idea, because who knows what the + // local timezone is? But the spec allows it. + tz = TimeZone.getDefault(); + } + + // make sure we ate all the characters, there were no stragglers + // at the end + if( i != chars.length ) { + throw new InvalidBERException("Extra characters at end"); + } + + // Create a calendar object from the date and time zone. + Calendar cal = Calendar.getInstance( tz ); + cal.set(year, month, day, hour, minute, second); + + return generateInstance(cal.getTime()); + } + + private static void + checkRange(int val, int low, int high, String field) + throws InvalidBERException + { + if( val < low || val > high ) { + throw new InvalidBERException("Invalid "+field); + } + } + + private static void + checkBounds(int index, int increment, int bound) + throws InvalidBERException + { + if(index+increment > bound) { + throw new InvalidBERException("Too few characters in " + + "TimeBase"); + } + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/asn1/UTCTime.java b/mozilla/security/jss/org/mozilla/jss/asn1/UTCTime.java new file mode 100644 index 00000000000..bce6ef40433 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/asn1/UTCTime.java @@ -0,0 +1,78 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.asn1; + +import java.io.IOException; +import java.util.Date; + +public class UTCTime extends TimeBase implements ASN1Value { + + public static final Tag TAG = new Tag(Tag.UNIVERSAL, 23); + public Tag getTag() { + return TAG; + } + + public UTCTime(Date date) { + super(date); + } + + protected boolean isUTC() { + return true; + } + + private static final UTCTime.Template templateInstance = + new UTCTime.Template(); + public static UTCTime.Template getTemplate() { + return templateInstance; + } + + public static class Template extends TimeBase.Template + implements ASN1Template + { + protected Tag getTag() { + return TAG; + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + protected boolean isUTC() { + return true; + } + + protected TimeBase generateInstance(Date date) { + return new UTCTime(date); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/asn1/UTF8String.java b/mozilla/security/jss/org/mozilla/jss/asn1/UTF8String.java new file mode 100644 index 00000000000..67ec9e4cf15 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/asn1/UTF8String.java @@ -0,0 +1,129 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.asn1; + +import java.io.CharConversionException; +import java.io.UnsupportedEncodingException; +import com.netscape.jss.util.Assert; + +public class UTF8String extends CharacterString implements ASN1Value { + + public UTF8String(char[] chars) throws CharConversionException { + super(chars); + } + + public UTF8String(String s) throws CharConversionException { + super(s); + } + + CharConverter getCharConverter() { + return new UTF8Converter(); + } + + public static final Tag TAG = new Tag( Tag.UNIVERSAL, 12 ); + public static final Form FORM = Form.PRIMITIVE; + + public Tag getTag() { + return TAG; + } + + private static final Template templateInstance = new Template(); + /** + * Returns a singleton instance of UTF8String.Template. This is more + * efficient than creating a new UTF8String.Template. + */ + public static Template getTemplate() { + return templateInstance; + } + +// nested class +public static class Template + extends CharacterString.Template implements ASN1Template +{ + protected Tag getTag() { + return TAG; + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + protected CharConverter getCharConverter() { + return new UTF8Converter(); + } + + protected CharacterString generateInstance(char[] chars) + throws CharConversionException + { + return new UTF8String(chars); + } + + protected String typeName() { + return "UTF8String"; + } +} + +private static class UTF8Converter implements CharConverter { + + public char[] byteToChar(byte[] bytes, int offset, int len) + throws CharConversionException + { + try { + + String s = new String(bytes, offset, len, "UTF8"); + return s.toCharArray(); + + } catch( UnsupportedEncodingException e ) { + String err = "Unable to find UTF8 encoding mechanism"; + Assert.notReached(err); + throw new CharConversionException(err); + } + } + + public byte[] charToByte(char[] chars, int offset, int len) + throws CharConversionException + { + try { + + String s = new String(chars, offset, len); + return s.getBytes("UTF8"); + + } catch( UnsupportedEncodingException e ) { + String err = "Unable to find UTF8 encoding mechanism"; + Assert.notReached(err); + throw new CharConversionException(err); + } + } +} // end of char converter + +} diff --git a/mozilla/security/jss/org/mozilla/jss/asn1/UniversalString.java b/mozilla/security/jss/org/mozilla/jss/asn1/UniversalString.java new file mode 100644 index 00000000000..efc74907ee9 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/asn1/UniversalString.java @@ -0,0 +1,229 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.asn1; + +import java.io.CharConversionException; +import java.io.CharArrayWriter; +import java.io.ByteArrayOutputStream; + +/** + * A UCS4 string. + */ +public class UniversalString extends CharacterString implements ASN1Value { + + public static final Tag TAG = new Tag(Tag.UNIVERSAL, 28); + public Tag getTag() { + return TAG; + } + + public UniversalString(char[] chars) throws CharConversionException { + super(chars); + } + + public UniversalString(String s) throws CharConversionException { + super(s); + } + + CharConverter getCharConverter() { + return new UniversalConverter(); + } + + /** + * Returns a singleton instance of the decoding template for this class. + */ + public static Template getTemplate() { + return templateInstance; + } + private static final Template templateInstance = new Template(); + +// nested class +public static class Template + extends CharacterString.Template implements ASN1Template +{ + protected Tag getTag() { + return TAG; + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + protected CharConverter getCharConverter() { + return new UniversalConverter(); + } + + protected CharacterString generateInstance(char[] chars) + throws CharConversionException + { + return new UniversalString( chars ); + } + + protected String typeName() { + return "UniversalString"; + } +} // end of Template + + /** + * A class for converting between Unicode and UCS4. + */ + private static class UniversalConverter implements CharConverter { + + // This is the maximum a UCS4 character can be if it has + // straight Unicode inside it. + public static final int MAX_UNICODE = 0x0000ffff; + + // This is the maximum a UCS4 character can be if it is UTF-16 + // encoded. UTF-16 encoding allows UCS4 chars to be stored across + // two Unicode chars. + public static final int MAX_UTF16 = 0x0010ffff; + + // This Unicode character is used to represent an unknown character + // in some other encoding. We use it for UCS4 characters that + // are not a part of normal Unicode and also cannot be encoded + // across two Unicode chars with UTF-16. + public static final char REPLACEMENT_CHAR = 0xfffd; + + // This is the base for UCS4 characters that can be mapped with UTF16. + public static final int UTF16_BASE = 0x00100000; + + + // In UTF16 encoding, each Unicode character has 10 bits of + // information. + public static final int HALF_SHIFT = 10; + + // The lowest 10 bits + public static final int HALF_MASK = 0x3ff; + + public static final int UTF16_HIGH_START = 0xd800; + public static final int UTF16_HIGH_END = 0xdcff; + public static final int UTF16_LOW_START = 0xdc00; + public static final int UTF16_LOW_END = 0xdfff; + + /** + * Turns big-endian UCS4 characters into Unicode Java characters + */ + public char[] byteToChar(byte[] bytes, int offset, int len) + throws CharConversionException + { + // Each UCS4 character is 4 bytes. Most UCS4 characters will + // map to one Unicode character. The exception is UTF-16 + // characters, which map to two Unicode characters. + CharArrayWriter out = new CharArrayWriter( len / 4 ); + + int end = offset + len; + + while( offset < end ) { + // eat 4 bytes and make a UCS4 char + if( end - offset < 4 ) { + throw new CharConversionException("input exhausted"); + } + int ucs4 = (bytes[offset++] & 0xff) << 24; + ucs4 += (bytes[offset++] & 0xff) << 16; + ucs4 += (bytes[offset++] & 0xff) << 8; + ucs4 += bytes[offset++] & 0xff; + + // convert UCS4 to Unicode + if( ucs4 <= MAX_UNICODE ) { + // Unicode is a subset of UCS4, and this char is + // in the common subset. Just chop off the unused top + // two bytes. + + out.write( ucs4 & 0xffff ); + + } else if( ucs4 <= MAX_UTF16 ) { + // This UCS4 char is not in Unicode, but can be encoded + // into two Unicode chars using UTF16. + + ucs4 -= UTF16_BASE; + out.write( (ucs4 >>> HALF_SHIFT) + UTF16_HIGH_START ); + out.write( (ucs4 & HALF_MASK) + UTF16_LOW_START ); + + } else { + // This character is not in Unicode or UTF16. We can't + // provide a suitable translation, so use the Unicode + // replacement char. + + out.write( REPLACEMENT_CHAR ); + + } + } + + return out.toCharArray(); + } + + // Convert Unicode chars to UCS4 chars + public byte[] charToByte(char[] chars, int offset, int len) + throws CharConversionException + { + ByteArrayOutputStream out = new ByteArrayOutputStream(len * 4); + + int end = offset + len; + + while( offset < end ) { + + char c = chars[offset++]; + int ucs4; + + if( c >= UTF16_HIGH_START && c <= UTF16_HIGH_END ) { + // This is the beginning of a UTF16 char + if( offset == end ) { + throw new CharConversionException("input exhausted"); + } + char low = chars[offset++]; + + // make sure the next char is the low half of a UTF16 char + if( low < UTF16_LOW_START || low > UTF16_LOW_END ) { + throw new CharConversionException("UTF16 high "+ + "character not followed by a UTF16 low character"); + } + + ucs4 = UTF16_BASE; + ucs4 += (c - UTF16_HIGH_START) << HALF_SHIFT; + ucs4 += low - UTF16_LOW_START; + + } else { + // this is a normal Unicode char + ucs4 = (c & 0x0000ffff); + } + + out.write( (ucs4 & 0xff000000) >>> 24 ); + out.write( (ucs4 & 0x00ff0000) >>> 16 ); + out.write( (ucs4 & 0x0000ff00) >>> 8 ); + out.write( (ucs4 & 0x000000ff) ); + } + + return out.toByteArray(); + } + + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/asn1/manifest.mn b/mozilla/security/jss/org/mozilla/jss/asn1/manifest.mn new file mode 100644 index 00000000000..ffd8897fee2 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/asn1/manifest.mn @@ -0,0 +1,110 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +CORE_DEPTH = ../../../../.. + +MODULE = ninja + +NS_USE_JDK = 1 + +PACKAGE = com/netscape/jss/asn1 + +CLASSES = \ + ANY \ + ASN1Header \ + ASN1Template \ + ASN1Util \ + ASN1Value \ + BIT_STRING \ + BMPString \ + BOOLEAN \ + CharacterString \ + CharConverter \ + CHOICE \ + CountingStream \ + ENUMERATED \ + EXPLICIT \ + FieldNotPresentException \ + Form \ + GeneralizedTime \ + IA5String \ + INTEGER \ + InvalidBERException \ + NULL \ + OBJECT_IDENTIFIER \ + OCTET_STRING \ + PrintableString \ + SEQUENCE \ + SET \ + Tag \ + TeletexString \ + TimeBase \ + UniversalString \ + UTCTime \ + UTF8String \ + $(NULL) + +JSRCS = \ + ANY.java \ + ASN1Header.java \ + ASN1Template.java \ + ASN1Util.java \ + ASN1Value.java \ + BIT_STRING.java \ + BMPString.java \ + BOOLEAN.java \ + CharacterString.java \ + CharConverter.java \ + CHOICE.java \ + CountingStream.java \ + ENUMERATED.java \ + EXPLICIT.java \ + FieldNotPresentException.java \ + Form.java \ + GeneralizedTime.java \ + IA5String.java \ + INTEGER.java \ + InvalidBERException.java \ + NULL.java \ + OBJECT_IDENTIFIER.java \ + OCTET_STRING.java \ + PrintableString.java \ + SEQUENCE.java \ + SET.java \ + Tag.java \ + TeletexString.java \ + TimeBase.java \ + UniversalString.java \ + UTCTime.java \ + UTF8String.java \ + $(NULL) diff --git a/mozilla/security/jss/org/mozilla/jss/asn1/package.html b/mozilla/security/jss/org/mozilla/jss/asn1/package.html new file mode 100644 index 00000000000..4f72ddd7fab --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/asn1/package.html @@ -0,0 +1,37 @@ + + + +ASN.1 structures, BER decoding, and DER encoding. + + diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/Algorithm.c b/mozilla/security/jss/org/mozilla/jss/crypto/Algorithm.c new file mode 100644 index 00000000000..f2a7f9a1251 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/Algorithm.c @@ -0,0 +1,523 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "_jni/com_netscape_jss_crypto_Algorithm.h" +#include "Algorithm.h" + +static PRStatus +getAlgInfo(JNIEnv *env, jobject alg, JSS_AlgInfo *info); + +/*********************************************************************** +** +** Algorithm indices. This must be kept in sync with the algorithm +** tags in the Algorithm class. +** We only store CKMs as a last resort if there is no corresponding +** SEC_OID. +**/ +JSS_AlgInfo JSS_AlgTable[NUM_ALGS] = { +/* 0 */ {SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION, SEC_OID_TAG}, +/* 1 */ {SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION, SEC_OID_TAG}, +/* 2 */ {SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION, SEC_OID_TAG}, +/* 3 */ {SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST, SEC_OID_TAG}, +/* 4 */ {SEC_OID_PKCS1_RSA_ENCRYPTION, SEC_OID_TAG}, +/* 5 */ {CKM_RSA_PKCS_KEY_PAIR_GEN, PK11_MECH}, +/* 6 */ {CKM_DSA_KEY_PAIR_GEN, PK11_MECH}, +/* 7 */ {SEC_OID_ANSIX9_DSA_SIGNATURE, SEC_OID_TAG}, +/* 8 */ {SEC_OID_RC4, SEC_OID_TAG}, +/* 9 */ {SEC_OID_DES_ECB, SEC_OID_TAG}, +/* 10 */ {SEC_OID_DES_CBC, SEC_OID_TAG}, +/* 11 */ {CKM_DES_CBC_PAD, PK11_MECH}, +/* 12 */ {CKM_DES3_ECB, PK11_MECH}, +/* 13 */ {SEC_OID_DES_EDE3_CBC, SEC_OID_TAG}, +/* 14 */ {CKM_DES3_CBC_PAD, PK11_MECH}, +/* 15 */ {CKM_DES_KEY_GEN, PK11_MECH}, +/* 16 */ {CKM_DES3_KEY_GEN, PK11_MECH}, +/* 17 */ {CKM_RC4_KEY_GEN, PK11_MECH}, +/* 18 */ {SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC, SEC_OID_TAG}, +/* 19 */ {SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC, SEC_OID_TAG}, +/* 20 */ {SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC, SEC_OID_TAG}, +/* 21 */ {SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4, SEC_OID_TAG}, +/* 22 */ {SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4, SEC_OID_TAG}, +/* 23 */ {SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC, + SEC_OID_TAG}, +/* 24 */ {SEC_OID_MD2, SEC_OID_TAG}, +/* 25 */ {SEC_OID_MD5, SEC_OID_TAG}, +/* 26 */ {SEC_OID_SHA1, SEC_OID_TAG}, +/* 27 */ {CKM_SHA_1_HMAC, PK11_MECH}, +/* 28 */ {SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC, SEC_OID_TAG}, +/* 29 */ {SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC, SEC_OID_TAG}, +/* 30 */ {SEC_OID_RC2_CBC, SEC_OID_TAG}, +/* 31 */ {CKM_PBA_SHA1_WITH_SHA1_HMAC, PK11_MECH} + +/* REMEMBER TO UPDATE NUM_ALGS!!! */ +}; + + +/*********************************************************************** + * + * A l g o r i t h m . g e t A l l A l g o r i t h m I n d i c e s + * + * INPUTS + * jUsage + * An enum corresponding to a unique usage. + * RETURNS + * An object containing all algorithms supported by this object. + */ +JNIEXPORT jlongArray JNICALL +Java_com_netscape_jss_crypto_Algorithm_getAllAlgorithmIndices +( JNIEnv *env, jclass this, jobject jUsage ) +{ + /* "JNI" data members */ + jlongArray javatable; + jlong* table; + jmethodID jGetID; + jint usage; + jthrowable jExcep; + + /* Perform initial assertions */ + PR_ASSERT( env != NULL ); + + /* Create a new java table for the algorithms */ + javatable = (*env)->NewLongArray( env, NUM_ALGS ); + + /* Create a new "C" table for the algorithms */ + table = (*env)->GetLongArrayElements( env, javatable, NULL ); + + /* Lookup java method ID */ + jGetID = ( *env )->GetMethodID( env, jUsage, "getID", "I" ); + if( jGetID == NULL ) { + ASSERT_OUTOFMEM( env ); + goto loser; + } + + /* Call java method */ + usage = ( *env )->CallIntMethod( env, jUsage, jGetID ); + if( usage == 0 ) { + ASSERT_OUTOFMEM( env ); + goto loser; + } + + /* Call the appropriate jUsage routine */ + switch( usage ) { + case JSS_CERT_SIGNING: + JSS_GetAllAlgorithmIndicesForCertSigning( table ); + break; + case JSS_SSL_KEY_EXCHANGE: + JSS_GetAllAlgorithmIndicesForSSLKeyExchange( table ); + break; + case JSS_CRS_KEY_WRAP: + JSS_GetAllAlgorithmIndicesForCRSKeyWrap( table ); + break; + case JSS_CRS_BULK_ENCRYPTION: + JSS_GetAllAlgorithmIndicesForCRSBulkEncryption( table ); + break; + case JSS_PASSWORD_ENCRYPTION: + JSS_GetAllAlgorithmIndicesForPasswordEncryption( table ); + break; + case JSS_KRA_TRANSPORT: + JSS_GetAllAlgorithmIndicesForKRATransport( table ); + break; + case JSS_KRA_STORAGE: + JSS_GetAllAlgorithmIndicesForKRAStorage( table ); + break; + case JSS_KRA_PKCS_12: + JSS_GetAllAlgorithmIndicesForKRAPKCS12( table ); + break; + default: + return NULL; + } + + /* Copy the contents of the "C" table into the "java" table */ + (*env)->ReleaseLongArrayElements( env, javatable, table, 0 ); + + return javatable; + +loser: + + /* Save the java exception and rethrow it */ + jExcep = ( *env )->ExceptionOccurred( env ); + PR_ASSERT( jExcep != NULL ); + + /* Return from exception */ + return( NULL ); +} + +/*********************************************************************** + * + * A l g o r i t h m . g e t S t r o n g e s t K e y S i z e + * + * INPUTS + * jUsage + * An enum corresponding to a unique usage. Must not be NULL. + * alg + * An algorithm corresponding to one listed in Algorithm.java. + * RETURNS + * A byte array containing the maximum key size supported by + * this object, or NULL if not supported by this object. + * NOTE + * All unusable key sizes are stored as 0L. + */ +JNIEXPORT jint JNICALL +Java_com_netscape_jss_crypto_Algorithm_getStrongestKeySize +( JNIEnv *env, jclass this, jobject jUsage, jint alg ) +{ + /* "JNI" data members */ + jmethodID jGetID; + jint usage; + jthrowable jExcep; + jclass usageClass; + + /* "C" data members */ + unsigned long maxkeysize; + + /* Perform initial assertions */ + PR_ASSERT( env != NULL && alg < NUM_ALGS ); + + /* Lookup java method ID */ + usageClass = (*env)->GetObjectClass(env, jUsage); + jGetID = ( *env )->GetMethodID( env, usageClass, "getID", "()I" ); + if( jGetID == NULL ) { + ASSERT_OUTOFMEM( env ); + goto loser; + } + + /* Call java method */ + usage = ( *env )->CallIntMethod( env, jUsage, jGetID ); + if( usage == 0 ) { + ASSERT_OUTOFMEM( env ); + goto loser; + } + + /* Call the appropriate jUsage routine */ + switch( usage ) { + case JSS_CERT_SIGNING: + maxkeysize = JSS_GetStrongestKeySizeFromCertSigning( alg ); + break; + case JSS_SSL_KEY_EXCHANGE: + maxkeysize = JSS_GetStrongestKeySizeFromSSLKeyExchange( alg ); + break; + case JSS_CRS_KEY_WRAP: + maxkeysize = JSS_GetStrongestKeySizeFromCRSKeyWrap( alg ); + break; + case JSS_CRS_BULK_ENCRYPTION: + maxkeysize = JSS_GetStrongestKeySizeFromCRSBulkEncryption( alg ); + break; + case JSS_PASSWORD_ENCRYPTION: + maxkeysize = JSS_GetStrongestKeySizeFromPasswordEncryption( alg ); + break; + case JSS_KRA_TRANSPORT: + maxkeysize = JSS_GetStrongestKeySizeFromKRATransport( alg ); + break; + case JSS_KRA_STORAGE: + maxkeysize = JSS_GetStrongestKeySizeFromKRAStorage( alg ); + break; + case JSS_KRA_PKCS_12: + maxkeysize = JSS_GetStrongestKeySizeFromKRAPKCS12( alg ); + break; + default: + return 0; + } + + /* Assert that key size will never be larger than 32 bits */ + PR_ASSERT( maxkeysize == ( maxkeysize & 0x7fffffffL ) ); + + /* Return */ + return ( jint ) maxkeysize; + +loser: + + /* Save the java exception and rethrow it */ + jExcep = ( *env )->ExceptionOccurred( env ); + PR_ASSERT( jExcep != NULL ); + + /* Return from exception */ + return( 0 ); +} + +/*********************************************************************** + * + * A l g o r i t h m . i s A l l o w e d + * + * INPUTS + * jUsage + * An enum corresponding to a unique usage. Must not be NULL. + * alg + * An algorithm corresponding to one listed in Algorithm.java. + * RETURNS + * A boolean denoting whether or not the algorithm is allowed. + */ +JNIEXPORT jboolean JNICALL +Java_com_netscape_jss_crypto_Algorithm_isAllowed +( JNIEnv *env, jclass this, jobject jUsage, jint alg ) +{ + /* "JNI" data members */ + jmethodID jGetID; + jint usage; + jthrowable jExcep; + jclass usageClass; + + /* "C" data members */ + PRBool result; + + /* Perform initial assertions */ + PR_ASSERT( env != NULL && alg < NUM_ALGS ); + + /* Lookup java method ID */ + usageClass = (*env)->GetObjectClass(env, jUsage); + jGetID = ( *env )->GetMethodID( env, usageClass, "getID", "()I" ); + if( jGetID == NULL ) { + ASSERT_OUTOFMEM( env ); + goto loser; + } + + /* Call java method */ + usage = ( *env )->CallIntMethod( env, jUsage, jGetID ); + if( usage == 0 ) { + ASSERT_OUTOFMEM( env ); + goto loser; + } + + /* Call the appropriate jUsage routine */ + switch( usage ) { + case JSS_CERT_SIGNING: + result = JSS_isAllowedFromCertSigning( alg ); + break; + case JSS_SSL_KEY_EXCHANGE: + result = JSS_isAllowedFromSSLKeyExchange( alg ); + break; + case JSS_CRS_KEY_WRAP: + result = JSS_isAllowedFromCRSKeyWrap( alg ); + break; + case JSS_CRS_BULK_ENCRYPTION: + result = JSS_isAllowedFromCRSBulkEncryption( alg ); + break; + case JSS_PASSWORD_ENCRYPTION: + result = JSS_isAllowedFromPasswordEncryption( alg ); + break; + case JSS_KRA_TRANSPORT: + result = JSS_isAllowedFromKRATransport( alg ); + break; + case JSS_KRA_STORAGE: + result = JSS_isAllowedFromKRAStorage( alg ); + break; + case JSS_KRA_PKCS_12: + result = JSS_isAllowedFromKRAPKCS12( alg ); + break; + default: + return 0; + } + + /* Return a java boolean */ + if( result != PR_TRUE ) { + return JNI_FALSE; + } + + return JNI_TRUE; + +loser: + + /* Save the java exception and rethrow it */ + jExcep = ( *env )->ExceptionOccurred( env ); + PR_ASSERT( jExcep != NULL ); + + /* Return from exception */ + return( JNI_FALSE ); +} + +/*********************************************************************** + * + * J S S _ g e t P K 1 1 M e c h F r o m A l g + * + * INPUTS + * alg + * An com.netscape.jss.Algorithm object. Must not be NULL. + * RETURNS + * CK_MECHANISM_TYPE corresponding to this algorithm, or + * CKM_INVALID_MECHANISM if none exists. + */ +PR_IMPLEMENT( CK_MECHANISM_TYPE ) +JSS_getPK11MechFromAlg(JNIEnv *env, jobject alg) +{ + JSS_AlgInfo info; + + if( getAlgInfo(env, alg, &info) != PR_SUCCESS) { + return CKM_INVALID_MECHANISM; + } + if( info.type == PK11_MECH ) { + return (CK_MECHANISM_TYPE) info.val; + } else { + PR_ASSERT( info.type == SEC_OID_TAG ); + return PK11_AlgtagToMechanism( (SECOidTag) info.val); + } +} + +/*********************************************************************** + * + * J S S _ g e t O i d T a g F r o m A l g + * + * INPUTS + * alg + * An com.netscape.jss.Algorithm object. Must not be NULL. + * RETURNS + * SECOidTag corresponding to this algorithm, or SEC_OID_UNKNOWN + * if none was found. + */ +PR_IMPLEMENT( SECOidTag ) +JSS_getOidTagFromAlg(JNIEnv *env, jobject alg) +{ + JSS_AlgInfo info; + + if( getAlgInfo(env, alg, &info) != PR_SUCCESS) { + return SEC_OID_UNKNOWN; + } + if( info.type == SEC_OID_TAG ) { + return (SECOidTag) info.val; + } else { + PR_ASSERT( info.type == PK11_MECH ); + /* We only store things as PK11 mechanisms as a last resort if + * there is no corresponding sec oid tag. */ + return SEC_OID_UNKNOWN; + } +} + +/*********************************************************************** + * + * J S S _ g e t A l g I n d e x + * + * INPUTS + * alg + * An com.netscape.jss.Algorithm object. Must not be NULL. + * RETURNS + * The index obtained from the algorithm, or -1 if an exception was + * thrown. + */ +static jshort +getAlgIndex(JNIEnv *env, jobject alg) +{ + jclass algClass; + jshort index=-1; + jfieldID indexField; + + PR_ASSERT(env!=NULL && alg!=NULL); + + algClass = (*env)->GetObjectClass(env, alg); + +#ifdef DEBUG + /* Make sure this really is an Algorithm. */ + { + jclass realClass = ((*env)->FindClass(env, ALGORITHM_CLASS_NAME)); + PR_ASSERT( (*env)->IsInstanceOf(env, alg, realClass) ); + } +#endif + + indexField = (*env)->GetFieldID( + env, + algClass, + OID_INDEX_FIELD_NAME, + OID_INDEX_FIELD_SIG); + if(indexField==NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + index = (*env)->GetShortField(env, alg, indexField); + PR_ASSERT( (index >= 0) && (index < NUM_ALGS) ); + +finish: + return index; +} + +/*********************************************************************** + * + * J S S _ g e t E n u m F r o m A l g + * + * INPUTS + * alg + * An com.netscape.jss.Algorithm object. Must not be NULL. + * OUTPUTS + * info + * Pointer to a JSS_AlgInfo which will get the information about + * this algorithm, if it is found. Must not be NULL. + * RETURNS + * PR_SUCCESS if the enum was found, otherwise PR_FAILURE. + */ +static PRStatus +getAlgInfo(JNIEnv *env, jobject alg, JSS_AlgInfo *info) +{ + jshort index; + PRStatus status; + + PR_ASSERT(env!=NULL && alg!=NULL && info!=NULL); + + index = getAlgIndex(env, alg); + if( index == -1 ) { + goto finish; + } + *info = JSS_AlgTable[index]; + status = PR_SUCCESS; + +finish: + return status; +} + +/*********************************************************************** + * + * EncryptionAlgorithm.getIVLength + * + */ +JNIEXPORT jint JNICALL +Java_com_netscape_jss_crypto_EncryptionAlgorithm_getIVLength + (JNIEnv *env, jobject this) +{ + CK_MECHANISM_TYPE mech; + + mech = JSS_getPK11MechFromAlg(env, this); + + if( mech == CKM_INVALID_MECHANISM ) { + PR_ASSERT(PR_FALSE); + return 0; + } else { + return PK11_GetIVLength(mech); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/Algorithm.h b/mozilla/security/jss/org/mozilla/jss/crypto/Algorithm.h new file mode 100644 index 00000000000..29e0b977222 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/Algorithm.h @@ -0,0 +1,181 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +/* These headers must be included before this header: +#include +#include +#include +#include +*/ + +#ifndef JSS_ALGORITHM_H +#define JSS_ALGORITHM_H + +PR_BEGIN_EXTERN_C + +typedef enum JSS_AlgType { + PK11_MECH, /* CK_MECHANISM_TYPE */ + SEC_OID_TAG /* SECOidTag */ +} JSS_AlgType; + +typedef struct JSS_AlgInfoStr { + unsigned long val; /* either a CK_MECHANISM_TYPE or a SECOidTag */ + JSS_AlgType type; +} JSS_AlgInfo; + +#define NUM_ALGS 32 + +extern JSS_AlgInfo JSS_AlgTable[]; + +/* + * The following definitions relate to the export control policy + */ + +enum { + JSS_CERT_SIGNING=1, + JSS_SSL_KEY_EXCHANGE, + JSS_CRS_KEY_WRAP, + JSS_CRS_BULK_ENCRYPTION, + JSS_PASSWORD_ENCRYPTION, + JSS_KRA_TRANSPORT, + JSS_KRA_STORAGE, + JSS_KRA_PKCS_12 +}; + + +PR_EXTERN( void ) +JSS_GetAllAlgorithmIndicesForCertSigning( jlong* table ); + +PR_EXTERN( void ) +JSS_GetAllAlgorithmIndicesForSSLKeyExchange( jlong* table ); + +PR_EXTERN( void ) +JSS_GetAllAlgorithmIndicesForCRSKeyWrap( jlong* table ); + +PR_EXTERN( void ) +JSS_GetAllAlgorithmIndicesForCRSBulkEncryption( jlong* table ); + +PR_EXTERN( void ) +JSS_GetAllAlgorithmIndicesForPasswordEncryption( jlong* table ); + +PR_EXTERN( void ) +JSS_GetAllAlgorithmIndicesForKRATransport( jlong* table ); + +PR_EXTERN( void ) +JSS_GetAllAlgorithmIndicesForKRAStorage( jlong* table ); + +PR_EXTERN( void ) +JSS_GetAllAlgorithmIndicesForKRAPKCS12( jlong* table ); + + +PR_EXTERN( unsigned long ) +JSS_GetStrongestKeySizeFromCertSigning( jint alg ); + +PR_EXTERN( unsigned long ) +JSS_GetStrongestKeySizeFromSSLKeyExchange( jint alg ); + +PR_EXTERN( unsigned long ) +JSS_GetStrongestKeySizeFromCRSKeyWrap( jint alg ); + +PR_EXTERN( unsigned long ) +JSS_GetStrongestKeySizeFromCRSBulkEncryption( jint alg ); + +PR_EXTERN( unsigned long ) +JSS_GetStrongestKeySizeFromPasswordEncryption( jint alg ); + +PR_EXTERN( unsigned long ) +JSS_GetStrongestKeySizeFromKRATransport( jint alg ); + +PR_EXTERN( unsigned long ) +JSS_GetStrongestKeySizeFromKRAStorage( jint alg ); + +PR_EXTERN( unsigned long ) +JSS_GetStrongestKeySizeFromKRAPKCS12( jint alg ); + + +PR_EXTERN( PRBool ) +JSS_isAllowedFromCertSigning( jint alg ); + +PR_EXTERN( PRBool ) +JSS_isAllowedFromSSLKeyExchange( jint alg ); + +PR_EXTERN( PRBool ) +JSS_isAllowedFromCRSKeyWrap( jint alg ); + +PR_EXTERN( PRBool ) +JSS_isAllowedFromCRSBulkEncryption( jint alg ); + +PR_EXTERN( PRBool ) +JSS_isAllowedFromPasswordEncryption( jint alg ); + +PR_EXTERN( PRBool ) +JSS_isAllowedFromKRATransport( jint alg ); + +PR_EXTERN( PRBool ) +JSS_isAllowedFromKRAStorage( jint alg ); + +PR_EXTERN( PRBool ) +JSS_isAllowedFromKRAPKCS12( jint alg ); + + +/*********************************************************************** + * + * J S S _ g e t O i d T a g F r o m A l g + * + * INPUTS + * alg + * An com.netscape.jss.Algorithm object. Must not be NULL. + * RETURNS + * SECOidTag corresponding to this algorithm, or SEC_OID_UNKNOWN + * if none was found. + */ +PR_EXTERN( SECOidTag ) +JSS_getOidTagFromAlg(JNIEnv *env, jobject alg); + +/*********************************************************************** + * + * J S S _ g e t P K 1 1 M e c h F r o m A l g + * + * INPUTS + * alg + * An com.netscape.jss.Algorithm object. Must not be NULL. + * RETURNS + * CK_MECHANISM_TYPE corresponding to this algorithm, or + * CKM_INVALID_MECHANISM if none was found. + */ +PR_EXTERN( CK_MECHANISM_TYPE ) +JSS_getPK11MechFromAlg(JNIEnv *env, jobject alg); + +PR_END_EXTERN_C + +#endif diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/Algorithm.java b/mozilla/security/jss/org/mozilla/jss/crypto/Algorithm.java new file mode 100644 index 00000000000..5c196c8bff4 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/Algorithm.java @@ -0,0 +1,208 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.crypto; + +import com.netscape.jss.asn1.OBJECT_IDENTIFIER; +import java.security.NoSuchAlgorithmException; + +/** + * Represents a cryptographic algorithm. + * @see EncryptionAlgorithm + * @see SignatureAlgorithm + */ +public class Algorithm { + + private Algorithm() { } + + /** + * @param oidIndex Index of the oid that this algorithm represents. + * @param name A String representation of the Algorithm. + */ + protected Algorithm(int oidIndex, String name) { + this.oidIndex = oidIndex; + this.name = name; + } + + /** + * @param oidIndex Index of the oid that this algorithm represents. + * @param name A String representation of the Algorithm. + * @param oid The object identifier for this Algorithm. + */ + protected Algorithm(int oidIndex, String name, OBJECT_IDENTIFIER oid) { + this(oidIndex, name); + this.oid = oid; + } + + protected Algorithm(int oidIndex, String name, OBJECT_IDENTIFIER oid, + Class paramClass) + { + this(oidIndex, name, oid); + this.parameterClass = paramClass; + } + + /** + * Returns a String representation of the algorithm. + */ + public String toString() { + return name; + } + + /** + * Returns the object identifier for this algorithm. + * @exception NoSuchAlgorithmException If no OID is registered for this + * algorithm. + */ + public OBJECT_IDENTIFIER toOID() throws NoSuchAlgorithmException { + if( oid == null ) { + throw new NoSuchAlgorithmException(); + } else { + return oid; + } + } + + /** + * The type of parameter that this algorithm expects. Returns + * null if this algorithm does not take any parameters. + */ + public Class getParameterClass() { + return parameterClass; + } + + /** + * This method is used to report all algorithms associated with + * the requested usage. + * @param usage the designated export control policy + */ + protected static native long[] getAllAlgorithmIndices( Usage usage ); + + /** + * This method is used to retrieve the maximum key size allowed for + * this algorithm. + * @param usage the designated export control policy + */ + public int getStrongestKeySize( Usage usage ) { + return getStrongestKeySize( usage, oidIndex ); + } + + /** + * This method is used to determine whether or not this algorithm + * may be used. + * @param usage the designated export control policy + */ + public boolean isAllowed( Usage usage ) { + return isAllowed( usage, oidIndex ); + } + + private static native int getStrongestKeySize( Usage usage, int alg ); + + private static native boolean isAllowed( Usage usage, int alg ); + + /** + * Index into the SECOidTag array in Algorithm.c. + */ + protected int oidIndex; + String name; + protected OBJECT_IDENTIFIER oid; + private Class parameterClass=null; + + ////////////////////////////////////////////////////////////// + // Algorithm OIDs + ////////////////////////////////////////////////////////////// + static final OBJECT_IDENTIFIER ANSI_X9_ALGORITHM = + new OBJECT_IDENTIFIER( new long[] { 1, 2, 840, 10040, 4 } ); + + // Algorithm indices. These must be kept in sync with the + // algorithm array in Algorithm.c. + protected static final short SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION=0; + protected static final short SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION=1; + protected static final short SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION=2; + protected static final short SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST=3; + protected static final short SEC_OID_PKCS1_RSA_ENCRYPTION=4; + protected static final short CKM_RSA_PKCS_KEY_PAIR_GEN=5; + protected static final short CKM_DSA_KEY_PAIR_GEN=6; + protected static final short SEC_OID_ANSIX9_DSA_SIGNATURE=7; + protected static final short SEC_OID_RC4=8; + protected static final short SEC_OID_DES_ECB=9; + protected static final short SEC_OID_DES_CBC=10; + protected static final short CKM_DES_CBC_PAD=11; + protected static final short CKM_DES3_ECB=12; + protected static final short SEC_OID_DES_EDE3_CBC=13; + protected static final short CKM_DES3_CBC_PAD=14; + protected static final short CKM_DES_KEY_GEN=15; + protected static final short CKM_DES3_KEY_GEN=16; + protected static final short CKM_RC4_KEY_GEN=17; + + protected static final short SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC=18; + protected static final short SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC=19; + protected static final short SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC=20; + protected static final short + SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4=21; + protected static final short + SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4=22; + protected static final short + SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC=23; + protected static final short SEC_OID_MD2=24; + protected static final short SEC_OID_MD5=25; + protected static final short SEC_OID_SHA1=26; + protected static final short CKM_SHA_1_HMAC=27; + protected static final short + SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC=28; + protected static final short + SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC=29; + protected static final short SEC_OID_RC2_CBC=30; + protected static final short CKM_PBA_SHA1_WITH_SHA1_HMAC=31; + + // These must correspond one-to-one with "../Algorithm.h" enum values + public static final class Usage + { + private int id; + + private Usage( int index ) { + id = index; + } + + public int getID() { + return id; + } + + public static final Usage JAVA_CERT_SIGNING = new Usage( 1 ); + public static final Usage JAVA_SSL_KEY_EXCHANGE = new Usage( 2 ); + public static final Usage JAVA_CRS_KEY_WRAP = new Usage( 3 ); + public static final Usage JAVA_CRS_BULK_ENCRYPTION = new Usage( 4 ); + public static final Usage JAVA_PASSWORD_ENCRYPTION = new Usage( 5 ); + public static final Usage JAVA_KRA_TRANSPORT = new Usage( 6 ); + public static final Usage JAVA_KRA_STORAGE = new Usage( 7 ); + public static final Usage JAVA_KRA_PKCS_12 = new Usage( 8 ); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/AlreadyInitializedException.java b/mozilla/security/jss/org/mozilla/jss/crypto/AlreadyInitializedException.java new file mode 100644 index 00000000000..8e99569d955 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/AlreadyInitializedException.java @@ -0,0 +1,45 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.crypto; + +/** + * This exception is thrown if an initialization operation + * is attempted on something that is already initialized. + */ +public class AlreadyInitializedException extends java.lang.Exception { + public AlreadyInitializedException() {} + public AlreadyInitializedException(String mesg) { + super(mesg); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/BadPaddingException.java b/mozilla/security/jss/org/mozilla/jss/crypto/BadPaddingException.java new file mode 100644 index 00000000000..1dd66345c7e --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/BadPaddingException.java @@ -0,0 +1,42 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.crypto; + +public class BadPaddingException extends Exception { + public BadPaddingException() { + super(); + } + public BadPaddingException(String msg) { + super(msg); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/Cipher.java b/mozilla/security/jss/org/mozilla/jss/crypto/Cipher.java new file mode 100644 index 00000000000..989bfe442e7 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/Cipher.java @@ -0,0 +1,226 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.crypto; + +import java.security.InvalidKeyException; +import java.security.spec.AlgorithmParameterSpec; +import java.security.InvalidAlgorithmParameterException; +import com.netscape.jss.util.Assert; + +/** + * A context for performing symmetric encryption and decryption. + * First, the context must be initialized. Then, it can be updated + * with input through zero or more calls to update. Finally, + * doFinal is called to finalize the operation. Note that + * it is not necessary to call update if all of the data is + * available at once. In this case, all of the input can be processed with one + * call to doFinal. + */ +public abstract class Cipher { + + /** + * Initializes a encryption context with a symmetric key. + */ + public abstract void initEncrypt(SymmetricKey key) + throws InvalidKeyException, InvalidAlgorithmParameterException, + TokenException; + + /** + * Initializes a decryption context with a symmetric key. + */ + public abstract void initDecrypt(SymmetricKey key) + throws InvalidKeyException, InvalidAlgorithmParameterException, + TokenException; + + /** + * Initializes an encryption context with a symmetric key and + * algorithm parameters. + */ + public abstract void + initEncrypt(SymmetricKey key, AlgorithmParameterSpec parameters) + throws InvalidKeyException, InvalidAlgorithmParameterException, + TokenException; + + /** + * Initializes a decryption context with a symmetric key and + * algorithm parameters. + */ + public abstract void + initDecrypt(SymmetricKey key, AlgorithmParameterSpec parameters) + throws InvalidKeyException, InvalidAlgorithmParameterException, + TokenException; + + /** + * Updates the encryption context with additional input. + * @param bytes Bytes of plaintext (if encrypting) or ciphertext (if + * decrypting). + * @return Bytes of ciphertext (if encrypting) or plaintext (if decrypting). + */ + public abstract byte[] update(byte[] bytes) + throws IllegalStateException, TokenException; + + /** + * Updates the encryption context with additional plaintext. + * @param bytes Bytes of plaintext (if encrypting) or ciphertext (if + * decrypting). + * @param offset The index in bytes at which to begin reading. + * @param length The number of bytes from bytes to read. + * @return Bytes of ciphertext (if encrypting) or plaintext (if decrypting). + */ + public abstract byte[] update(byte[] bytes, int offset, int length) + throws IllegalStateException, TokenException; + + /** + * Completes an cipher operation. This can be called directly after + * the context is initialized, or update may be called + * any number of times before calling final. + * @param bytes Bytes of plaintext (if encrypting) or ciphertext (if + * decrypting). + * @return The last of the output. + */ + public abstract byte[] doFinal(byte[] bytes) + throws IllegalStateException, IllegalBlockSizeException, + BadPaddingException, TokenException; + + /** + * Completes an cipher operation. + * @param bytes Bytes of plaintext (if encrypting) or ciphertext (if + * decrypting). + * @param offset The index in bytes at which to begin reading. + * @param length The number of bytes from bytes to read. + * @return The last of the output. + */ + public abstract byte[] doFinal(byte[] bytes, int offset, int length) + throws IllegalStateException, IllegalBlockSizeException, + BadPaddingException, TokenException; + + /** + * Completes an cipher operation. + * @return The last of the output. + */ + public abstract byte[] doFinal() + throws IllegalStateException, IllegalBlockSizeException, + BadPaddingException, TokenException; + + /** + * Pads a byte array so that its length is a multiple of the given + * blocksize. The method of padding is the one defined in the RSA + * PKCS standards. If M is the length of the data and + * B is the block size, the padding string consists of + * B - (M mod B) octets, each having the value + * B - (M mod B). + * @param The block size of the encryption algorithm. Must be greater + * than zero. + * @see #unPad + */ + public static byte[] + pad(byte[] toBePadded, int blockSize) { + Assert.assert(blockSize > 0); + + // the padOctet is also the number of pad octets + byte padOctet = (byte) (blockSize - (toBePadded.length % blockSize)); + + byte[] padded = new byte[toBePadded.length + padOctet]; + + System.arraycopy(toBePadded, 0, padded, 0, toBePadded.length); + + for(int i = toBePadded.length; i < padded.length; i++) { + padded[i] = padOctet; + } + + return padded; + } + + /** + * Un-pads a byte array that is padded with PKCS padding. + * + * @param blockSize The block size of the encryption algorithm. This + * is only used for error checking: if the pad size is not + * between 1 and blockSize, a BadPaddingException is thrown. + * + * @see #pad + */ + public static byte[] + unPad(byte[] padded, int blockSize) throws BadPaddingException { + if(padded.length == 0) { + return new byte[0]; + } + + if( padded.length < blockSize ) { + throw new BadPaddingException("Length of padded array is less than"+ + " one block"); + } + byte padOctet = padded[padded.length-1]; + if(padOctet > blockSize) { + throw new BadPaddingException("Padding octet ("+padOctet+") is "+ + "larger than block size ("+blockSize+")"); + } + if(padOctet < 1) { + throw new BadPaddingException("Padding octet is less than 1"); + } + + byte[] unpadded = new byte[padded.length - padOctet]; + + System.arraycopy(padded, 0, unpadded, 0, unpadded.length); + + return unpadded; + } + + /** + * Un-pads a byte array that is padded with PKCS padding. Since + * this version does not take block size as a parameter, it cannot + * error check. + * @see #pad + */ + public static byte[] + unPad(byte[] padded) throws BadPaddingException { + if(padded.length == 0) { + return new byte[0]; + } + + byte padOctet = padded[padded.length-1]; + if(padOctet < 1) { + throw new BadPaddingException("Padding octet is less than 1"); + } else if(padOctet >= padded.length) { + throw new BadPaddingException("Padding is larger than entire"+ + " array"); + } + + byte[] unpadded = new byte[padded.length - padOctet]; + + System.arraycopy(padded, 0, unpadded, 0, unpadded.length); + + return unpadded; + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/CryptoStore.java b/mozilla/security/jss/org/mozilla/jss/crypto/CryptoStore.java new file mode 100644 index 00000000000..cdd8508287a --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/CryptoStore.java @@ -0,0 +1,193 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.crypto; + +import com.netscape.jss.util.*; +import java.security.*; +import java.security.cert.CertificateEncodingException; +import java.io.Serializable; + +/** + * This is an interface for a permanent repository of cryptographic objects, + * such as keys, certs, and passwords. + */ +public interface CryptoStore { + + //////////////////////////////////////////////////////////// + // Private Keys + //////////////////////////////////////////////////////////// + + /** + * Imports an encoded, encrypted private key into this token. + * + * @param encodedKey The encoded, encrypted private key. These bytes + * are expected to be a DER-encoded PKCS #8 EncryptedKeyInfo. + * Currently, the only encryption algorithm is RC4. + * @param password The password that encodes this key. The password + * will be cleared by this method. This password, + * together with the salt, are used to construct the decrypting key. + * @param salt The password salt. + * @exception InvalidKeyFormatException If the key cannot be decoded. + * This may be caused by supplying an incorrect password, or + * it may be due to corrupted data. + * @exception TokenException If the key cannot be imported to this token. + * @deprecated A key type should be specified so that the correct usages + * can be enabled on the key. + */ + public void + importEncryptedPrivateKey( byte[] encodedKey, + Password password, + byte[] salt, + byte[] globalSalt ) + throws InvalidKeyFormatException, TokenException; + + /** + * Imports an encoded, encrypted private key into this token. + * + * @param encodedKey The encoded, encrypted private key. These bytes + * are expected to be a DER-encoded PKCS #8 EncryptedKeyInfo. + * Currently, the only encryption algorithm is RC4. + * @param password The password that encodes this key. The password + * will be cleared by this method. This password, + * together with the salt, are used to construct the decrypting key. + * @param salt The password salt. + * @param type The type of the private key. This is used to enable the + * right operations for the key. + * @exception InvalidKeyFormatException If the key cannot be decoded. + * This may be caused by supplying an incorrect password, or + * it may be due to corrupted data. + * @exception TokenException If the key cannot be imported to this token. + * @deprecated Use importPrivateKey instead. + */ + public void + importEncryptedPrivateKey( byte[] encodedKey, + Password password, + byte[] salt, + byte[] globalSalt, + PrivateKey.Type type ) + throws InvalidKeyFormatException, TokenException; + + /** + * Imports a raw private key into this token. + * + * @param key The private key. + * @exception TokenException If the key cannot be imported to this token. + * @exception KeyAlreadyImportedException If the key already exists on this token. + */ + public void + importPrivateKey( byte[] key, + PrivateKey.Type type ) + throws TokenException, KeyAlreadyImportedException; + + + /** + * Imports an encoded, encrypted private key into this token, and stores + * it as a temporary (session) object. The key will be deleted + * when it is garbage collected. + * + * @param encodedKey The encoded, encrypted private key. These bytes + * are expected to be a DER-encoded PKCS #8 EncryptedKeyInfo. + * Currently, the only encryption algorithm is RC4. + * @param password The password that encodes this key. The password + * will be cleared by this method. This password, + * together with the salt, are used to construct the decrypting key. + * @param salt The password salt. + * @param type The type of the private key. This is used to enable the + * right operations for the key. + * @exception InvalidKeyFormatException If the key cannot be decoded. + * This may be caused by supplying an incorrect password, or + * it may be due to corrupted data. + * @exception TokenException If the key cannot be imported to this token. + */ + public void + importTemporaryEncryptedPrivateKey( byte[] encodedKey, + Password password, + byte[] salt, + byte[] globalSalt, + PrivateKey.Type type ) + throws InvalidKeyFormatException, TokenException; + + /** + * Returns all private keys stored on this token. + * + * @return An array of all private keys stored on this token. + * @exception TokenException If an error occurs on the token while + * gathering the keys. + */ + public PrivateKey[] + getPrivateKeys() throws TokenException; + + /** + * Deletes the given PrivateKey from the CryptoToken. + * This is a very dangerous call: it deletes the key from the underlying + * token. After calling this, the PrivateKey passed in must no longer + * be used, or a TokenException will occur. + * + * @param key A PrivateKey to be permanently deleted. It must reside + * on this token. + * @exception NoSuchItemOnTokenException If the given privae key does + * not reside on this token. + * @exception TokenException If an error occurs on the token while + * deleting the key. + */ + public void deletePrivateKey(com.netscape.jss.crypto.PrivateKey key) + throws NoSuchItemOnTokenException, TokenException; + + //////////////////////////////////////////////////////////// + // Certs + //////////////////////////////////////////////////////////// + /** + * Returns all user certificates stored on this token. A user certificate + * is one that has a matching private key. + * + * @return An array of all user certificates present on this token. + * @exception TokenException If an error occurs on the token while + * gathering the certificates. + */ + public X509Certificate[] + getCertificates() throws TokenException; + + /** + * Deletes a certificate from a token. + * + * @param cert A certificate to be deleted from this token. The cert + * must actually reside on this token. + * @exception NoSuchItemOnTokenException If the given cert does not + * reside on this token. + * @exception TokenException If an error occurred on the token while + * deleting the certificate. + */ + public void deleteCert(X509Certificate cert) + throws NoSuchItemOnTokenException, TokenException; +} diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/CryptoToken.java b/mozilla/security/jss/org/mozilla/jss/crypto/CryptoToken.java new file mode 100644 index 00000000000..d7a6d5fe2f9 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/CryptoToken.java @@ -0,0 +1,328 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.crypto; + +import com.netscape.jss.util.*; +import java.security.*; + +/** + * A CryptoToken performs cryptographic operations and stores + * cryptographic items, such as keys and certs. It corresponds to a + * Cryptographic Service Provider (CSP) in CDSA, and to a PKCS #11 token. + *

Instances of CryptoToken are obtained from CryptoManager. + * @see com.netscape.jss.CryptoManager + */ +public interface CryptoToken { + +// +// SERVICES +// + /** + * Creates a Signature object, which can perform signing and signature + * verification. Signing and verification cryptographic operations will + * take place on this token. The signing key must be located on this + * token. + * + * @param algorithm The algorithm used for the signing/verification. + * @exception java.security.NoSuchAlgorithmException If the given + * algorithm is not supported by this provider. + */ + public abstract com.netscape.jss.crypto.Signature + getSignatureContext(SignatureAlgorithm algorithm) + throws java.security.NoSuchAlgorithmException, TokenException; + + /** + * Creates a Digest object. Digesting cryptographic operations will + * take place on this token. + * + * @param algorithm The algorithm used for digesting. + * @exception java.security.NoSuchAlgorithmException If this provider + * does not support the given algorithm. + */ + public abstract JSSMessageDigest + getDigestContext(DigestAlgorithm algorithm) + throws java.security.NoSuchAlgorithmException, DigestException; + + // !!! MAC ??? + + /** + * Creates a Cipher object, which can be used for encryption and + * decryption. Cryptographic operations will take place on this token. + * The keys used in the operations must be located on this token. + * + * @param algorithm The algorithm used for encryption/decryption. + * @exception java.security.NoSuchAlgorithmException If this provider + * does not support the given algorithm. + */ + public abstract Cipher + getCipherContext(EncryptionAlgorithm algorithm) + throws java.security.NoSuchAlgorithmException, TokenException; + + public abstract KeyWrapper + getKeyWrapper(KeyWrapAlgorithm algorithm) + throws java.security.NoSuchAlgorithmException, TokenException; + + /** + * Returns a Random Number Generator implemented on this token. + * + * @exception com.netscape.jss.crypto.ServiceNotProvidedException If this token + * does not perform random number generation + */ + /* + public abstract SecureRandom getRandomGenerator() + throws NotImplementedException, TokenException; + */ + + // !!! Derive Keys ??? + + /** + * Creates a KeyGenerator object, which can be used to generate + * symmetric encryption keys. Any keys generated with this KeyGenerator + * will be generated on this token. + * + * @param algorithm The algorithm that the keys will be used with. + * @exception java.security.NoSuchAlgorithmException If this token does not + * support the given algorithm. + */ + public abstract KeyGenerator + getKeyGenerator(KeyGenAlgorithm algorithm) + throws java.security.NoSuchAlgorithmException, TokenException; + + /** + * Clones a SymmetricKey from a different token onto this token. + * + * @exception SymmetricKey.NotExtractableException If the key material + * cannot be extracted from the current token. + * @exception InvalidKeyException If the owning token cannot process + * the key to be cloned. + */ + public SymmetricKey cloneKey(SymmetricKey key) + throws SymmetricKey.NotExtractableException, + InvalidKeyException, TokenException; + + /** + * Creates a KeyPairGenerator object, which can be used to generate + * key pairs. Any keypairs generated with this generator will be generated + * on this token. + * + * @param algorithm The algorithm that the keys will be used with (RSA, + * DSA, etc.) + * @exception java.security.NoSuchAlgorithmException If this token does + * not support the given algorithm. + */ + public abstract KeyPairGenerator + getKeyPairGenerator(KeyPairAlgorithm algorithm) + throws java.security.NoSuchAlgorithmException, TokenException; + + /** + * Generates a b64 encoded PKCS10 blob used for making cert + * request. Begin/End brackets included. + * @param subject subject dn of the certificate + * @param keysize size of the key + * @param keyType "rsa" or "dsa" + * @param P The DSA prime parameter + * @param Q The DSA sub-prime parameter + * @param G The DSA base parameter + * @return base64 encoded pkcs10 certificate request with + * Begin/end brackets + */ + public abstract String generateCertRequest(String subject, int + keysize, + String keyType, + byte[] P, byte[] Q, + byte[] G) + throws TokenException, InvalidParameterException, + PQGParamGenException; + + /** + * Determines whether this token supports the given algorithm. + * + * @param alg A JSS algorithm. Note that for Signature, a token may + * fail to support a specific SignatureAlgorithm (such as + * RSASignatureWithMD5Digest) even though it does support the + * generic algorithm (RSASignature). In this case, the signature + * operation will be performed on that token, but the digest + * operation will be performed on the internal token. + * @return true if the token supports the algorithm. + */ + public boolean doesAlgorithm(Algorithm alg); + + /** + * Login to the token. If a token is logged in, it will not trigger + * password callbacks. + * + * @param password The password for this token. + * @exception IncorrectPasswordException If the supplied password is + * incorrect. + * @see #setLoginMode + * @see com.netscape.jss.CryptoManager#setPasswordCallback + */ + public abstract void login(PasswordCallback pwcb) + throws IncorrectPasswordException, TokenException; + + /** + * Logout of the token. + * + */ + public abstract void logout() throws TokenException; + + /** + * Login once, never need to re-enter the password until you log out. + */ + public static final int ONE_TIME=0; + /** + * Need to re-login after a period of time. + * @see com.netscape.jss.crypto.CryptoToken#setLoginTimeoutMinutes + */ + public static final int TIMEOUT=1; + /** + * Need to provide a password before each crypto operation. + */ + public static final int EVERY_TIME=2; + + /** + * Returns the login mode of this token: ONE_TIME, TIMEOUT, or + * EVERY_TIME. The default is ONE_TIME. + * @see #getLoginTimeoutMinutes + * @exception TokenException If an error occurs on the token. + */ + public abstract int getLoginMode() throws TokenException; + + /** + * Sets the login mode of this token. + * + * @param mode ONE_TIME, TIMEOUT, or EVERY_TIME + * @exception TokenException If this mode is not supported by this token, + * or an error occurs on the token. + * @see #login + * @see #setLoginTimeoutMinutes + */ + public abstract void setLoginMode(int mode) throws TokenException; + + /** + * Returns the login timeout period. The timeout is only used if the + * login mode is TIMEOUT. + * + * @see #getLoginMode + * @exception TokenException If an error occurs on the token. + */ + public abstract int getLoginTimeoutMinutes() throws TokenException; + + /** + * Sets the timeout period for logging in. This will only be used + * if the login mode is TIMEOUT. + * + * @exception TokenException If timeouts are not supported by this + * token, or an error occurs on the token. + * @see #setLoginMode + */ + public abstract void setLoginTimeoutMinutes(int timeoutMinutes) + throws TokenException; + + /** + * Find out if the token is currently logged in. + * + * @see #login + * @see #logout + */ + public boolean isLoggedIn() throws TokenException; + + /** + * Initialize the password of this token. + * + * @param securityOfficerPW A callback to obtain the password of the + * SecurityOfficer. Pass in a NullPasswordCallback if there is + * no security officer password. Must not be null. + * @param userPW A callback to obtain the new password for this token. + * Must not be null. + * @exception IncorrectPasswordException If the supplied security officer + * password is incorrect. + * @exception AlreadyInitializedException If the token only allows one + * password initialization, and it has already occurred. + * @exception TokenException If an error occurs on the token. + */ + public abstract void + initPassword(PasswordCallback securityOfficerPW, PasswordCallback userPW) + throws IncorrectPasswordException, AlreadyInitializedException, + TokenException; + + /** + * Determine whether the password has been initialized yet. Some tokens + * (such as the Netscape Internal Key Token) don't allow initializing + * the PIN more than once. + * + * @exception TokenException If an error occurs on the token. + */ + public abstract boolean + passwordIsInitialized() throws TokenException; + + /** + * Change the password of this token. + * + * @exception IncorrectPasswordException If the supplied old password is + * incorrect. + * @param oldpw A callback (which could be just a Password) to retrieve + * the current password. + * @param newpw A callback (which could be just a Password) to retrieve + * the new password. + */ + public abstract void + changePassword(PasswordCallback oldpw, PasswordCallback newpw) + throws IncorrectPasswordException, TokenException; + + /** + * Obtain the nickname, or label, of this token. + * + * @exception TokenException If an error occurs on the token. + */ + public abstract String getName() throws TokenException; + + /** + * Get the CryptoStore interface to this token's objects. + */ + public abstract CryptoStore getCryptoStore(); + + /** + * Deep comparison operation. Use this, rather than ==, to determine + * whether two CryptoTokens are the same. + */ + public boolean equals(Object object); + + /** + * Determines whether this token is currently present. + * This could return false if the token is a smart card that was + * removed from its slot. + */ + public boolean isPresent(); +} diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/DigestAlgorithm.java b/mozilla/security/jss/org/mozilla/jss/crypto/DigestAlgorithm.java new file mode 100644 index 00000000000..cf9572281f4 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/DigestAlgorithm.java @@ -0,0 +1,99 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.crypto; + +import java.util.Hashtable; +import java.security.NoSuchAlgorithmException; +import com.netscape.jss.asn1.*; + +public class DigestAlgorithm extends Algorithm { + + // The size in bytes of the output of this hash. + private int outputSize; + + protected DigestAlgorithm(int oidIndex, String name, + OBJECT_IDENTIFIER oid, int outputSize) + { + super(oidIndex, name, oid); + + this.outputSize = outputSize; + + // only store the first algorithm for a given oid. More than one + // alg might share the same oid, such as from child classes. + if( oid != null && oidMap.get(oid)==null ) { + oidMap.put(oid, this); + } + } + + /////////////////////////////////////////////////////////////////////// + // OID mapping + /////////////////////////////////////////////////////////////////////// + private static Hashtable oidMap = new Hashtable(); + + public static DigestAlgorithm fromOID(OBJECT_IDENTIFIER oid) + throws NoSuchAlgorithmException + { + Object alg = oidMap.get(oid); + if( alg == null ) { + throw new NoSuchAlgorithmException(); + } else { + return (DigestAlgorithm) alg; + } + } + + /** + * Returns the output size in bytes for this algorithm. + */ + public int getOutputSize() { + return outputSize; + } + + /** + * The MD2 digest algorithm, from RSA. + */ + public static final DigestAlgorithm MD2 = new DigestAlgorithm + (SEC_OID_MD2, "MD2", OBJECT_IDENTIFIER.RSA_DIGEST.subBranch(2), 16 ); + + /** + * The MD5 digest algorithm, from RSA. + */ + public static final DigestAlgorithm MD5 = new DigestAlgorithm + (SEC_OID_MD5, "MD5", OBJECT_IDENTIFIER.RSA_DIGEST.subBranch(5), 16 ); + + /** + * The SHA-1 digest algorithm, from Uncle Sam. + */ + public static final DigestAlgorithm SHA1 = new DigestAlgorithm + (SEC_OID_SHA1, "SHA-1", OBJECT_IDENTIFIER.ALGORITHM.subBranch(26), 20); +} diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/EncryptionAlgorithm.java b/mozilla/security/jss/org/mozilla/jss/crypto/EncryptionAlgorithm.java new file mode 100644 index 00000000000..31eec2d6afa --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/EncryptionAlgorithm.java @@ -0,0 +1,187 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.crypto; + +import java.util.Hashtable; +import java.security.NoSuchAlgorithmException; +import com.netscape.jss.asn1.*; + +/** + * An algorithm for performing symmetric encryption. + */ +public class EncryptionAlgorithm extends Algorithm { + protected EncryptionAlgorithm(int oidTag, String name, Class paramClass, + int blockSize, boolean padded, OBJECT_IDENTIFIER oid) + { + super(oidTag, name, oid, paramClass); + this.blockSize = blockSize; + this.padded = padded; + if(oid!=null) { + oidMap.put(oid, this); + } + } + + private int blockSize; + private boolean padded; + + /////////////////////////////////////////////////////////////////////// + // OID mapping + /////////////////////////////////////////////////////////////////////// + private static Hashtable oidMap = new Hashtable(); + + public static EncryptionAlgorithm fromOID(OBJECT_IDENTIFIER oid) + throws NoSuchAlgorithmException + { + Object alg = oidMap.get(oid); + if( alg == null ) { + throw new NoSuchAlgorithmException(); + } else { + return (EncryptionAlgorithm) alg; + } + } + + /** + * The blocksize of the algorithm in bytes. Stream algorithms (such as + * RC4) have a blocksize of 1. + */ + public int getBlockSize() { + return blockSize; + } + + /** + * Returns true if this algorithm performs padding. + */ + public boolean isPadded() { + return padded; + } + + /** + * Returns the number of bytes that this algorithm expects in + * its initialization vector. + * + * @return The size in bytes of the IV for this algorithm. A size of + * 0 means this algorithm does not take an IV. + */ + public native int getIVLength(); + + public static final EncryptionAlgorithm + RC4 = new EncryptionAlgorithm(SEC_OID_RC4, "RC4", null, 1, false, + OBJECT_IDENTIFIER.RSA_CIPHER.subBranch(4) ); + + public static final EncryptionAlgorithm + DES_ECB = new EncryptionAlgorithm(SEC_OID_DES_ECB, "DES/ECB", null, + 8, false, OBJECT_IDENTIFIER.ALGORITHM.subBranch(6) ); + + public static final EncryptionAlgorithm + DES_CBC = new EncryptionAlgorithm(SEC_OID_DES_CBC, "DES/CBC", + IVParameterSpec.class, 8, false, + OBJECT_IDENTIFIER.ALGORITHM.subBranch(7) ); + + public static final EncryptionAlgorithm + DES_CBC_PAD = new EncryptionAlgorithm(CKM_DES_CBC_PAD, "DES/CBC/Pad", + IVParameterSpec.class, 8, true, null); // no oid + + public static final EncryptionAlgorithm + DES3_ECB = new EncryptionAlgorithm(CKM_DES3_ECB, "DES3/ECB", null, 8, + false, null); // no oid + + public static final EncryptionAlgorithm + DES3_CBC = new EncryptionAlgorithm(SEC_OID_DES_EDE3_CBC, "DES3/CBC", + IVParameterSpec.class, 8, false, + OBJECT_IDENTIFIER.RSA_CIPHER.subBranch(7) ); + + public static final EncryptionAlgorithm + DES3_CBC_PAD = new EncryptionAlgorithm(CKM_DES3_CBC_PAD, "DES3/CBC/Pad", + IVParameterSpec.class, 8, true, null); // no oid + + public static final EncryptionAlgorithm + RC2_CBC = new EncryptionAlgorithm(SEC_OID_RC2_CBC, "RC2/CBC", + IVParameterSpec.class, 8, false, + OBJECT_IDENTIFIER.RSA_CIPHER.subBranch(2) ); + + /////////////////////////////////////////////////////////////////////// + // Export control code + /////////////////////////////////////////////////////////////////////// + + private static final int NUMBER_OF_ALGORITHMS = 8; + + public EncryptionAlgorithm[] getAllAlgorithms( Usage usage ) { + EncryptionAlgorithm[] algs = new + EncryptionAlgorithm[NUMBER_OF_ALGORITHMS]; + + long[] indices = getAllAlgorithmIndices( usage ); + + int j = 0; + for( int i = 0; i <= indices.length; i++ ) { + switch( ( int ) indices[i] ) { + case SEC_OID_RC4: + algs[j] = RC4; + j++; + break; + case SEC_OID_DES_ECB: + algs[j] = DES_ECB; + j++; + break; + case SEC_OID_DES_CBC: + algs[j] = DES_CBC; + j++; + break; + case CKM_DES_CBC_PAD: + algs[j] = DES_CBC_PAD; + j++; + break; + case CKM_DES3_ECB: + algs[j] = DES3_ECB; + j++; + break; + case SEC_OID_DES_EDE3_CBC: + algs[j] = DES3_CBC; + j++; + break; + case CKM_DES3_CBC_PAD: + algs[j] = DES3_CBC_PAD; + j++; + break; + case SEC_OID_RC2_CBC: + algs[j] = RC2_CBC; + j++; + break; + default: + continue; + } + } + + return algs; + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/HMACAlgorithm.java b/mozilla/security/jss/org/mozilla/jss/crypto/HMACAlgorithm.java new file mode 100644 index 00000000000..91774302a98 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/HMACAlgorithm.java @@ -0,0 +1,85 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.crypto; + +import java.util.Hashtable; +import com.netscape.jss.asn1.*; +import java.security.NoSuchAlgorithmException; + +/** + * Algorithms for performing HMACs. These can be used to create + * MessageDigests. + */ +public class HMACAlgorithm extends DigestAlgorithm { + + protected HMACAlgorithm(int oidIndex, String name, OBJECT_IDENTIFIER oid, + int outputSize) { + super(oidIndex, name, oid, outputSize); + + if( oid!=null && oidMap.get(oid)==null) { + oidMap.put(oid, this); + } + } + + /////////////////////////////////////////////////////////////////////// + // OID mapping + /////////////////////////////////////////////////////////////////////// + private static Hashtable oidMap = new Hashtable(); + + /** + * Looks up the HMAC algorithm with the given OID. + * + * @exception NoSuchAlgorithmException If no registered HMAC algorithm + * has the given OID. + */ + public static DigestAlgorithm fromOID(OBJECT_IDENTIFIER oid) + throws NoSuchAlgorithmException + { + Object alg = oidMap.get(oid); + if( alg == null ) { + throw new NoSuchAlgorithmException(); + } else { + return (HMACAlgorithm) alg; + } + } + + /** + * SHA-1 HMAC. This is a Message Authentication Code that uses a + * symmetric key together with SHA-1 digesting to create a form of + * signature. + */ + public static final HMACAlgorithm SHA1 = new HMACAlgorithm + (CKM_SHA_1_HMAC, "SHA-1-HMAC", + OBJECT_IDENTIFIER.ALGORITHM.subBranch(26), 20); +} diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/IVParameterSpec.java b/mozilla/security/jss/org/mozilla/jss/crypto/IVParameterSpec.java new file mode 100644 index 00000000000..d29d1dbd653 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/IVParameterSpec.java @@ -0,0 +1,57 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.crypto; + +import java.security.spec.AlgorithmParameterSpec; + +/** + * An algorithm parameter that consists of an initialization vector (IV). + */ +public class IVParameterSpec implements AlgorithmParameterSpec { + + private byte[] iv; + + private IVParameterSpec() { } + + public IVParameterSpec(byte[] iv) { + this.iv = iv; + } + + /** + * Returns a reference to an internal copy of the initialization vector. + */ + public byte[] getIV() { + return iv; + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/IllegalBlockSizeException.java b/mozilla/security/jss/org/mozilla/jss/crypto/IllegalBlockSizeException.java new file mode 100644 index 00000000000..e93c1cd5674 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/IllegalBlockSizeException.java @@ -0,0 +1,35 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.crypto; + +public class IllegalBlockSizeException extends Exception { } diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/InternalCertificate.java b/mozilla/security/jss/org/mozilla/jss/crypto/InternalCertificate.java new file mode 100644 index 00000000000..427b042a55b --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/InternalCertificate.java @@ -0,0 +1,100 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.crypto; + +/** + * Certificates residing in the internal database. Their trust flags + * can be viewed and modified. Other types of certificates do not + * have trust flags. + */ +public interface InternalCertificate extends X509Certificate +{ + //////////////////////////////////////////////////// + // Trust manipulation + //////////////////////////////////////////////////// + public static final int VALID_PEER = (1<<0); + public static final int TRUSTED_PEER = (1<<1); // CERTDB_TRUSTED + public static final int VALID_CA = (1<<3); + public static final int TRUSTED_CA = (1<<4); + public static final int USER = (1<<6); + public static final int TRUSTED_CLIENT_CA = (1<<7); + + /** + * Set the SSL trust flags for this certificate. + * + * @param trust A bitwise OR of the trust flags VALID_PEER, VALID_CA, + * TRUSTED_CA, USER, and TRUSTED_CLIENT_CA. + */ + public abstract void setSSLTrust(int trust); + + /** + * Set the email (S/MIME) trust flags for this certificate. + * + * @param trust A bitwise OR of the trust flags VALID_PEER, VALID_CA, + * TRUSTED_CA, USER, and TRUSTED_CLIENT_CA. + */ + public abstract void setEmailTrust(int trust); + + /** + * Set the object signing trust flags for this certificate. + * + * @param trust A bitwise OR of the trust flags VALID_PEER, VALID_CA, + * TRUSTED_CA, USER, and TRUSTED_CLIENT_CA. + */ + public abstract void setObjectSigningTrust(int trust); + + /** + * Get the SSL trust flags for this certificate. + * + * @return A bitwise OR of the trust flags VALID_PEER, VALID_CA, + * TRUSTED_CA, USER, and TRUSTED_CLIENT_CA. + */ + public abstract int getSSLTrust(); + + /** + * Get the email (S/MIME) trust flags for this certificate. + * + * @return A bitwise OR of the trust flags VALID_PEER, VALID_CA, + * TRUSTED_CA, USER, and TRUSTED_CLIENT_CA. + */ + public abstract int getEmailTrust(); + + /** + * Get the object signing trust flags for this certificate. + * + * @return A bitwise OR of the trust flags VALID_PEER, VALID_CA, + * TRUSTED_CA, USER, and TRUSTED_CLIENT_CA. + */ + public abstract int getObjectSigningTrust(); +} diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/InvalidDERException.java b/mozilla/security/jss/org/mozilla/jss/crypto/InvalidDERException.java new file mode 100644 index 00000000000..1e9e9beadcd --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/InvalidDERException.java @@ -0,0 +1,42 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.crypto; + +/** + * This exception is thrown when we encounter a bogus DER blob. + */ +public class InvalidDERException extends Exception { + public InvalidDERException() { super(); } + public InvalidDERException(String mesg) { super(mesg); } +} diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/InvalidKeyFormatException.java b/mozilla/security/jss/org/mozilla/jss/crypto/InvalidKeyFormatException.java new file mode 100644 index 00000000000..2b7dba94d21 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/InvalidKeyFormatException.java @@ -0,0 +1,47 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.crypto; + +/** + * An exception of this type is thrown if an encoded private key + * cannot be decoded. + */ +public class InvalidKeyFormatException extends Exception { + public InvalidKeyFormatException() { + super(); + } + public InvalidKeyFormatException(String mesg) { + super(mesg); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/JSSMessageDigest.java b/mozilla/security/jss/org/mozilla/jss/crypto/JSSMessageDigest.java new file mode 100644 index 00000000000..889ed16579d --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/JSSMessageDigest.java @@ -0,0 +1,143 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.crypto; + +import java.security.DigestException; +import java.security.InvalidKeyException; + +/** + * A class for performing message digesting (hashing) and MAC operations. + */ +public abstract class JSSMessageDigest { + + /** + * Initializes an HMAC digest with the given symmetric key. This also + * has the effect of resetting the digest. + * + * @exception DigestException If this algorithm is not an HMAC algorithm. + * @exception InvalidKeyException If the given key is not valid. + */ + public abstract void initHMAC(SymmetricKey key) + throws DigestException, InvalidKeyException; + + /** + * Updates the digest with a single byte of input. + */ + public void update(byte input) throws DigestException { + byte[] in = { input }; + update(in, 0, 1); + } + + /** + * Updates the digest with a portion of an array. + * + * @param input An array from which to update the digest. + * @param offset The index in the array at which to start digesting. + * @param len The number of bytes to digest. + * @exception DigestException If an error occurs while digesting. + */ + public abstract void update(byte[] input, int offset, int len) + throws DigestException; + + /** + * Updates the digest with an array. + * + * @param input An array to feed to the digest. + * @exception DigestException If an error occurs while digesting. + */ + public void update(byte[] input) throws DigestException { + update(input, 0, input.length); + } + + /** + * Completes digestion. + * + * @return The, ahem, output of the digest operation. + * @param If an error occurs while digesting. + */ + public byte[] digest() throws DigestException { + byte[] output = new byte[getOutputSize()]; + digest(output, 0, output.length); + return output; + } + + /** + * Completes digesting, storing the result into the provided array. + * + * @param buf The buffer in which to place the digest output. + * @param offset The offset in the buffer at which to store the output. + * @param len The amount of space available in the buffer for the + * digest output. + * @return The number of bytes actually stored into buf. + * @exception DigestException If the provided space is too small for + * the digest, or an error occurs with the digest. + */ + public abstract int digest(byte[] buf, int offset, int len) + throws DigestException; + + /** + * Provides final data to the digest, then completes it and returns the + * output. + * + * @param input The digest's last meal. + * @return The completed digest. + * @exception DigestException If an error occurs while digesting. + */ + public byte[] digest(byte[] input) throws DigestException { + update(input); + return digest(); + } + + /** + * Resets this digest for further use. This clears all input and + * output streams. If this is an HMAC digest, the HMAC key is not + * cleared. + */ + public abstract void reset() throws DigestException; + + /** + * Returns the algorithm that this digest uses. + */ + public abstract DigestAlgorithm getAlgorithm(); + + /** + * Returns the length of the digest created by this digest's + * digest algorithm. + * + * @return The size in bytes of the output of this digest. + */ + public int getOutputSize() { + return getAlgorithm().getOutputSize(); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/JSSSecureRandom.java b/mozilla/security/jss/org/mozilla/jss/crypto/JSSSecureRandom.java new file mode 100644 index 00000000000..d46bec1c213 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/JSSSecureRandom.java @@ -0,0 +1,58 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.crypto; + +/** + * An interface for secure random numbers. This should be replaced with + * java.security.SecureRandom when we move to JDK 1.2. In JDK 1.1, + * SecureRandom is implemented by a Sun class. In JDK 1.2, it uses a + * provider architecture. + */ +public interface JSSSecureRandom { + + /** + * Seed the RNG with the given seed bytes. + */ + public void setSeed(byte[] seed); + + /** + * Seed the RNG with the eight bytes contained in seed. + */ + public void setSeed(long seed); + + /** + * Retrieves random bytes and stores them in the given array. + */ + public void nextBytes(byte bytes[]); +} diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/KeyAlreadyImportedException.java b/mozilla/security/jss/org/mozilla/jss/crypto/KeyAlreadyImportedException.java new file mode 100644 index 00000000000..3f81fac6e29 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/KeyAlreadyImportedException.java @@ -0,0 +1,45 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.crypto; + +/** + * This exception is thrown if the user tries to import a + * key which is already in the specified token + */ +public class KeyAlreadyImportedException extends java.lang.Exception { + public KeyAlreadyImportedException() {} + public KeyAlreadyImportedException(String mesg) { + super(mesg); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/KeyGenAlgorithm.java b/mozilla/security/jss/org/mozilla/jss/crypto/KeyGenAlgorithm.java new file mode 100644 index 00000000000..7856dbe20d7 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/KeyGenAlgorithm.java @@ -0,0 +1,151 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.crypto; + +import com.netscape.jss.asn1.OBJECT_IDENTIFIER; +import java.util.Hashtable; +import java.security.NoSuchAlgorithmException; + +/** + * Algorithms that can be used for generating symmetric keys. + */ +public class KeyGenAlgorithm extends Algorithm { + + protected KeyGenAlgorithm(int oidTag, String name, int validStrength, + OBJECT_IDENTIFIER oid, Class paramClass) + { + super(oidTag, name, oid, paramClass); + this.validStrength = validStrength; + if(oid!=null) { + oidMap.put(oid, this); + } + } + + /////////////////////////////////////////////////////////////////////// + // OIDs + /////////////////////////////////////////////////////////////////////// + private static final OBJECT_IDENTIFIER PKCS5 = OBJECT_IDENTIFIER.PKCS5; + private static final OBJECT_IDENTIFIER PKCS12_PBE = + OBJECT_IDENTIFIER.PKCS12.subBranch(1); + + /////////////////////////////////////////////////////////////////////// + // OID mapping + /////////////////////////////////////////////////////////////////////// + private static Hashtable oidMap = new Hashtable(); + + public static KeyGenAlgorithm fromOID(OBJECT_IDENTIFIER oid) + throws NoSuchAlgorithmException + { + Object alg = oidMap.get(oid); + if( alg == null ) { + throw new NoSuchAlgorithmException(oid.toString()); + } else { + return (KeyGenAlgorithm) alg; + } + } + + // The valid strength (key size in bits) for keys of this algorithm. + // A value of -1 means all strengths are valid (such as for RC4). + private int validStrength; + + /** + * Returns true if the given strength is valid for this + * key generation algorithm. Note that PBE algorithms require + * PBEParameterSpecs rather than strengths. It is the responsibility + * of the caller to verify this. + */ + public boolean isValidStrength(int strength) { + if( validStrength == -1 ) { + return true; + } else { + return strength == validStrength; + } + } + + ////////////////////////////////////////////////////////////// + public static final KeyGenAlgorithm + DES = new KeyGenAlgorithm(CKM_DES_KEY_GEN, "DES", 56, null, null); + + ////////////////////////////////////////////////////////////// + public static final KeyGenAlgorithm + DES3 = new KeyGenAlgorithm(CKM_DES3_KEY_GEN, "DES3", 168, null, null); + + ////////////////////////////////////////////////////////////// + public static final KeyGenAlgorithm + RC4 = new KeyGenAlgorithm(CKM_RC4_KEY_GEN, "RC4", -1, null, null); + + ////////////////////////////////////////////////////////////// + public static final KeyGenAlgorithm + PBA_SHA1_HMAC = new KeyGenAlgorithm( + CKM_PBA_SHA1_WITH_SHA1_HMAC, + "PBA/SHA1/HMAC", 160, null, PBEKeyGenParams.class ); + + ////////////////////////////////////////////////////////////// + // Export control code + ////////////////////////////////////////////////////////////// + + private static final int NUMBER_OF_ALGORITHMS = 4; + + public KeyGenAlgorithm[] getAllAlgorithms( Usage usage ) { + KeyGenAlgorithm[] algs = new KeyGenAlgorithm[NUMBER_OF_ALGORITHMS]; + + long[] indices = getAllAlgorithmIndices( usage ); + + int j = 0; + for( int i = 0; i <= indices.length; i++ ) { + switch( ( int ) indices[i] ) { + case CKM_DES_KEY_GEN: + algs[j] = DES; + j++; + break; + case CKM_DES3_KEY_GEN: + algs[j] = DES3; + j++; + break; + case CKM_RC4_KEY_GEN: + algs[j] = RC4; + j++; + break; + case CKM_PBA_SHA1_WITH_SHA1_HMAC: + algs[j] = PBA_SHA1_HMAC; + j++; + break; + default: + continue; + } + } + + return algs; + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/KeyGenerator.java b/mozilla/security/jss/org/mozilla/jss/crypto/KeyGenerator.java new file mode 100644 index 00000000000..1c9532ed38a --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/KeyGenerator.java @@ -0,0 +1,111 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.crypto; + +import java.security.spec.AlgorithmParameterSpec; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.io.CharConversionException; + +/** + * Generates symmetric keys for encryption and decryption. + */ +public interface KeyGenerator { + + /** + * @param strength Key size in bits. Must be evenly divisible by 8. + */ + public void initialize(int strength) + throws InvalidAlgorithmParameterException; + + public void initialize(AlgorithmParameterSpec parameters) + throws InvalidAlgorithmParameterException; + + public SymmetricKey generate() + throws IllegalStateException, TokenException, CharConversionException; + + /** + * Generates an Initialization Vector using a PBE algorithm. + * In order to call this method, the algorithm must be a PBE algorithm, + * and the KeyGenerator must have been initialized with an instance + * of PBEKeyGenParams. + * + * @return The initialization vector derived from the password and salt + * using the PBE algorithm. + * @exception IllegalStateException If the algorithm is not a PBE + * algorithm, or the KeyGenerator has not been initialized with + * an instance of PBEKeyGenParams. + * @exception TokenException If an error occurs on the CryptoToken while + * generating the IV. + */ + public byte[] generatePBE_IV() + throws IllegalStateException, TokenException, CharConversionException; + + /** + * Allows a SymmetricKey to be cloned on a different token. + * + * @exception SymmetricKey.NotExtractableException If the key material + * cannot be extracted from the current token. + * @exception InvalidKeyException If the owning token cannot process + * the key to be cloned. + */ + public SymmetricKey clone(SymmetricKey key) + throws SymmetricKey.NotExtractableException, + InvalidKeyException, TokenException; + + /** + * An interface for converting a password of Java characters into an array + * of bytes. This conversion must be performed to provide a byte array + * to the low-level crypto engine. The default conversion is UTF8. + * Null-termination is not necessary, and indeed is usually incorrect, + * since the password is passed to the crypto engine as a byte array, not + * a C string. + */ + public static interface CharToByteConverter { + + /** + * Converts a password of Java characters into a password of + * bytes, using some encoding scheme. The input char array must + * not be modified. + */ + public byte[] convert(char[] chars) throws CharConversionException; + } + + /** + * Sets the character to byte converter for passwords. The default + * conversion is UTF8 with no null termination. + */ + public void setCharToByteConverter(CharToByteConverter charToByte); + +} diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/KeyPairAlgorithm.java b/mozilla/security/jss/org/mozilla/jss/crypto/KeyPairAlgorithm.java new file mode 100644 index 00000000000..9d5d03a4e4c --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/KeyPairAlgorithm.java @@ -0,0 +1,105 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.crypto; + +/** + * Algorithms that can be used for keypair generation. + */ +public class KeyPairAlgorithm extends Algorithm { + + protected KeyPairAlgorithm(int oidIndex, String name, Algorithm algFamily) { + super(oidIndex, name); + this.algFamily = algFamily; + } + + /** + * Returns the algorithm family for a given key pair generation algorithm. + * If a token supports a family and is writable, we can do keypair gen + * on the token even if it doesn't support the keypair gen algorithm. + * We do this by doing the keypair gen on the internal module and then + * moving the key out to the other token. + */ + public Algorithm + getAlgFamily() + { + return algFamily; + } + + protected Algorithm algFamily; + + //////////////////////////////////////////////////////////////// + // Key-Pair Generation Algorithms + //////////////////////////////////////////////////////////////// + public static final Algorithm + RSAFamily = new Algorithm(SEC_OID_PKCS1_RSA_ENCRYPTION, "RSA"); + + public static final Algorithm + DSAFamily = new Algorithm(SEC_OID_ANSIX9_DSA_SIGNATURE, "DSA"); + + public static final KeyPairAlgorithm + RSA = new KeyPairAlgorithm(CKM_RSA_PKCS_KEY_PAIR_GEN, "RSA", RSAFamily); + + public static final KeyPairAlgorithm + DSA = new KeyPairAlgorithm(CKM_DSA_KEY_PAIR_GEN, "DSA", DSAFamily); + + //////////////////////////////////////////////////////////////// + // Export control code + //////////////////////////////////////////////////////////////// + + private static final int NUMBER_OF_ALGORITHMS = 4; + + public KeyPairAlgorithm[] getAllAlgorithms( Usage usage ) { + KeyPairAlgorithm[] algs = new KeyPairAlgorithm[NUMBER_OF_ALGORITHMS]; + + long[] indices = getAllAlgorithmIndices( usage ); + + int j = 0; + for( int i = 0; i <= indices.length; i++ ) { + switch( ( int ) indices[i] ) { + case CKM_RSA_PKCS_KEY_PAIR_GEN: + algs[j] = RSA; + j++; + break; + case CKM_DSA_KEY_PAIR_GEN: + algs[j] = DSA; + j++; + break; + default: + continue; + } + } + + return algs; + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/KeyPairGenerator.java b/mozilla/security/jss/org/mozilla/jss/crypto/KeyPairGenerator.java new file mode 100644 index 00000000000..84da1a26376 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/KeyPairGenerator.java @@ -0,0 +1,165 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.crypto; + +import java.security.*; +import java.security.SecureRandom; +import java.security.spec.AlgorithmParameterSpec; + +/** + * Generates RSA and DSA key pairs. Each CryptoToken provides a + * KeyPairGenerator, which can be used to generate key pairs on that token. + * A given token may not support all algorithms, and some tokens may not + * support any key pair generation. If a token does not support key pair + * generation, the Netscape internal token may do it instead. Call + * keygenOnInternalToken to find out if this is happening. + * + * @see com.netscape.jss.crypto.CryptoToken#getKeyPairGenerator + */ +public class KeyPairGenerator { + + /** + * Creates a new key pair generator. KeyPairGenerators should + * be obtained by calling CryptoToken.getKeyPairGenerator + * instead of calling this constructor. + * + * @param algorithm The type of keys that the generator will be + * used to generate. + * @param engine The engine object that provides the implementation for + * the class. + */ + public KeyPairGenerator(KeyPairAlgorithm algorithm, + KeyPairGeneratorSpi engine) { + this.algorithm = algorithm; + this.engine = engine; + } + + /** + * Generates a new key pair. + * + * @return A new key pair. The keys reside on the CryptoToken that + * provided this KeyPairGenerator. + * @exception TokenException If an error occurs on the CryptoToken + * in the process of generating the key pair. + */ + public java.security.KeyPair + genKeyPair() throws TokenException { + return engine.generateKeyPair(); + } + + /** + * @return The type of key that this generator generates. + */ + public KeyPairAlgorithm getAlgorithm() { + return algorithm; + } + + /** + * Initializes the generator with algorithm-specific parameters. + * + * @param params Algorithm-specific parameters for the key pair generation. + * @param random This parameter is ignored. + * @exception InvalidAlgorithmParameterException If the parameters are + * inappropriate for the type of key pair that is being generated, + * or they are not supported by this generator. + * @see com.netscape.jss.crypto.RSAParameterSpec + * @see java.security.spec.DSAParameterSpec + */ + public void initialize(AlgorithmParameterSpec params, SecureRandom random) + throws InvalidAlgorithmParameterException + { + engine.initialize(params, random); + } + + /** + * Initializes the generator with algorithm-specific parameters. + * + * @param params Algorithm-specific parameters for the key pair generation. + * @exception InvalidAlgorithmParameterException If the parameters are + * inappropriate for the type of key pair that is being generated, + * or they are not supported by this generator. + * @see com.netscape.jss.crypto.RSAParameterSpec + * @see java.security.spec.DSAParameterSpec + */ + public void initialize(AlgorithmParameterSpec params) + throws InvalidAlgorithmParameterException + { + engine.initialize(params, null); + } + + /** + * Initializes the generator with the strength of the keys. + * + * @param strength The strength of the keys that will be generated. + * Usually this is the length of the key in bits. + * @param random This parameter is ignored. + */ + public void initialize(int strength, SecureRandom random) { + engine.initialize(strength, random); + } + + /** + * Initializes the generator with the strength of the keys. + * + * @param strength The strength of the keys that will be generated. + * Usually this is the length of the key in bits. + */ + public void initialize(int strength) { + engine.initialize(strength, null); + } + + /** + * @return true if the keypair generation will take place on the + * internal token rather than the current token. This will + * happen if the token does not support keypair generation + * but does support this algorithm and is writable. In this + * case the keypair will be generated on the Netscape internal + * token and then moved to this token. + */ + public boolean keygenOnInternalToken() { + return engine.keygenOnInternalToken(); + } + + /** + * Tells the generator to generate temporary, rather than permanent, + * keypairs. Temporary keys are not written permanently to the token. + * They are destroyed by the garbage collector. + */ + public void temporaryPairs(boolean temp) { + engine.temporaryPairs(temp); + } + + protected KeyPairAlgorithm algorithm; + protected KeyPairGeneratorSpi engine; +} diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/KeyPairGeneratorSpi.java b/mozilla/security/jss/org/mozilla/jss/crypto/KeyPairGeneratorSpi.java new file mode 100644 index 00000000000..596ea569900 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/KeyPairGeneratorSpi.java @@ -0,0 +1,56 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.crypto; + +import java.security.*; +import java.security.SecureRandom; +import java.security.spec.AlgorithmParameterSpec; + +public abstract class KeyPairGeneratorSpi { + + public KeyPairGeneratorSpi() { + } + + public abstract void initialize(int strength, SecureRandom random); + + public abstract void initialize(AlgorithmParameterSpec params, + SecureRandom random) + throws InvalidAlgorithmParameterException; + + public abstract KeyPair generateKeyPair() throws TokenException; + + public abstract void temporaryPairs(boolean temp); + + public abstract boolean keygenOnInternalToken(); +} diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/KeyWrapAlgorithm.java b/mozilla/security/jss/org/mozilla/jss/crypto/KeyWrapAlgorithm.java new file mode 100644 index 00000000000..6eb15108317 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/KeyWrapAlgorithm.java @@ -0,0 +1,137 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.crypto; + +/** + * + */ +public class KeyWrapAlgorithm extends Algorithm { + protected KeyWrapAlgorithm(int oidTag, String name, Class paramClass, + boolean padded) { + super(oidTag, name); + parameterClass = paramClass; + this.padded = padded; + } + + private Class parameterClass; + private boolean padded; + + /** + * The type of parameter that this algorithm expects. Returns + * null if this algorithm does not take any parameters. + */ + public Class getParameterClass() { + return parameterClass; + } + + public boolean isPadded() { + return padded; + } + + public static final KeyWrapAlgorithm + DES_ECB = new KeyWrapAlgorithm(SEC_OID_DES_ECB, "DES/ECB", null, false); + + public static final KeyWrapAlgorithm + DES_CBC = new KeyWrapAlgorithm(SEC_OID_DES_CBC, "DES/CBC", + IVParameterSpec.class, false); + + public static final KeyWrapAlgorithm + DES_CBC_PAD = new KeyWrapAlgorithm(CKM_DES_CBC_PAD, "DES/CBC/Pad", + IVParameterSpec.class, true); + + public static final KeyWrapAlgorithm + DES3_ECB = new KeyWrapAlgorithm(CKM_DES3_ECB, "DES3/ECB", null, false); + + public static final KeyWrapAlgorithm + DES3_CBC = new KeyWrapAlgorithm(SEC_OID_DES_EDE3_CBC, "DES3/CBC", + IVParameterSpec.class, false); + + public static final KeyWrapAlgorithm + DES3_CBC_PAD = new KeyWrapAlgorithm(CKM_DES3_CBC_PAD, "DES3/CBC/Pad", + IVParameterSpec.class, true); + + public static final KeyWrapAlgorithm + RSA = new KeyWrapAlgorithm(SEC_OID_PKCS1_RSA_ENCRYPTION, "RSA", null, + false); + + /////////////////////////////////////////////////////////////////////// + // Export control code + /////////////////////////////////////////////////////////////////////// + + private static final int NUMBER_OF_ALGORITHMS = 7; + + public KeyWrapAlgorithm[] getAllAlgorithms( Usage usage ) { + KeyWrapAlgorithm[] algs = new KeyWrapAlgorithm[NUMBER_OF_ALGORITHMS]; + + long[] indices = getAllAlgorithmIndices( usage ); + + int j = 0; + for( int i = 0; i <= indices.length; i++ ) { + switch( ( int ) indices[i] ) { + case SEC_OID_DES_ECB: + algs[j] = DES_ECB; + j++; + break; + case SEC_OID_DES_CBC: + algs[j] = DES_CBC; + j++; + break; + case CKM_DES_CBC_PAD: + algs[j] = DES_CBC_PAD; + j++; + break; + case CKM_DES3_ECB: + algs[j] = DES3_ECB; + j++; + break; + case SEC_OID_DES_EDE3_CBC: + algs[j] = DES3_CBC; + j++; + break; + case CKM_DES3_CBC_PAD: + algs[j] = DES3_CBC_PAD; + j++; + break; + case SEC_OID_PKCS1_RSA_ENCRYPTION: + algs[j] = RSA; + j++; + break; + default: + continue; + } + } + + return algs; + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/KeyWrapper.java b/mozilla/security/jss/org/mozilla/jss/crypto/KeyWrapper.java new file mode 100644 index 00000000000..cd6b758b9bf --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/KeyWrapper.java @@ -0,0 +1,105 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.crypto; + +import java.security.spec.AlgorithmParameterSpec; +import java.security.InvalidAlgorithmParameterException; +import java.security.PublicKey; +import java.security.InvalidKeyException; + +public interface KeyWrapper { + + public void initWrap(SymmetricKey wrappingKey, + AlgorithmParameterSpec parameters) + throws InvalidKeyException, InvalidAlgorithmParameterException; + + public void initWrap(PublicKey wrappingKey, + AlgorithmParameterSpec parameters) + throws InvalidKeyException, InvalidAlgorithmParameterException; + + public void initUnwrap(SymmetricKey unwrappingKey, + AlgorithmParameterSpec parameters) + throws InvalidKeyException, InvalidAlgorithmParameterException; + + public void initUnwrap(PrivateKey unwrappingKey, + AlgorithmParameterSpec parameters) + throws InvalidKeyException, InvalidAlgorithmParameterException; + + public byte[] wrap(PrivateKey toBeWrapped) + throws InvalidKeyException, IllegalStateException, TokenException; + + public byte[] wrap(SymmetricKey toBeWrapped) + throws InvalidKeyException, IllegalStateException, TokenException; + + /** + * Unwraps a private key, creating a permanent private key object. + * A permanent private key object resides on a token until it is + * explicitly deleted from the token. + * + * @publicKey Used to calculate the key identifier that must be stored + * with the private key. Must be a RSAPublicKey or a + * DSAPublicKey. + * @exception InvalidKeyException If the type of the public key does not + * match the type of the private key to be unwrapped. + */ + public PrivateKey unwrapPrivate(byte[] wrapped, PrivateKey.Type type, + PublicKey publicKey) + throws TokenException, InvalidKeyException, IllegalStateException; + + /** + * Unwraps a private key, creating a temporary private key object. + * A temporary + * private key is one that does not permanently reside on a token. + * As soon as it is garbage-collected, it is gone forever. + * + * @publicKey Used to calculate the key identifier that must be stored + * with the private key. Must be a RSAPublicKey or a + * DSAPublicKey. + * @exception InvalidKeyException If the type of the public key does not + * match the type of the private key to be unwrapped. + */ + public PrivateKey unwrapTemporaryPrivate(byte[] wrapped, + PrivateKey.Type type, PublicKey publicKey) + throws TokenException, InvalidKeyException, IllegalStateException; + + /** + * @param keyLength The expected length of the key in bytes. This is + * only used for variable-length keys (RC4) and non-padding + * algorithms. Otherwise, it can be set to anything(like 0). + */ + public SymmetricKey unwrapSymmetric(byte[] wrapped, SymmetricKey.Type type, + int keyLength) + throws TokenException, IllegalStateException, + InvalidAlgorithmParameterException; + +} diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/Makefile b/mozilla/security/jss/org/mozilla/jss/crypto/Makefile new file mode 100644 index 00000000000..22938deaa48 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/Makefile @@ -0,0 +1,72 @@ +#! gmake +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +####################################################################### +# (1) Include initial platform-independent assignments (MANDATORY). # +####################################################################### + +include manifest.mn + +####################################################################### +# (2) Include "global" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/config.mk + +####################################################################### +# (3) Include "component" configuration information. (OPTIONAL) # +####################################################################### +include $(CORE_DEPTH)/$(MODULE)/config/config.mk + + +####################################################################### +# (4) Include "local" platform-dependent assignments (OPTIONAL). # +####################################################################### + +include config.mk + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### + diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/NoSuchItemOnTokenException.java b/mozilla/security/jss/org/mozilla/jss/crypto/NoSuchItemOnTokenException.java new file mode 100644 index 00000000000..29fc5492d0c --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/NoSuchItemOnTokenException.java @@ -0,0 +1,49 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.crypto; + +/** + * Thrown if a cryptographic item does not exist on the token it is + * trying to be used on. + */ +public class NoSuchItemOnTokenException extends Exception { + + public + NoSuchItemOnTokenException() {} + + public + NoSuchItemOnTokenException( String message ) { + super( message ); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/NoSuchPaddingException.java b/mozilla/security/jss/org/mozilla/jss/crypto/NoSuchPaddingException.java new file mode 100644 index 00000000000..23e50fdc947 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/NoSuchPaddingException.java @@ -0,0 +1,39 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.crypto; + +/** + * This class is a stub for javax.crypto.NoSuchPaddingException until we + * move to JDK 1.2. + */ +public class NoSuchPaddingException extends Exception { } diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/ObjectNotFoundException.java b/mozilla/security/jss/org/mozilla/jss/crypto/ObjectNotFoundException.java new file mode 100644 index 00000000000..9e5eb5dd29f --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/ObjectNotFoundException.java @@ -0,0 +1,42 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.crypto; + +/** + * This exception is thrown whenever something isn't implemented. + */ +public class ObjectNotFoundException extends Exception { + public ObjectNotFoundException() { super(); } + public ObjectNotFoundException(String mesg) { super(mesg); } +} diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/PBEAlgorithm.java b/mozilla/security/jss/org/mozilla/jss/crypto/PBEAlgorithm.java new file mode 100644 index 00000000000..cda545a5b78 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/PBEAlgorithm.java @@ -0,0 +1,197 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.crypto; + +import com.netscape.jss.asn1.OBJECT_IDENTIFIER; +import java.util.Hashtable; +import java.security.NoSuchAlgorithmException; + +/** + * Algorithms that can be used for generating symmetric keys from passwords. + */ +public class PBEAlgorithm extends KeyGenAlgorithm { + + private EncryptionAlgorithm encAlg; + private int saltLength; + + protected PBEAlgorithm(int oidTag, String name, int validStrength, + OBJECT_IDENTIFIER oid, EncryptionAlgorithm encAlg, int saltLength) + { + super(oidTag, name, validStrength, oid, PBEKeyGenParams.class); + this.encAlg = encAlg; + this.saltLength = saltLength; + } + + /** + * Returns the EncryptionAlgorithm that should be used with keys + * generated with this PBEAlgorithm. For example, + * PBE_MD2_DES_CBC.getEncryptionAlg() returns + * EncryptionAlgorithm.DES_CBC. + */ + public EncryptionAlgorithm getEncryptionAlg() { + return encAlg; + } + + /** + * Returns the number of bytes of salt that should be supplied when + * generating keys with this algorithm. + * + *

PKCS #5 algorithms require exactly 8 bytes of salt. PKCS #12 + * algorithms take + * a variable length, but recommend that the salt length be at least + * as long as the output of the hash function. For SHA-1, the output + * length is 20 bytes. + */ + public int getSaltLength() { + return saltLength; + } + + /////////////////////////////////////////////////////////////////////// + // OIDs + /////////////////////////////////////////////////////////////////////// + private static final OBJECT_IDENTIFIER PKCS5 = OBJECT_IDENTIFIER.PKCS5; + private static final OBJECT_IDENTIFIER PKCS12_PBE = + OBJECT_IDENTIFIER.PKCS12.subBranch(1); + + /////////////////////////////////////////////////////////////////////// + // OID mapping + /////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////// + public static final PBEAlgorithm + PBE_MD2_DES_CBC = new PBEAlgorithm( + SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC, "PBE/MD2/DES/CBC", 56, + PKCS5.subBranch(1), EncryptionAlgorithm.DES_CBC, 8 ); + + ////////////////////////////////////////////////////////////// + public static final PBEAlgorithm + PBE_MD5_DES_CBC = new PBEAlgorithm( + SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC, "PBE/MD5/DES/CBC", 56, + PKCS5.subBranch(3), EncryptionAlgorithm.DES_CBC, 8 ); + + ////////////////////////////////////////////////////////////// + public static final PBEAlgorithm + PBE_SHA1_DES_CBC = new PBEAlgorithm( + SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC, "PBE/SHA1/DES/CBC", 56, + PKCS5.subBranch(10), EncryptionAlgorithm.DES_CBC, 8 ); + + ////////////////////////////////////////////////////////////// + public static final PBEAlgorithm + PBE_SHA1_RC4_128 = new PBEAlgorithm( + SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4, + "PBE/SHA1/RC4-128", 128, PKCS12_PBE.subBranch(1), + EncryptionAlgorithm.RC4, 20 ); + + ////////////////////////////////////////////////////////////// + public static final PBEAlgorithm + PBE_SHA1_RC4_40 = new PBEAlgorithm( + SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4, + "PBE/SHA1/RC4-40", 40, PKCS12_PBE.subBranch(2), + EncryptionAlgorithm.RC4, 20 ); + + ////////////////////////////////////////////////////////////// + public static final PBEAlgorithm + PBE_SHA1_DES3_CBC = new PBEAlgorithm( + SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC, + "PBE/SHA1/DES3/CBC", 168, PKCS12_PBE.subBranch(3), + EncryptionAlgorithm.DES3_CBC, 20 ); + + ////////////////////////////////////////////////////////////// + public static final PBEAlgorithm + PBE_SHA1_RC2_128_CBC = new PBEAlgorithm( + SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC, + "PBE/SHA1/RC2-128", 128, PKCS12_PBE.subBranch(5), + EncryptionAlgorithm.RC2_CBC, 20 ); + + ////////////////////////////////////////////////////////////// + public static final PBEAlgorithm + PBE_SHA1_RC2_40_CBC = new PBEAlgorithm( + SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC, + "PBE/SHA1/RC2-40", 40, PKCS12_PBE.subBranch(6), + EncryptionAlgorithm.RC2_CBC, 20 ); + + ////////////////////////////////////////////////////////////// + // Export control code + ////////////////////////////////////////////////////////////// + + private static final int NUMBER_OF_ALGORITHMS = 8; + + public KeyGenAlgorithm[] getAllAlgorithms( Usage usage ) { + KeyGenAlgorithm[] algs = new KeyGenAlgorithm[NUMBER_OF_ALGORITHMS]; + + long[] indices = getAllAlgorithmIndices( usage ); + + int j = 0; + for( int i = 0; i <= indices.length; i++ ) { + switch( ( int ) indices[i] ) { + case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC: + algs[j] = PBE_MD2_DES_CBC; + j++; + break; + case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC: + algs[j] = PBE_MD5_DES_CBC; + j++; + break; + case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC: + algs[j] = PBE_SHA1_DES_CBC; + j++; + break; + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4: + algs[j] = PBE_SHA1_RC4_128; + j++; + break; + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4: + algs[j] = PBE_SHA1_RC4_40; + j++; + break; + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC: + algs[j] = PBE_SHA1_DES3_CBC; + j++; + break; + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: + algs[j] = PBE_SHA1_RC2_128_CBC; + j++; + break; + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: + algs[j] = PBE_SHA1_RC2_40_CBC; + j++; + break; + default: + continue; + } + } + + return algs; + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/PBEKeyGenParams.java b/mozilla/security/jss/org/mozilla/jss/crypto/PBEKeyGenParams.java new file mode 100644 index 00000000000..212c93b84f6 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/PBEKeyGenParams.java @@ -0,0 +1,102 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.crypto; + +import java.security.spec.AlgorithmParameterSpec; +import com.netscape.jss.util.Password; + +public class PBEKeyGenParams implements AlgorithmParameterSpec { + + private Password pass; + private byte[] salt; + private int iterations; + + private PBEKeyGenParams() { } + + static private final int DEFAULT_SALT_LENGTH = 8; + static private final int DEFAULT_ITERATIONS = 1; + + /** + * Creates PBE parameters. + * + * @param pass The password. It will be cloned, so the + * caller is still responsible for clearing it. It must not be null. + * @param salt The salt for the PBE algorithm. Will not be cloned. + * Must not be null. It is the responsibility of the caller to + * use the right salt length for the algorithm. Most algorithms + * use 8 bytes of salt. + * @param The iteration count for the PBE algorithm. + */ + public PBEKeyGenParams(Password pass, byte[] salt, int iterations) { + if(pass==null || salt==null) { + throw new NullPointerException(); + } + this.pass = (Password) pass.clone(); + this.salt = salt; + this.iterations = iterations; + } + + /** + * Returns a reference to the password, not a copy. + */ + public Password getPassword() { + return pass; + } + + /** + * Returns a reference to the salt. + */ + public byte[] getSalt() { + return salt; + } + + /** + * Returns the iteration count. + */ + public int getIterations() { + return iterations; + } + + /** + * Clears the password. This should be called when this object is no + * longer needed so the password is not left around in memory. + */ + public void clear() { + pass.clear(); + } + + protected void finalize() throws Throwable { + pass.clear(); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/PQGParamGenException.java b/mozilla/security/jss/org/mozilla/jss/crypto/PQGParamGenException.java new file mode 100644 index 00000000000..aa63d8c9d23 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/PQGParamGenException.java @@ -0,0 +1,39 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.crypto; + +public class PQGParamGenException extends Exception { + public PQGParamGenException() {} + public PQGParamGenException(String msg) { super(msg); } +} diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/PQGParams.c b/mozilla/security/jss/org/mozilla/jss/crypto/PQGParams.c new file mode 100644 index 00000000000..49da9dbc3bd --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/PQGParams.c @@ -0,0 +1,389 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +#include "_jni/com_netscape_jss_crypto_PQGParams.h" + +#include + +#include +#include +#include +#include /* for PQGParams */ +#include + +#include +#include +#include +#include + +static jobject +generate(JNIEnv *env, jclass PQGParamsClass, jint keySize, jint seedBytes); + +/********************************************************************** + * P Q G P a r a m s . g e n e r a t e ( keysize ) + * + */ +JNIEXPORT jobject JNICALL +Java_com_netscape_jss_crypto_PQGParams_generateNative__I + (JNIEnv *env, jclass PQGParamsClass, jint keySize) +{ + return generate(env, PQGParamsClass, keySize, 0); +} + +/********************************************************************** + * P Q G P a r a m s . g e n e r a t e ( keysize, seedBytes ) + * + */ +JNIEXPORT jobject JNICALL +Java_com_netscape_jss_crypto_PQGParams_generateNative__II + (JNIEnv *env, jclass PQGParamsClass, jint keySize, jint seedBytes) +{ + if(seedBytes < 20 || seedBytes > 255) { + JSS_throwMsg(env, INVALID_PARAMETER_EXCEPTION, + "Number of bytes in seed must be in range [20,255]"); + return NULL; + } + return generate(env, PQGParamsClass, keySize, seedBytes); +} + +#define ZERO_SECITEM(item) (item).data=NULL; (item).len=0; + +/********************************************************************** + * + * g e n e r a t e + * + * INPUTS + * env + * The JNI environment. + * this + * Reference to a Java PQGGenerator object. + * keySize + * The size of the key, which is actually the size of P in bits. + * seedBytes + * The length of the seed in bytes, or 0 to let the algorithm + * figure it out. + * RETURNS + * A new PQGParams object. + */ +static jobject +generate(JNIEnv *env, jclass PQGParamsClass, jint keySize, jint seedBytes) +{ + int keySizeIndex; + jobject newObject = NULL; + SECStatus status; + PQGParams *pParams=NULL; + PQGVerify *pVfy=NULL; + jbyteArray bytes; + jclass BigIntegerClass; + jmethodID BigIntegerConstructor; + jmethodID PQGParamsConstructor; + + /*----PQG parameters and friends----*/ + SECItem P; /* prime */ + SECItem Q; /* subPrime */ + SECItem G; /* base */ + SECItem H; + SECItem seed; + unsigned int counter; + + /*----Java versions of the PQG parameters----*/ + jobject jP; + jobject jQ; + jobject jG; + jobject jH; + jint jcounter; + jobject jSeed; + + /* basic argument validation */ + PR_ASSERT(env!=NULL && PQGParamsClass!=NULL); + + /* clear the SECItems so we can free them indiscriminately at the end */ + ZERO_SECITEM(P); + ZERO_SECITEM(Q); + ZERO_SECITEM(G); + ZERO_SECITEM(H); + ZERO_SECITEM(seed); + + + /*********************************************************************** + * PQG_ParamGen doesn't take a key size, it takes an index that points to + * a valid key size. + */ + keySizeIndex = PQG_PBITS_TO_INDEX(keySize); + if(keySizeIndex == -1 || keySize<512 || keySize>1024) { + JSS_throwMsg(env, INVALID_PARAMETER_EXCEPTION, + "DSA key size must be a multiple of 64 between 512 " + "and 1024, inclusive"); + goto finish; + } + + /*********************************************************************** + * Do the actual parameter generation. + */ + if(seedBytes == 0) { + status = PQG_ParamGen(keySizeIndex, &pParams, &pVfy); + } else { + status = PQG_ParamGenSeedLen(keySizeIndex, seedBytes, &pParams, &pVfy); + } + if(status != SECSuccess) { + JSS_throw(env, PQG_PARAM_GEN_EXCEPTION); + goto finish; + } + + /********************************************************************** + * NOTE: the new PQG parameters will be verified at the Java level. + */ + + /********************************************************************** + * Get ready for the BigIntegers + */ + BigIntegerClass = (*env)->FindClass(env, BIG_INTEGER_CLASS_NAME); + if(BigIntegerClass == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + BigIntegerConstructor = (*env)->GetMethodID(env, + BigIntegerClass, + BIG_INTEGER_CONSTRUCTOR_NAME, + BIG_INTEGER_CONSTRUCTOR_SIG); + if(BigIntegerConstructor == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + /*********************************************************************** + * Convert the parameters to Java types. + */ + if( PQG_GetPrimeFromParams( pParams, &P) || + PQG_GetSubPrimeFromParams( pParams, &Q) || + PQG_GetBaseFromParams( pParams, &G) || + PQG_GetHFromVerify( pVfy, &H) || + PQG_GetSeedFromVerify( pVfy, &seed) ) + { + JSS_throw(env, PQG_PARAM_GEN_EXCEPTION); + goto finish; + } + counter = PQG_GetCounterFromVerify(pVfy); + + /* + * construct P + */ + bytes = JSS_OctetStringToByteArray(env, &P); + if(bytes==NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + jP = (*env)->NewObject(env, BigIntegerClass, BigIntegerConstructor, bytes); + if(jP==NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + /* + * construct Q + */ + bytes = JSS_OctetStringToByteArray(env, &Q); + if(bytes==NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + jQ = (*env)->NewObject(env, BigIntegerClass, BigIntegerConstructor, bytes); + if(jQ==NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + /* + * construct G + */ + bytes = JSS_OctetStringToByteArray(env, &G); + if(bytes==NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + jG = (*env)->NewObject(env, BigIntegerClass, BigIntegerConstructor, bytes); + if(jG==NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + /* + * construct seed + */ + bytes = JSS_OctetStringToByteArray(env, &seed); + if(bytes==NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + jSeed = (*env)->NewObject(env, BigIntegerClass, BigIntegerConstructor, + bytes); + if(jSeed==NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + /* + * construct H + */ + bytes = JSS_OctetStringToByteArray(env, &H); + if(bytes==NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + jH = (*env)->NewObject(env, BigIntegerClass, BigIntegerConstructor, bytes); + if(jH==NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + /* + * construct counter + */ + jcounter = counter; + + /********************************************************************** + * Construct the PQGParams object + */ + PQGParamsConstructor = (*env)->GetMethodID( + env, + PQGParamsClass, + PQG_PARAMS_CONSTRUCTOR_NAME, + PQG_PARAMS_CONSTRUCTOR_SIG); + if(PQGParamsConstructor==NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + newObject = (*env)->NewObject( env, + PQGParamsClass, + PQGParamsConstructor, + jP, + jQ, + jG, + jSeed, + jcounter, + jH); + + +finish: + if(pParams!=NULL) { + PQG_DestroyParams(pParams); + } + if(pVfy!=NULL) { + PQG_DestroyVerify(pVfy); + } + SECITEM_FreeItem(&P, PR_FALSE /*don't free P itself*/); + SECITEM_FreeItem(&Q, PR_FALSE); + SECITEM_FreeItem(&G, PR_FALSE); + SECITEM_FreeItem(&H, PR_FALSE); + SECITEM_FreeItem(&seed, PR_FALSE); + + return newObject; +} + +/********************************************************************** + * + * P Q G P a r a m s . p a r a m s A r e V a l i d + * + */ +JNIEXPORT jboolean JNICALL +Java_com_netscape_jss_crypto_PQGParams_paramsAreValidNative + (JNIEnv *env, jobject this, jbyteArray jP, jbyteArray jQ, jbyteArray jG, + jbyteArray jSeed, jint jCounter, jbyteArray jH) +{ + jboolean valid=JNI_FALSE; + PQGParams *pParams=NULL; + PQGVerify *pVfy=NULL; + SECStatus verifyResult; + + /*---PQG and verification params in C---*/ + SECItem P; + SECItem Q; + SECItem G; + SECItem seed; + SECItem H; + unsigned int counter; + + PR_ASSERT(env!=NULL && this!=NULL); + + /* clear the secitems so we can free them indiscriminately later */ + ZERO_SECITEM(P); + ZERO_SECITEM(Q); + ZERO_SECITEM(G); + ZERO_SECITEM(seed); + ZERO_SECITEM(H); + + /********************************************************************** + * Extract the Java parameters + */ + if( JSS_ByteArrayToOctetString(env, jP, &P) || + JSS_ByteArrayToOctetString(env, jQ, &Q) || + JSS_ByteArrayToOctetString(env, jG, &G) || + JSS_ByteArrayToOctetString(env, jSeed, &seed) || + JSS_ByteArrayToOctetString(env, jH, &H) ) + { + goto finish; + } + counter = jCounter; + + /*********************************************************************** + * Construct PQGParams and PQGVerify structures. + */ + pParams = PQG_NewParams(&P, &Q, &G); + pVfy = PQG_NewVerify(counter, &seed, &H); + if(pParams==NULL || pVfy==NULL) { + JSS_throw(env, OUT_OF_MEMORY_ERROR); + goto finish; + } + + /*********************************************************************** + * Perform the verification. + */ + if( PQG_VerifyParams(pParams, pVfy, &verifyResult) != PR_SUCCESS) { + JSS_throw(env, OUT_OF_MEMORY_ERROR); + goto finish; + } + if(verifyResult == SECSuccess) { + valid = JNI_TRUE; + } + +finish: + SECITEM_FreeItem(&P, PR_FALSE /*don't free P itself*/); + SECITEM_FreeItem(&Q, PR_FALSE); + SECITEM_FreeItem(&G, PR_FALSE); + SECITEM_FreeItem(&seed, PR_FALSE); + SECITEM_FreeItem(&H, PR_FALSE); + PQG_DestroyParams(pParams); + PQG_DestroyVerify(pVfy); + + return valid; +} diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/PQGParams.java b/mozilla/security/jss/org/mozilla/jss/crypto/PQGParams.java new file mode 100644 index 00000000000..c2b6b14032f --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/PQGParams.java @@ -0,0 +1,243 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.crypto; + +import java.math.BigInteger; +import java.security.spec.DSAParameterSpec; +import com.netscape.jss.util.Assert; + +/** + * PQG parameters for DSA key generation, along with the seed, counter, + * and H values for verification. + *

This class has two main purposes: + * generating PQG parameters and verifying PQG parameters. To generate + * PQG parameters, call one of the static generate methods. + * They will return a new set of PQG paramters. To verify existing PQG + * parameters, create a new PQGParams object with the + * constructor and call paramsAreValid on the object. + * + *

It is necessary to call CryptoManager.initialize before + * using this class. + * + */ +public class PQGParams extends DSAParameterSpec { + + /** + * Creates a PQGParams object from a set of pre-computed DSA + * parameters. + * + * @param P The DSA prime parameter. + * @param Q The DSA sub-prime parameter. + * @param G The DSA base parameter. + * @param seed The Seed used to calculate P, Q, and G. + * @param counter The Counter (C) used to calculate P, Q, and G. + * @param H The H value used to generate P, Q, and G. + */ + public PQGParams(BigInteger P, BigInteger Q, BigInteger G, + BigInteger seed, int counter, BigInteger H) + { + super(P, Q, G); + this.seed = seed; + this.counter = counter; + this.H = H; + } + + /** + * Generates P, Q, and G parameters for DSA key generation. Also + * provides the seed, counter, and H values for verification of the + * P, Q, and G. The parameters are generated and then verified + * before being returned. The length of the Seed will equal the + * length of P. + * + * It is necessary to call one of the + * CryptoManager.initialize functions before calling + * this method. + * + * @param keySize The size of P in bits. Keys generated by these P, + * Q, and G values will have this length. Valid key sizes + * are multiples of 64 in the closed interval [512,1024]. + * This also dictates the length of H and Seed. + * @return A new set of P, Q, and G parameters, along with the Seed, + * Counter, and H values used to generate them. + * @exception java.security.InvalidParameterException If the keySize + * is outside the bounds described by the DSA key pair + * generation algorithm. + * @exception com.netscape.jss.crypto.PQGParamGenException If an error + * occurs during the generation process. + * @see com.netscape.jss.CryptoManager#initialize + */ + public static PQGParams + generate(int keySize) + throws java.security.InvalidParameterException, + PQGParamGenException + { + PQGParams pqg = generateNative(keySize); + if( ! pqg.paramsAreValid() ) { + throw new PQGParamGenException( + "Generated parameters did not verify correctly"); + } + return pqg; + } + + /** + * Does the actual work of generation, but does not verify. + */ + private static native PQGParams + generateNative(int keySize) + throws java.security.InvalidParameterException, + PQGParamGenException; + + /** + * Generates P, Q, and G parameters for DSA key generation. Also + * provides the seed, counter, and H values for verification of the + * P, Q, and G. The parameters are generated and then verified + * before being returned. + * + * It is necessary to call one of the + * CryptoManager.initialize functions before calling + * this method. + * + * @param keySize The size of P in bits. Keys generated by these P, + * Q, and G values will have this length. Valid key sizes + * are multiples of 64 in the closed interval [512,1024]. + * This also dictates the length of H. + * @param seedBytes The number of bytes in the Seed value used to + * generate P, Q, and G. seedBytes must be + * from the closed interval [20,255]. + * @return A new set of P, Q, and G parameters, along with the Seed, + * Counter, and H values used to generate them. + * @exception java.security.InvalidParameterException If the keySize + * or number of seed bytes is outside the bounds described by the + * DSA key pair generation algorithm. + * @exception com.netscape.jss.crypto.PQGParamGenException If an error + * occurs during the generation process. + * @see com.netscape.jss.CryptoManager#initialize + */ + public static PQGParams + generate(int keySize, int seedBytes) + throws java.security.InvalidParameterException, + PQGParamGenException + { + PQGParams pqg = generateNative(keySize, seedBytes); + if( ! pqg.paramsAreValid() ) { + throw new PQGParamGenException( + "Generated parameters did not verify correctly"); + } + return pqg; + } + + /** + * Does the actual work of generation, but does not verify. + */ + private static native PQGParams + generateNative(int keySize, int seedBytes) + throws java.security.InvalidParameterException, + PQGParamGenException; + + /** + * Produces an unsigned byte-array representation of a BigInteger. + * + *

BigInteger adds an extra sign bit to the beginning of its byte + * array representation. In some cases this will cause the size + * of the byte array to increase, which may be unacceptable for some + * applications. This function returns a minimal byte array representing + * the BigInteger without extra sign bits. + * + * @return An unsigned, big-endian byte array representation + * of a BigInteger. + */ + public static byte[] BigIntegerToUnsignedByteArray(BigInteger big) { + byte[] ret; + + // big must not be negative + Assert.assert(big.signum() != -1); + + // bitLength is the size of the data without the sign bit. If + // it exactly fills an integral number of bytes, that means a whole + // new byte will have to be added to accomodate the sign bit. In + // this case we need to remove the first byte. + if(big.bitLength() % 8 == 0) { + byte[] array = big.toByteArray(); + // The first byte should just be sign bits + Assert.assert( array[0] == 0 ); + ret = new byte[array.length-1]; + System.arraycopy(array, 1, ret, 0, ret.length); + } else { + ret = big.toByteArray(); + } + return ret; + } + + /** + * Verifies the PQG parameters using the seed, counter, and H values. + * @return true if the parameters verified correctly, false if they + * did not verify. + */ + public boolean paramsAreValid() { + return paramsAreValidNative(BigIntegerToUnsignedByteArray( getP() ), + BigIntegerToUnsignedByteArray( getQ() ), + BigIntegerToUnsignedByteArray( getG() ), + BigIntegerToUnsignedByteArray( seed ), + counter, + BigIntegerToUnsignedByteArray( H )); + } + + private native boolean paramsAreValidNative(byte[] P, byte[] Q, byte[]G, + byte[] seed, int counter, byte[] H); + + /** + * @return The Seed used to generate P, Q, and G. + */ + public BigInteger getSeed() { + return seed; + } + + /** + * @return The Counter (C) used to generate P, Q, and G. + */ + public int getCounter() { + return counter; + } + + /** + * @return The H value used to generate P, Q, and G. + */ + public BigInteger getH() { + return H; + } + + private BigInteger seed; + private int counter; + private BigInteger H; +} diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/PrivateKey.java b/mozilla/security/jss/org/mozilla/jss/crypto/PrivateKey.java new file mode 100644 index 00000000000..6c6b6e367c4 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/PrivateKey.java @@ -0,0 +1,120 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.crypto; + +import com.netscape.jss.asn1.OBJECT_IDENTIFIER; +import java.util.Hashtable; +import com.netscape.jss.util.Assert; +import java.security.NoSuchAlgorithmException; + +/** + * Private Keys used by JSS. All the private keys handled by JSS are + * of this type, which is a subtype of java.security.PrivateKey. + */ +public interface PrivateKey extends java.security.PrivateKey +{ + + public static final Type RSA = Type.RSA; + public static final Type DSA = Type.DSA; + + /** + * Returns the type (RSA or DSA) of this private key. + */ + public Type getType(); + + /** + * Returns the unique ID of this key. Unique IDs can be used to match + * certificates to keys. + * + * @see com.netscape.jss.crypto.TokenCertificate#getUniqueID + */ + public byte[] getUniqueID() throws TokenException; + + /** + * Returns the size, in bits, of the modulus of an RSA key. + * Returns -1 for other types of keys. + */ + public int getStrength(); + + /** + * Returns the CryptoToken that owns this private key. Cryptographic + * operations with this key may only be performed on the token that + * owns the key. + */ + public CryptoToken getOwningToken(); + + public static final class Type { + private OBJECT_IDENTIFIER oid; + private String name; + + private Type() { } + + private Type(OBJECT_IDENTIFIER oid, String name) { + this.oid = oid; + this.name = name; + Object old = oidMap.put(oid, this); + Assert.assert( old == null ); + } + + private static Hashtable oidMap = new Hashtable(); + + + public static Type fromOID(OBJECT_IDENTIFIER oid) + throws NoSuchAlgorithmException + { + Object obj = oidMap.get(oid); + if( obj == null ) { + throw new NoSuchAlgorithmException(); + } + return (Type) obj; + } + + /** + * Returns a string representation of the algorithm, such as + * "RSA" or "DSA". + */ + public String toString() { + return name; + } + + public OBJECT_IDENTIFIER toOID() { + return oid; + } + + public static final Type RSA = new Type( + OBJECT_IDENTIFIER.PKCS1.subBranch(1), "RSA" ); + public static final Type DSA = new Type( + Algorithm.ANSI_X9_ALGORITHM.subBranch(1), "DSA" ); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/RSAParameterSpec.java b/mozilla/security/jss/org/mozilla/jss/crypto/RSAParameterSpec.java new file mode 100644 index 00000000000..98c868048a6 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/RSAParameterSpec.java @@ -0,0 +1,66 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.crypto; + +import java.security.spec.AlgorithmParameterSpec; +import java.math.BigInteger; + +/** + * This class specifies the parameters used for generating an RSA key pair. + */ +public class RSAParameterSpec implements AlgorithmParameterSpec { + + /** + * Creates a new RSAParameterSpec with the specified parameter values. + * @param keySize The size of the modulus in bits. + * @param publicExponent The public exponent e. Common values + * are 3, 17, and 65537. 65537 is recommended. + */ + public RSAParameterSpec(int keySize, BigInteger publicExponent) { + this.keySize = keySize; + this.publicExponent = publicExponent; + } + + /** + * Returns the size of the modulus in bits. + */ + public int getKeySize() { return keySize; } + + /** + * Returns the public exponent e. + */ + public BigInteger getPublicExponent() { return publicExponent; } + + private int keySize; + private BigInteger publicExponent; +} diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/ShortBufferException.java b/mozilla/security/jss/org/mozilla/jss/crypto/ShortBufferException.java new file mode 100644 index 00000000000..e805a8c03da --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/ShortBufferException.java @@ -0,0 +1,39 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.crypto; + +/** + * This class is a placeholder for javax.crypto.ShortBufferException until + * we move to JDK 1.2. + */ +public class ShortBufferException extends Exception { } diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/Signature.java b/mozilla/security/jss/org/mozilla/jss/crypto/Signature.java new file mode 100644 index 00000000000..10cbdd2b37c --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/Signature.java @@ -0,0 +1,220 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.crypto; + +import com.netscape.jss.util.*; +import java.security.*; +import java.security.spec.AlgorithmParameterSpec; + +/** + * A class for producing and verifying digital signatures. + * Instances of this class can be obtain from CryptoTokens. + * + * @see com.netscape.jss.crypto.CryptoToken#getSignatureContext + */ +public class Signature { + + protected Signature() { } + + Signature(SignatureAlgorithm algorithm, SignatureSpi engine) { + this.algorithm = algorithm; + this.engine = engine; + } + + /** + * This is not supported yet. + */ + public Provider getProvider() { + Assert.notYetImplemented("Signature.getProvider"); + return null; + } + + /** + * Supplying sources of randoms is not supported yet. + public void initSign(PrivateKey privateKey, SecureRandom random) + throws InvalidKeyException, TokenException + { + engine.engineInitSign(privateKey, random); + } + */ + + /** + * Initialize the signature context for signing. + * @param privateKey The private key with which to sign. + * @exception InvalidKeyException If the key is the wrong type for the + * algorithm or does not exist on the token of this signature + * context. + * @exception TokenException If an error occurred on the token. + */ + public void initSign(PrivateKey privateKey) + throws InvalidKeyException, TokenException + { + engine.engineInitSign(privateKey); + } + + /** + * Initialize the signature context for verifying. + * @param publicKey The public key with which to verify the signature. + * @exception InvalidKeyException If the key is the wrong type for the + * algorithm. + * @exception TokenException If an error occurs on the token. + */ + public void initVerify(PublicKey publicKey) + throws InvalidKeyException, TokenException + { + engine.engineInitVerify(publicKey); + } + + /** + * Set parameters for the signing algorithm. This is currently not + * supported or needed. + * @param params Parameters for the signing algorithm. + * @exception InvalidAlgorithmParameterException If there is something wrong + * with the parameters. + * @exception TokenException If an error occurs on the token. + */ + public void setParameter(AlgorithmParameterSpec params) + throws InvalidAlgorithmParameterException, TokenException + { + engine.engineSetParameter(params); + } + + /** + * Finish a signing operation and return the signature. + * @exception SignatureException If an error occurs with the signing + * operation. + * @exception TokenException If an error occurs on the token. + * @return The signature. + */ + public byte[] sign() throws SignatureException, TokenException + { + return engine.engineSign(); + } + + /** + * Finish a signing operation and store the signature in the provided + * buffer. + * @param outbuf Buffer to hold the signature + * @param offset Offset in buffer at which to store signature. + * @param len Number of bytes of buffer available for signature. + * @return int The number of bytes placed into outbuf. + * @exception SignatureException If an error occurred while signing, or + * len was insufficient to contain the signature. + * @exception TokenException If an error occurred on the token. + */ + public int sign(byte[] outbuf, int offset, int len) + throws SignatureException, TokenException + { + return engine.engineSign(outbuf, offset, len); + } + + /** + * Finish a verification operation. + * @param signature The signature to be verified. + * @return true if the signature is valid, false if it is invalid. + * @exception SignatureException If an error occurred with the verification + * operation + * @exception TokenException If an error occurred on the token. + */ + public boolean verify(byte[] signature) + throws SignatureException, TokenException + { + return engine.engineVerify(signature); + } + + /** + * Provide more data for a signature or verification operation. + * @param b A byte to be signed or verified. + * @exception SignatureException If an error occurs in the + * signature/verifcation. + * @exception TokenException If an error occurs on the token. + */ + public void update(byte b) + throws SignatureException, TokenException + { + engine.engineUpdate(b); + } + + /** + * Provide more data for a signature or verification operation. + * @param data An array of bytes to be signed or verified. + * @exception SignatureException If an error occurs in the + * signature/verifcation. + * @exception TokenException If an error occurs on the token. + */ + public void update(byte[] data) + throws SignatureException, TokenException + { + engine.engineUpdate(data, 0, data.length); + } + + /** + * Provide more data for a signature or verification operation. + * @param data An array of bytes, some of which will be signed or verified. + * @param off The beginning offset of the bytes to be signed/verified. + * @param len The number of bytes to be signed/verified. + * @exception SignatureException If an error occurs in the + * signature/verifcation. + * @exception TokenException If an error occurs on the token. + */ + public void update(byte[] data, int off, int len) + throws SignatureException, TokenException + { + engine.engineUpdate(data, off, len); + } + + /** + * Returns the name of the algorithm to be used for signing. + */ + public String getAlgorithm() { + return algorithm.toString(); + } + + /** + * Returns the algorithm to be used for signing. + */ + public SignatureAlgorithm getAlgorithmID() { + return algorithm; + } + + /** + * Cloning is not supported yet + */ + protected Object clone() throws CloneNotSupportedException { + // no cloning for now + throw new CloneNotSupportedException(); + } + + protected SignatureAlgorithm algorithm; + protected SignatureSpi engine; +} diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/SignatureAlgorithm.java b/mozilla/security/jss/org/mozilla/jss/crypto/SignatureAlgorithm.java new file mode 100644 index 00000000000..f1fda358cd6 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/SignatureAlgorithm.java @@ -0,0 +1,193 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.crypto; + +import com.netscape.jss.asn1.OBJECT_IDENTIFIER; +import java.util.Hashtable; +import java.security.NoSuchAlgorithmException; + +/** + * Algorithms that can be used for signing. + */ +public class SignatureAlgorithm extends Algorithm { + + private static Hashtable oidMap = new Hashtable(); + + protected SignatureAlgorithm(int oidIndex, String name, + SignatureAlgorithm signingAlg, DigestAlgorithm digestAlg, + OBJECT_IDENTIFIER oid) + { + super(oidIndex, name, oid); + if(signingAlg == null) { + this.signingAlg = this; + } else { + this.signingAlg = signingAlg; + } + this.digestAlg = digestAlg; + oidMap.put(oid, this); + } + + /** + * Looks up the signature algorithm with the given OID. + * @exception NoSuchAlgorithmException If no algorithm is found with this + * OID. + */ + public static SignatureAlgorithm fromOID(OBJECT_IDENTIFIER oid) + throws NoSuchAlgorithmException + { + Object alg = oidMap.get(oid); + if( alg == null ) { + throw new NoSuchAlgorithmException(); + } + return (SignatureAlgorithm) alg; + } + + /** + * The raw encryption portion of the signature algorithm. For example, + * SignatureAlgorithm.RSASignatureWithMD2Digest.getSigningAlg == + * SignatureAlgorithm.RSASignature. + */ + public Algorithm getSigningAlg() { + return signingAlg; + } + public SignatureAlgorithm getRawAlg() { + return signingAlg; + } + private SignatureAlgorithm signingAlg; + + /** + * The digest portion of the signature algorithm. + */ + public DigestAlgorithm getDigestAlg() throws NoSuchAlgorithmException { + if( digestAlg == null ) { + throw new NoSuchAlgorithmException(); + } + return digestAlg; + } + private DigestAlgorithm digestAlg; + + ////////////////////////////////////////////////////////////////////// + // Signature Algorithms + ////////////////////////////////////////////////////////////////////// + + /********************************************************************** + * Raw RSA signing. This algorithm does not do any hashing, it merely + * encrypts its input, which should be a hash. + */ + public static final SignatureAlgorithm + RSASignature = new SignatureAlgorithm(SEC_OID_PKCS1_RSA_ENCRYPTION, "RSA", + null, null, OBJECT_IDENTIFIER.PKCS1.subBranch(1) ); + + /********************************************************************** + * Raw DSA signing. This algorithm does not do any hashing, it merely + * encrypts its input, which should be a hash. + */ + public static final SignatureAlgorithm + DSASignature = new SignatureAlgorithm(SEC_OID_ANSIX9_DSA_SIGNATURE, "DSA", + null, null, ANSI_X9_ALGORITHM.subBranch(1) ); + + ////////////////////////////////////////////////////////////////////// + public static final SignatureAlgorithm + RSASignatureWithMD2Digest = + new SignatureAlgorithm(SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION, + "RSASignatureWithMD2Digest", RSASignature, DigestAlgorithm.MD2, + OBJECT_IDENTIFIER.PKCS1.subBranch(2) ); + + ////////////////////////////////////////////////////////////////////// + public static final SignatureAlgorithm + RSASignatureWithMD5Digest = + new SignatureAlgorithm(SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION, + "RSASignatureWithMD5Digest", RSASignature, DigestAlgorithm.MD5, + OBJECT_IDENTIFIER.PKCS1.subBranch(4) ); + + ////////////////////////////////////////////////////////////////////// + public static final SignatureAlgorithm + RSASignatureWithSHA1Digest = + new SignatureAlgorithm(SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION, + "RSASignatureWithSHA1Digest", RSASignature, DigestAlgorithm.SHA1, + OBJECT_IDENTIFIER.PKCS1.subBranch(5) ); + + ////////////////////////////////////////////////////////////////////// + public static final SignatureAlgorithm + DSASignatureWithSHA1Digest = + new SignatureAlgorithm(SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST, + "DSASignatureWithSHA1Digest", DSASignature, DigestAlgorithm.SHA1, + ANSI_X9_ALGORITHM.subBranch(3) ); + + ////////////////////////////////////////////////////////////////////// + // Export control code + ////////////////////////////////////////////////////////////////////// + + private static final int NUMBER_OF_ALGORITHMS = 6; + + public SignatureAlgorithm[] getAllAlgorithms( Usage usage ) { + SignatureAlgorithm[] algs = new + SignatureAlgorithm[NUMBER_OF_ALGORITHMS]; + + long[] indices = getAllAlgorithmIndices( usage ); + + int j = 0; + for( int i = 0; i <= indices.length; i++ ) { + switch( ( int ) indices[i] ) { + case SEC_OID_PKCS1_RSA_ENCRYPTION: + algs[j] = RSASignature ; + j++; + break; + case SEC_OID_ANSIX9_DSA_SIGNATURE: + algs[j] = DSASignature; + j++; + break; + case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION: + algs[j] = RSASignatureWithMD2Digest; + j++; + break; + case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION: + algs[j] = RSASignatureWithMD5Digest; + j++; + break; + case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION: + algs[j] = RSASignatureWithSHA1Digest; + j++; + break; + case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST: + algs[j] = DSASignatureWithSHA1Digest; + j++; + break; + default: + continue; + } + } + + return algs; + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/SignatureSpi.java b/mozilla/security/jss/org/mozilla/jss/crypto/SignatureSpi.java new file mode 100644 index 00000000000..33036d8e0f5 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/SignatureSpi.java @@ -0,0 +1,71 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.crypto; + +import java.security.*; +import java.security.SecureRandom; +import java.security.spec.AlgorithmParameterSpec; + +/** + * You don't need to use this unless you are hacking JSS. + */ +public abstract class SignatureSpi { + + public abstract void engineInitVerify(PublicKey publicKey) + throws InvalidKeyException, TokenException; + + public abstract void engineInitSign(PrivateKey privateKey) + throws InvalidKeyException, TokenException; + + public abstract void engineInitSign(PrivateKey privateKey, + SecureRandom random) + throws InvalidKeyException, TokenException; + + public abstract void engineUpdate(byte b) + throws SignatureException, TokenException; + + public abstract void engineUpdate(byte[] b, int off, int len) + throws SignatureException, TokenException; + + public abstract byte[] engineSign() + throws SignatureException, TokenException; + + public abstract int engineSign(byte[] outbuf, int offset, int len) + throws SignatureException, TokenException; + + public abstract boolean engineVerify(byte[] sigBytes) + throws SignatureException, TokenException; + + public abstract void engineSetParameter(AlgorithmParameterSpec params) + throws InvalidAlgorithmParameterException, TokenException; +} diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/SymmetricKey.java b/mozilla/security/jss/org/mozilla/jss/crypto/SymmetricKey.java new file mode 100644 index 00000000000..48e2d06e59c --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/SymmetricKey.java @@ -0,0 +1,68 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.crypto; + +public interface SymmetricKey { + + public static final Type DES = Type.DES; + public static final Type DES3 = Type.DES3; + public static final Type RC4 = Type.RC4; + public static final Type RC2 = Type.RC2; + public static final Type SHA1_HMAC = Type.SHA1_HMAC; + public Type getType(); + + public CryptoToken getOwningToken(); + + public int getStrength(); + + public byte[] getKeyData() throws NotExtractableException; + + public static class NotExtractableException extends Exception { } + + public final static class Type { + private String name; + private Type() { } + private Type(String name) { + this.name = name; + } + public static final Type DES = new Type("DES"); + public static final Type DES3 = new Type("DES3"); + public static final Type RC4 = new Type("RC4"); + public static final Type RC2 = new Type("RC2"); + public static final Type SHA1_HMAC = new Type("SHA1_HMAC"); + + public String toString() { + return name; + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/TokenCertificate.java b/mozilla/security/jss/org/mozilla/jss/crypto/TokenCertificate.java new file mode 100644 index 00000000000..a45269d3baa --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/TokenCertificate.java @@ -0,0 +1,58 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.crypto; + +/** + * An X509 Certificate that lives on a PKCS #11 token. + * Many of the X509Certificates returned by JSS calls are actually + * TokenCertificates. + * To find out if an X509Certificate is a TokenCertificate, use + * instanceof. + */ +public interface TokenCertificate extends X509Certificate { + + /** + * Returns the unique ID of this key. Unique IDs can be used to match + * certificates to keys. + * + * @see com.netscape.jss.crypto.PrivateKey#getUniqueID + */ + public abstract byte[] getUniqueID(); + + /** + * Returns the CryptoToken that owns this certificate. Cryptographic + * operations with this key may only be performed on the token that + * owns the key. + */ + public abstract CryptoToken getOwningToken(); +} diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/TokenException.java b/mozilla/security/jss/org/mozilla/jss/crypto/TokenException.java new file mode 100644 index 00000000000..535be3800b9 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/TokenException.java @@ -0,0 +1,47 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.crypto; + +/** + * This class indicates that an unknown error occurred on a CryptoToken. + * The nature of CryptoTokens makes such unpredictable errors possible. + * For example, a smartcard could be yanked out of its slot in the middle + * of a cryptographic operation. + */ +public class TokenException extends Exception { + public TokenException() { super(); } + + public TokenException(String mesg) { + super(mesg); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/TokenSupplier.java b/mozilla/security/jss/org/mozilla/jss/crypto/TokenSupplier.java new file mode 100644 index 00000000000..f14af8301b9 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/TokenSupplier.java @@ -0,0 +1,44 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.crypto; + +/** + * An interface that allows providers to access CryptoManager without actually + * knowing about CryptoManager. This is necessary to prevent cyclic + * dependencies. CryptoManager knows about the providers, so the providers + * can't know about CryptoManager. Instead, CryptoManager implements + * this interface. + */ +public interface TokenSupplier { + public CryptoToken getInternalCryptoToken(); +} diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/TokenSupplierManager.java b/mozilla/security/jss/org/mozilla/jss/crypto/TokenSupplierManager.java new file mode 100644 index 00000000000..9cf54581f60 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/TokenSupplierManager.java @@ -0,0 +1,51 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.crypto; + +/** + * The com.netscape.jss.provider package comes before CryptoManager in + * the depency list, so this class is used to allow them to access + * CryptoManager sneakily. When CryptoManager initializes, it registers + * itself as a token supplier with setTokenSupplier. Then + * the providers call getTokenSupplier when they need to use + * CryptoManager. CryptoManager implements the TokenSupplier interface. + */ +public class TokenSupplierManager { + static private TokenSupplier supplier; + static public void setTokenSupplier(TokenSupplier ts) { + supplier = ts; + } + static public TokenSupplier getTokenSupplier() { + return supplier; + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/Tunnel.java b/mozilla/security/jss/org/mozilla/jss/crypto/Tunnel.java new file mode 100644 index 00000000000..fea3939d930 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/Tunnel.java @@ -0,0 +1,47 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.crypto; + +/** + * This is a private JSS class that allows the pkcs11 package access + * to some of the + * package methods in the crypto package. A friend declaration would + * have been ideal. + */ +public class Tunnel { + protected static Signature + ConstructSignature( SignatureAlgorithm alg, SignatureSpi engine) { + return new Signature(alg, engine); + } +} + diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/X509Certificate.java b/mozilla/security/jss/org/mozilla/jss/crypto/X509Certificate.java new file mode 100644 index 00000000000..750ae30ccf4 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/X509Certificate.java @@ -0,0 +1,85 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.crypto; + +import java.security.Principal; +import java.math.BigInteger; + +/** + * Certificates handled by JSS. All certificates handled by JSS are + * of this type, which is a subtype of java.security.cert.X509Certificate. + */ +public interface X509Certificate +{ + /** + * Returns the DER encoding of this certificate. + */ + public byte[] getEncoded() + throws java.security.cert.CertificateEncodingException; + + /** + * Returns the possibly-null nickname of this certificate. + */ + public abstract String getNickname(); + + /** + * Extracts the Public Key from this certificate. + */ + public abstract java.security.PublicKey getPublicKey(); + + /** + * Returns the RFC 1485 ASCII encoding of the Subject Name. + */ + public abstract Principal + getSubjectDN(); + + /** + * Returns the RFC 1485 ASCII encoding of the issuer's Subject Name. + */ + public abstract Principal + getIssuerDN(); + + /** + * Returns the serial number of this certificate. + */ + public abstract BigInteger + getSerialNumber(); + + /** + * Returns the version number of this X.509 certificate. + * 0 means v1, 1 means v2, 2 means v3. + */ + public abstract int + getVersion(); + +} diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/config.mk b/mozilla/security/jss/org/mozilla/jss/crypto/config.mk new file mode 100644 index 00000000000..6bdda6bde1b --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/config.mk @@ -0,0 +1,66 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +####################################################################### +# Set the LD_LIBS value to encompass all static JSS, security, and # +# dbm libraries # +####################################################################### + +LD_LIBS += $(LIBJSSUTIL) \ + $(LIBJSSPOLICY) \ + $(LIBSECMOD) \ + $(LIBCERT) \ + $(LIBKEY) \ + $(LIBCRYPTO) \ + $(LIBHASH) \ + $(LIBSECUTIL) \ + $(LIBDBM) \ + $(NULL) + +####################################################################### +# Append additional LD_LIBS value to encompass all dynamic NSPR 2.0, # +# java, and system libraries # +####################################################################### + +ifeq ($(OS_ARCH), WINNT) + LD_LIBS += $(DLLPLDS) $(DLLPLC) $(DLLPR) $(DLLSYSTEM) +else + LD_LIBS += -L$(SOURCE_LIB_DIR) -lplds3 -lplc3 -lnspr3 $(DLLSYSTEM) +endif + +####################################################################### +# Turn off any Export Control Policy for these libraries # +####################################################################### + +POLICY = + diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/manifest.mn b/mozilla/security/jss/org/mozilla/jss/crypto/manifest.mn new file mode 100644 index 00000000000..2948ec09e2e --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/manifest.mn @@ -0,0 +1,160 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +CORE_DEPTH = ../../../../.. + +MODULE = ninja + +NS_USE_JDK = 1 + +REQUIRES = nspr20 dbm security + +PACKAGE = com/netscape/jss/crypto + +JNI_GEN = \ + com.netscape.jss.crypto.Algorithm \ + com.netscape.jss.crypto.EncryptionAlgorithm \ + com.netscape.jss.crypto.PQGParams \ + $(NULL) + +PRIVATE_EXPORTS = \ + Algorithm.h \ + $(NULL) + +CLASSES = \ + Algorithm \ + AlreadyInitializedException \ + BadPaddingException \ + Cipher \ + CryptoStore \ + CryptoToken \ + DigestAlgorithm \ + EncryptionAlgorithm \ + HMACAlgorithm \ + IllegalBlockSizeException \ + InvalidDERException \ + InvalidKeyFormatException \ + InternalCertificate \ + IVParameterSpec \ + KeyAlreadyImportedException \ + KeyGenAlgorithm \ + KeyGenerator \ + KeyPairAlgorithm \ + KeyPairGenerator \ + KeyPairGeneratorSpi \ + KeyWrapAlgorithm \ + KeyWrapper \ + JSSMessageDigest \ + NoSuchItemOnTokenException \ + NoSuchPaddingException \ + ObjectNotFoundException \ + PBEAlgorithm \ + PBEKeyGenParams \ + PrivateKey \ + PQGParams \ + PQGParamGenException \ + RSAParameterSpec \ + JSSSecureRandom \ + ShortBufferException \ + Signature \ + SignatureSpi \ + SignatureAlgorithm \ + SymmetricKey \ + TokenCertificate \ + TokenException \ + TokenSupplier \ + TokenSupplierManager \ + Tunnel \ + X509Certificate \ + $(NULL) + +PRIVATE_CLASSES = \ + $(NULL) + +JSRCS = \ + Algorithm.java \ + AlreadyInitializedException.java \ + BadPaddingException.java \ + Cipher.java \ + CryptoStore.java \ + CryptoToken.java \ + DigestAlgorithm.java \ + EncryptionAlgorithm.java \ + HMACAlgorithm.java \ + IllegalBlockSizeException.java \ + InvalidDERException.java \ + InvalidKeyFormatException.java \ + InternalCertificate.java \ + IVParameterSpec.java \ + KeyAlreadyImportedException.java \ + KeyGenAlgorithm.java \ + KeyGenerator.java \ + KeyPairAlgorithm.java \ + KeyPairGenerator.java \ + KeyPairGeneratorSpi.java \ + KeyWrapAlgorithm.java \ + KeyWrapper.java \ + JSSMessageDigest.java \ + NoSuchItemOnTokenException.java \ + NoSuchPaddingException.java \ + ObjectNotFoundException.java \ + PBEAlgorithm.java \ + PBEKeyGenParams.java \ + PrivateKey.java \ + PQGParams.java \ + PQGParamGenException.java \ + RSAParameterSpec.java \ + JSSSecureRandom.java \ + ShortBufferException.java \ + Signature.java \ + SignatureAlgorithm.java \ + SignatureSpi.java \ + SymmetricKey.java \ + TokenCertificate.java \ + TokenException.java \ + Tunnel.java \ + TokenSupplier.java \ + TokenSupplierManager.java \ + X509Certificate.java \ + $(NULL) + +PRIVATE_JSRCS = \ + $(NULL) + + +CSRCS = Algorithm.c \ + PQGParams.c \ + $(NULL) + + +LIBRARY_NAME = jsscrypto diff --git a/mozilla/security/jss/org/mozilla/jss/crypto/package.html b/mozilla/security/jss/org/mozilla/jss/crypto/package.html new file mode 100644 index 00000000000..fbf439f8fb7 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/crypto/package.html @@ -0,0 +1,37 @@ + + + +Generic cryptographic operations, such as signing and key pair generation. + + diff --git a/mozilla/security/jss/org/mozilla/jss/hclhacks/Makefile b/mozilla/security/jss/org/mozilla/jss/hclhacks/Makefile new file mode 100644 index 00000000000..9b72e07f79e --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/hclhacks/Makefile @@ -0,0 +1,76 @@ +#! gmake +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +####################################################################### +# (1) Include initial platform-independent assignments (MANDATORY). # +####################################################################### + +include manifest.mn + +####################################################################### +# (2) Include "global" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/config.mk + +####################################################################### +# (3) Include "component" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/$(MODULE)/config/config.mk + +####################################################################### +# (4) Include "local" platform-dependent assignments (OPTIONAL). # +####################################################################### + +include config.mk + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### + + + diff --git a/mozilla/security/jss/org/mozilla/jss/hclhacks/config.mk b/mozilla/security/jss/org/mozilla/jss/hclhacks/config.mk new file mode 100644 index 00000000000..21744eb5bf0 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/hclhacks/config.mk @@ -0,0 +1,66 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +####################################################################### +# Set the LD_LIBS value to encompass all static JSS, security, and # +# dbm libraries # +####################################################################### + +LD_LIBS += $(LIBSECMOD) \ + $(LIBPKCS12) \ + $(LIBPKCS7) \ + $(LIBHASH) \ + $(LIBCERT) \ + $(LIBKEY) \ + $(LIBCRYPTO) \ + $(LIBSECUTIL) \ + $(LIBDBM) \ + $(NULL) + +####################################################################### +# Append additional LD_LIBS value to encompass all dynamic NSPR 2.0, # +# java, and system libraries # +####################################################################### + +ifeq ($(OS_ARCH), WINNT) + LD_LIBS += $(DLLPLDS) $(DLLPLC) $(DLLPR) $(DLLSYSTEM) +else + LD_LIBS += -L$(SOURCE_LIB_DIR) -lplds3 -lplc3 -lnspr3 $(DLLSYSTEM) +endif + +####################################################################### +# Turn off any Export Control Policy for these libraries # +####################################################################### + +POLICY = + diff --git a/mozilla/security/jss/org/mozilla/jss/hclhacks/hclhacks.h b/mozilla/security/jss/org/mozilla/jss/hclhacks/hclhacks.h new file mode 100644 index 00000000000..1fe6f1cbd98 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/hclhacks/hclhacks.h @@ -0,0 +1,92 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +#ifndef HCLHACKS_H +#define HCLHACKS_H + +PR_BEGIN_EXTERN_C + +/************************************************************/ +/************************************************************/ +/*** The following should be added to lib/crypto/cryptot.h **/ +/************************************************************/ +/************************************************************/ + +typedef struct VFYContext2Str VFYContext2; + +/************************************************************/ +/************************************************************/ +/*** The following should be added to lib/crypto/crypto.h ***/ +/************************************************************/ +/************************************************************/ + + +/********************************************* +** Signature verification, where the signature to be verified is supplied +** at the end rather than at the beginning. +*/ + +/* +** Create a signature verification context, where the signature is +** given at the end of the operation. +** "key" the public key to verify with +** "algid" specifies the signing algorithm to use. This must match +** the key type. +*/ +extern VFYContext2 *VFY_CreateContext2(SECKEYPublicKey *key, SECOidTag algid); + +/* +** Destroy a verification-context object. +** "cx" the context to destroy +** "freeit" if PR_TRUE then free the object as well as its sub-objects +*/ +extern void VFY_DestroyContext2(VFYContext2 *cx, PRBool freeit); + +extern SECStatus VFY_Begin2(VFYContext2 *cx); + +extern SECStatus VFY_Update2(VFYContext2 *cx, unsigned char *input, + unsigned int inputLen); + +/* +** Finish the verification process. The return value is a status which +** indicates success or failure. On success, the SECSuccess value is +** returned. Otherwise, SECFailure is returned and the error code found +** using PORT_GetError() indicates what failure occurred. +** "cx" the context +** "sig" the signature to verify +** "wincx" the password argument +*/ +extern SECStatus VFY_End2(VFYContext2 *cx, SECItem *sig, void *wincx); + +PR_END_EXTERN_C + +#endif diff --git a/mozilla/security/jss/org/mozilla/jss/hclhacks/manifest.mn b/mozilla/security/jss/org/mozilla/jss/hclhacks/manifest.mn new file mode 100644 index 00000000000..c1639b20724 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/hclhacks/manifest.mn @@ -0,0 +1,49 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +CORE_DEPTH = ../../../../.. + +MODULE = ninja + +NS_USE_JDK = 1 + +REQUIRES = nspr20 dbm security + +PRIVATE_EXPORTS = hclhacks.h \ + $(NULL) + +CSRCS = \ + secvfy.c \ + $(NULL) + +LIBRARY_NAME = jsshclhacks diff --git a/mozilla/security/jss/org/mozilla/jss/hclhacks/secvfy.c b/mozilla/security/jss/org/mozilla/jss/hclhacks/secvfy.c new file mode 100644 index 00000000000..6e2f29aadae --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/hclhacks/secvfy.c @@ -0,0 +1,382 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +#include +#include "crypto.h" +#include "sechash.h" +#include "key.h" +#include "secasn1.h" +#include "secoid.h" +#include "pk11func.h" +#include "rsa.h" +#include "secerr.h" + +/* +** Decrypt signature block using public key (in place) +** XXX this is assuming that the signature algorithm has WITH_RSA_ENCRYPTION +*/ +static SECStatus +DecryptSigBlock(int *tagp, unsigned char *digest, SECKEYPublicKey *key, + SECItem *sig, char *wincx) +{ + SECItem it; + SGNDigestInfo *di = NULL; + unsigned char *dsig; + SECStatus rv; + SECOidTag tag; + unsigned char buf[MAX_RSA_MODULUS_LEN]; + + dsig = NULL; + it.data = buf; + it.len = sizeof(buf); + + if (key == NULL) goto loser; + + /* Decrypt signature block */ + dsig = (unsigned char*) PORT_Alloc(sig->len); + if (dsig == NULL) goto loser; + + /* decrypt the block */ + rv = PK11_VerifyRecover(key, sig, &it, wincx); + if (rv != SECSuccess) goto loser; + + di = SGN_DecodeDigestInfo(&it); + if (di == NULL) goto sigloser; + + /* + ** Finally we have the digest info; now we can extract the algorithm + ** ID and the signature block + */ + tag = SECOID_GetAlgorithmTag(&di->digestAlgorithm); + /* XXX Check that tag is an appropriate algorithm? */ + if (di->digest.len > 32) { + PORT_SetError(SEC_ERROR_OUTPUT_LEN); + goto loser; + } + PORT_Memcpy(digest, di->digest.data, di->digest.len); + *tagp = tag; + goto done; + + sigloser: + PORT_SetError(SEC_ERROR_BAD_SIGNATURE); + + loser: + rv = SECFailure; + + done: + if (di != NULL) SGN_DestroyDigestInfo(di); + if (dsig != NULL) PORT_Free(dsig); + + return rv; +} + +typedef enum { VFY_RSA, VFY_DSA} VerifyType; + +/************************************************************************/ +/************************************************************************/ +/* Above is from secvfy.c. Here's the new stuff: */ +/* Reverse-direction verification: get the signature at the end of the */ +/* digest instead of at the beginning. */ +/************************************************************************/ +/************************************************************************/ +#include "hclhacks.h" + +struct VFYContext2Str { + SECOidTag compositeAlg; + SECOidTag alg; /* hash alg */ + SECKEYPublicKey *key; + VerifyType type; + void *hashcx; + SECHashObject *hashobj; +}; + +/* + * Pulls the hash algorithm, signing algorithm, and key type out of a + * composite algorithm. + * + * alg: the composite algorithm to dissect. + * hashalg: address of a SECOidTag which will be set with the hash algorithm. + * signalg: address of a SECOidTag which will be set with the signing alg. + * keyType: address of a KeyType which will be set with the key type. + * Returns: SECSuccess if the algorithm was acceptable, SECFailure if the + * algorithm was not found or was not a signing algorithm. + */ +static SECStatus +dissectSigAlg(SECOidTag alg, SECOidTag *hashalg, SECOidTag *signalg, + KeyType *keyType) +{ + PR_ASSERT(hashalg!=NULL && signalg!=NULL && keyType!=NULL); + + switch (alg) { + /* We probably shouldn't be generating MD2 signatures either */ + case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION: + *hashalg = SEC_OID_MD2; + *signalg = SEC_OID_PKCS1_RSA_ENCRYPTION; + *keyType = rsaKey; + return SECSuccess; + case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION: + *hashalg = SEC_OID_MD5; + *signalg = SEC_OID_PKCS1_RSA_ENCRYPTION; + *keyType = rsaKey; + return SECSuccess; + case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION: + case SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE: + *hashalg = SEC_OID_SHA1; + *signalg = SEC_OID_PKCS1_RSA_ENCRYPTION; + *keyType = rsaKey; + return SECSuccess; + /* what about normal DSA? */ + case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST: + case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST: + *hashalg = SEC_OID_SHA1; + *signalg = SEC_OID_ANSIX9_DSA_SIGNATURE; + *keyType = dsaKey; + return SECSuccess; + case SEC_OID_MISSI_DSS: + case SEC_OID_MISSI_KEA_DSS: + case SEC_OID_MISSI_KEA_DSS_OLD: + case SEC_OID_MISSI_DSS_OLD: + *hashalg = SEC_OID_SHA1; + *signalg = SEC_OID_MISSI_DSS; /* XXX Is there a better algid? */ + *keyType = fortezzaKey; + return SECSuccess; + /* we don't implement MD4 hashes */ + case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION: + default: + return SECFailure; + } + PR_ASSERT(PR_FALSE); /* shouldn't get here */ +} + +/* + * algid: The composite signature algorithm, for example + * SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION. + * Returns: a new VFYContext2, or NULL if an error occurred. + */ +VFYContext2 * +VFY_CreateContext2(SECKEYPublicKey *key, SECOidTag algid) +{ + VFYContext2 *cx=NULL; + SECOidTag hashAlg; + SECOidTag sigAlg; + KeyType keyType; + + PR_ASSERT(key!=NULL); + + /* + * validate key type and hash algorithm + */ + if( dissectSigAlg(algid, &hashAlg, &sigAlg, &keyType) != SECSuccess) { + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); + goto loser; + } + if( keyType != key->keyType ) { + /* key type of algorithm is not the type of the key that + * was passed in */ + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); + goto loser; + } + switch(hashAlg) { + case SEC_OID_MD2: + case SEC_OID_MD5: + case SEC_OID_SHA1: + break; + default: + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); + goto loser; + } + + /* + * Create the context + */ + cx = (VFYContext2*) PORT_ZAlloc(sizeof(VFYContext2)); + if (cx == NULL) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + cx->compositeAlg = algid; + cx->alg = hashAlg; + switch(keyType) { + case rsaKey: + cx->type = VFY_RSA; + break; + case dsaKey: + case fortezzaKey: + cx->type = VFY_DSA; + break; + default: + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); + goto loser; + } + cx->key = SECKEY_CopyPublicKey(key); + PR_ASSERT(cx->hashcx == NULL); + PR_ASSERT(cx->hashobj == NULL); + + return cx; + + loser: + if(cx) { + VFY_DestroyContext2(cx, PR_TRUE); + } + return NULL; +} + +void +VFY_DestroyContext2(VFYContext2 *cx, PRBool freeit) +{ + if (cx) { + if (cx->hashcx != NULL) { + (*cx->hashobj->destroy)(cx->hashcx, PR_TRUE); + cx->hashcx = NULL; + } + if (cx->key) { + SECKEY_DestroyPublicKey(cx->key); + } + if (freeit) { + PORT_ZFree(cx, sizeof(VFYContext2)); + } + } +} + +SECStatus +VFY_Begin2(VFYContext2 *cx) +{ + if (cx->hashcx != NULL) { + (*cx->hashobj->destroy)(cx->hashcx, PR_TRUE); + cx->hashcx = NULL; + } + + switch (cx->alg) { + case SEC_OID_MD2: + cx->hashobj = &SECHashObjects[HASH_AlgMD2]; + break; + case SEC_OID_MD5: + cx->hashobj = &SECHashObjects[HASH_AlgMD5]; + break; + case SEC_OID_SHA1: + cx->hashobj = &SECHashObjects[HASH_AlgSHA1]; + break; + default: + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); + return SECFailure; + } + + cx->hashcx = (*cx->hashobj->create)(); + if (cx->hashcx == NULL) + return SECFailure; + + (*cx->hashobj->begin)(cx->hashcx); + return SECSuccess; +} + +SECStatus +VFY_Update2(VFYContext2 *cx, unsigned char *input, unsigned inputLen) +{ + if (cx->hashcx == NULL) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + (*cx->hashobj->update)(cx->hashcx, input, inputLen); + return SECSuccess; +} + + +SECStatus +VFY_End2(VFYContext2 *cx, SECItem *sig, void *wincx) +{ + unsigned char final[32]; + unsigned part; + int hashAlg; + SECItem hash, mysig; + SECItem *dsasig = NULL; + unsigned char digest[DSA_SIGNATURE_LEN]; + SECStatus status = SECFailure; + + if (cx->hashcx == NULL) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + goto finish; + } + (*cx->hashobj->end)(cx->hashcx, final, &part, sizeof(final)); + switch (cx->type) { + case VFY_DSA: + /* if this is a DER encoded signature, decode it first */ + if ((cx->compositeAlg==SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) || + (cx->compositeAlg==SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST) || + (cx->compositeAlg==SEC_OID_ANSIX9_DSA_SIGNATURE)) { + dsasig = DSAU_DecodeDerSig(sig); + if ((dsasig == NULL) || (dsasig->len != DSA_SIGNATURE_LEN)) { + PORT_SetError(SEC_ERROR_BAD_SIGNATURE); + goto finish; + } + PORT_Memcpy(&digest[0], dsasig->data, dsasig->len); + } else { + if (sig->len != DSA_SIGNATURE_LEN) { + PORT_SetError(SEC_ERROR_BAD_SIGNATURE); + goto finish; + } + PORT_Memcpy(&digest[0], sig->data, sig->len); + } + mysig.data = digest; + mysig.len = DSA_SIGNATURE_LEN; /* magic size of dsa signature */ + hash.data = final; + hash.len = part; + if (PK11_Verify(cx->key,&mysig,&hash,wincx) != SECSuccess) { + PORT_SetError(SEC_ERROR_BAD_SIGNATURE); + goto finish; + } + break; + case VFY_RSA: + if( DecryptSigBlock(&hashAlg, &digest[0], cx->key, sig, wincx) + != SECSuccess) + { + PORT_SetError(SEC_ERROR_BAD_SIGNATURE); + goto finish; + } + if (PORT_Memcmp(final, digest, part)) { + PORT_SetError(SEC_ERROR_BAD_SIGNATURE); + goto finish; + } + break; + default: + PR_ASSERT(PR_FALSE); /* shouldn't happen */ + PORT_SetError(SEC_ERROR_BAD_SIGNATURE); + goto finish; + } + status = SECSuccess; + +finish: + if (dsasig != NULL) { + SECITEM_FreeItem(dsasig, PR_TRUE); + } + return status; +} diff --git a/mozilla/security/jss/org/mozilla/jss/manage/CRLImportException.java b/mozilla/security/jss/org/mozilla/jss/manage/CRLImportException.java new file mode 100644 index 00000000000..c1b141ee383 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/manage/CRLImportException.java @@ -0,0 +1,43 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss; + +/** + * Thrown if a CRL cannot be imported + */ +public class CRLImportException extends java.lang.Exception { + public CRLImportException() {} + public CRLImportException(String mesg) { + super(mesg); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/manage/CertDatabaseException.java b/mozilla/security/jss/org/mozilla/jss/manage/CertDatabaseException.java new file mode 100644 index 00000000000..00b2d61fbf7 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/manage/CertDatabaseException.java @@ -0,0 +1,44 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss; + +/** + * This exception is thrown if the certificate database does not exist, + * or if an error occurs while opening it. + */ +public class CertDatabaseException extends java.lang.Exception { + public CertDatabaseException() {} + public CertDatabaseException(String mesg) { + super(mesg); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/manage/CryptoManager.c b/mozilla/security/jss/org/mozilla/jss/manage/CryptoManager.c new file mode 100644 index 00000000000..9b0eb8e6b0c --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/manage/CryptoManager.c @@ -0,0 +1,1154 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +#include "_jni/com_netscape_jss_CryptoManager.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "jssinit.h" +#include "pk11util.h" +#include "Policy.h" + +#if defined(AIX) || defined(HPUX) || defined(LINUX) +#include +#endif + +/* +** NOTE: We must declare a function "prototype" for the following function +** since it is defined in the "private" NSPR 2.0 header files, +** specifically "ns/nspr20/pr/include/private/pprthred.h". +** +** Get this thread's affinity mask. The affinity mask is a 32 bit quantity +** marking a bit for each processor this process is allowed to run on. +** The processor mask is returned in the mask argument. +** The least-significant-bit represents processor 0. +** +** Returns 0 on success, -1 on failure. +*/ +PR_EXTERN(PRInt32) +PR_GetThreadAffinityMask(PRThread *thread, PRUint32 *mask); + +static jobject +makePWCBInfo(JNIEnv *env, PK11SlotInfo *slot); + +static char* +getPWFromCallback(PK11SlotInfo *slot, PRBool retry, void *arg); + +static jint +getPolicyTypeIndex( SVRPLCYPolicyType thisPolicy ); + +/*********************************************************************** +** +** Policy Type indices. This must be kept in sync with the policy +** type indices in the CryptoManager class. +**/ + +#define NUM_POLICIES 4 + +SVRPLCYPolicyType JSS_PolicyTable[NUM_POLICIES] = { +/* 0 */ { SVRPLCYNull }, +/* 1 */ { SVRPLCYDomestic }, +/* 2 */ { SVRPLCYExport }, +/* 3 */ { SVRPLCYFrance } + +/* REMEMBER TO UPDATE NUM_POLICIES!!! */ +}; + +/************************************************************* + * AIX, HP, and Linux signal handling madness + * + * In order for the JVM, kernel, and NSPR to work together, we setup + * a signal handler for SIGCHLD that does nothing. This is only done + * on AIX, HP, and Linux. + *************************************************************/ +#if defined(AIX) || defined(HPUX) || defined(LINUX) + +static PRStatus +handleSigChild(JNIEnv *env) { + + struct sigaction action; + sigset_t signalset; + int result; + + sigemptyset(&signalset); + + action.sa_handler = SIG_DFL; + action.sa_mask = signalset; + action.sa_flags = 0; + + result = sigaction( SIGCHLD, &action, NULL ); + + if( result != 0 ) { + JSS_throwMsg(env, GENERAL_SECURITY_EXCEPTION, + "Failed to set SIGCHLD handler"); + return PR_FAILURE; + } + + return PR_SUCCESS; +} + +#endif + + +int ConfigureOSCP( + JNIEnv *env, + CERTCertDBHandle *db, + jboolean ocspCheckingEnabled, + jstring ocspResponderURL, + jstring ocspResponderCertNickname ) +{ + char *ocspResponderURL_string=NULL; + char *ocspResponderCertNickname_string=NULL; + SECStatus status; + int result = SECSuccess; + + + /* if caller specified default responder, get the + * strings associated with these args + */ + + if (ocspResponderURL) { + ocspResponderURL_string = + (char*) (*env)->GetStringUTFChars(env, ocspResponderURL, NULL); + if (ocspResponderURL_string == NULL) { + JSS_throwMsg(env, GENERAL_SECURITY_EXCEPTION, + "OCSP invalid URL"); + result = SECFailure; + goto loser; + } + } + + if (ocspResponderCertNickname) { + ocspResponderCertNickname_string = + (char*) (*env)->GetStringUTFChars(env, ocspResponderCertNickname, NULL); + if (ocspResponderCertNickname_string == NULL) { + JSS_throwMsg(env, GENERAL_SECURITY_EXCEPTION, + "OCSP invalid nickname"); + result = SECFailure; + goto loser; + } + } + + /* first disable OCSP - we'll enable it later */ + + CERT_DisableOCSPChecking(db); + + /* if they set the default responder, then set it up + * and enable it + */ + if (ocspResponderURL) { + status = + CERT_SetOCSPDefaultResponder( db, + ocspResponderURL_string, + ocspResponderCertNickname_string + ); + if (status == SECFailure) { + /* deal with error */ + JSS_throwMsg(env, GENERAL_SECURITY_EXCEPTION, + "OCSP Could not set responder"); + result = SECFailure; + goto loser; + } + CERT_EnableOCSPDefaultResponder(db); + } + else { + /* if no defaultresponder is set, disable it */ + CERT_DisableOCSPDefaultResponder(db); + } + + + /* enable OCSP checking if requested */ + + if (ocspCheckingEnabled) { + CERT_EnableOCSPChecking(db); + } + +loser: + + if (ocspResponderURL_string) { + (*env)->ReleaseStringUTFChars(env, + ocspResponderURL, ocspResponderURL_string); + } + + if (ocspResponderCertNickname_string) { + (*env)->ReleaseStringUTFChars(env, + ocspResponderCertNickname, ocspResponderCertNickname_string); + } + + return result; + +} + +/*********************************************************************** + * simpleInitialize + * + * Initializes NSPR and the RNG only. + * + * RETURNS + * PR_SUCCESS for success, PR_FAILURE otherwise. If not successful, + * an exception will be thrown. + */ +static PRStatus +simpleInitialize(JNIEnv *env) +{ + /* initialize is synchronized, so this is thread-safe */ + static PRBool initialized = PR_FALSE; + + /* initialize values used to calculate concurrency */ + PRUint32 mask = 0; + PRUint32 template = 0x00000001; + PRUintn cpus = 0; + PRUintn concurrency = 0; + + if(initialized) { + return PR_SUCCESS; + } + + /* On AIX, HP, and Linux, we need to do nasty signal handling in order + * to have NSPR play nice with the JVM and kernel. + */ +#if defined(AIX) || defined(HPUX) || defined(LINUX) + if( handleSigChild(env) != PR_SUCCESS ) { + return PR_FAILURE; + } +#endif + + /* NOTE: Removed PR_Init() function since NSPR now self-initializes. */ + /* PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 0); */ + + /* Obtain the mask containing the number of CPUs */ + if( PR_GetThreadAffinityMask( PR_GetCurrentThread(), &mask ) ) { + JSS_throwMsg( env, SECURITY_EXCEPTION, + "Failed to calculate number of CPUs" ); + return PR_FAILURE; + } + + /* Count the bits to calculate the number of CPUs in the machine */ + while( mask != 0 ) { + cpus += ( mask & template ); + mask >>= 1; + } + + /* Specify the concurrency */ +#if defined(WIN32) && !defined(WIN95) /* WINNT (fiberous) */ + /* Always specify at least a concurrency of 2 for (fiberous) Windows NT */ + if( cpus <= 1 ) { + concurrency = 2; + } else { + concurrency = cpus; + } +#else + if( cpus <= 1 ) { + concurrency = 1; + } else { + concurrency = cpus; + } +#endif + + /* Set the concurrency */ + PR_SetConcurrency( concurrency ); + + RNG_RNGInit(); + + /* establish a Utility policy */ + if( SVRPLCY_InstallUtilityPolicy() != PR_SUCCESS ) { + JSS_throwMsg(env, SECURITY_EXCEPTION, + "Failed to install utility policy"); + return PR_FAILURE; + } + + /* establish an SSL policy */ + SVRPLCY_InstallSSLPolicy(); + + /* establish a JSS policy */ + if( SVRPLCY_InstallJSSPolicy() != PR_SUCCESS ) { + JSS_throwMsg(env, SECURITY_EXCEPTION, + "Failed to install JSS policy"); + return PR_FAILURE; + } + + /* establish JSS max key sizes */ + if( JSS_InstallMaxKeySizesAllowed() != PR_SUCCESS ) { + JSS_throwMsg(env, SECURITY_EXCEPTION, + "Failed to install max JSS key sizes"); + return PR_FAILURE; + } + + initialized = PR_TRUE; + + return PR_SUCCESS; +} + +/* + * CryptoManager.initialize + * + * Initializes NSPR and the RNG only. + */ +JNIEXPORT void JNICALL +Java_com_netscape_jss_CryptoManager_initializeNative + (JNIEnv *env, jclass clazz) +{ + if(simpleInitialize(env) != PR_SUCCESS ) { + PR_ASSERT( (*env)->ExceptionOccurred(env) ); + return; + } +} + +/* + * Callback for key database name. Name is passed in through void* argument. + */ +static char* +keyDBNameCallback(void *arg, int dbVersion) +{ + PR_ASSERT(arg!=NULL); + if(dbVersion==3) { + return PL_strdup((char*)arg); + } else { + return PL_strdup(""); + } +} + +static char* +certDBNameCallback(void *arg, int dbVersion) +{ + PR_ASSERT(arg!=NULL); + if(dbVersion == 7) { + return PL_strdup((char*)arg); + } else { + return PL_strdup(""); + } +} + +/********************************************************************** + * This is the PasswordCallback object that will be used to login + * to tokens implicitly. + */ +static jobject globalPasswordCallback = NULL; + +/********************************************************************** + * The Java virtual machine can be used to retrieve the JNI environment + * pointer from callback functions. + */ +static JavaVM *javaVM = NULL; + +/*********************************************************************** + * CryptoManager.initialize + * + * Initialize the security library and open all the databases. + * + */ +JNIEXPORT void JNICALL +Java_com_netscape_jss_CryptoManager_initializeAllNative + (JNIEnv *env, jclass clazz, + jstring modDBName, + jstring keyDBName, + jstring certDBName, + jboolean readOnly, + jstring manuString, + jstring libraryString, + jstring tokString, + jstring keyTokString, + jstring slotString, + jstring keySlotString, + jstring fipsString, + jstring fipsKeyString, + jboolean ocspCheckingEnabled, + jstring ocspResponderURL, + jstring ocspResponderCertNickname ) +{ + JSS_completeInitialize(env, + modDBName, + keyDBName, + certDBName, + readOnly, + manuString, + libraryString, + tokString, + keyTokString, + slotString, + keySlotString, + fipsString, + fipsKeyString, + ocspCheckingEnabled, + ocspResponderURL, + ocspResponderCertNickname + ); +} + +/*********************************************************************** + * JSS_completeInitialize + * + * Initialize the security library and open all the databases. + * + */ +PR_IMPLEMENT( void ) +JSS_completeInitialize(JNIEnv *env, + jstring modDBName, + jstring keyDBName, + jstring certDBName, + jboolean readOnly, + jstring manuString, + jstring libraryString, + jstring tokString, + jstring keyTokString, + jstring slotString, + jstring keySlotString, + jstring fipsString, + jstring fipsKeyString, + jboolean ocspCheckingEnabled, + jstring ocspResponderURL, + jstring ocspResponderCertNickname ) +{ + CERTCertDBHandle *cdb_handle=NULL; + SECKEYKeyDBHandle *kdb_handle=NULL; + SECStatus rv = SECFailure; + PRStatus status = PR_FAILURE; + JavaVM *VMs[5]; + jint numVMs; + char *szDBName = NULL; /* C string version of a database filename */ + char *manuChars=NULL; + char *libraryChars=NULL; + char *tokChars=NULL; + char *keyTokChars=NULL; + char *slotChars=NULL; + char *keySlotChars=NULL; + char *fipsChars=NULL; + char *fipsKeyChars=NULL; + + /* This is thread-safe because initialize is synchronized */ + static PRBool initialized=PR_FALSE; + + /* + * Initialize NSPR and the RNG + */ + if( simpleInitialize(env) != PR_SUCCESS ) { + PR_ASSERT((*env)->ExceptionOccurred(env)); + return; + } + + + PR_ASSERT(env!=NULL && modDBName!=NULL && certDBName!=NULL + && keyDBName!=NULL); + + /* Make sure initialize() completes only once */ + if(initialized) { + JSS_throw(env, ALREADY_INITIALIZED_EXCEPTION); + return; + } + + /* + * Initialize the private key database. + */ + szDBName = (char*) (*env)->GetStringUTFChars(env, keyDBName, NULL); + PR_ASSERT(szDBName != NULL); + /* Bug #299899: OpenKeyDBFilename is broken. */ + kdb_handle = SECKEY_OpenKeyDB( readOnly, + keyDBNameCallback, + (void*) szDBName); + (*env)->ReleaseStringUTFChars(env, keyDBName, szDBName); + if (kdb_handle != NULL) { + SECKEY_SetDefaultKeyDB(kdb_handle); + } else { + char *err; + PR_smprintf(err, "Unable to open key database %s", szDBName); + JSS_nativeThrowMsg(env, KEY_DATABASE_EXCEPTION, err); + PR_smprintf_free(err); + goto finish; + } + + /* + * Initialize the certificate database. + */ + cdb_handle = PR_NEWZAP(CERTCertDBHandle); + if(cdb_handle == NULL) { + JSS_nativeThrowMsg(env, + OUT_OF_MEMORY_ERROR, + "creating certificate database handle"); + goto finish; + } + + szDBName = (char*) (*env)->GetStringUTFChars(env, certDBName, NULL); + PR_ASSERT(szDBName != NULL); + /* Bug #299899: OpenCertDBFilename is broken. */ + rv = CERT_OpenCertDB(cdb_handle, readOnly, + certDBNameCallback, szDBName); + (*env)->ReleaseStringUTFChars(env, certDBName, szDBName); + + if (rv == SECSuccess) { + CERT_SetDefaultCertDB(cdb_handle); + } else { + char *err; + PR_smprintf(err, "Unable to open certificate database %s", szDBName); + JSS_nativeThrowMsg(env, CERT_DATABASE_EXCEPTION, err); + PR_smprintf_free(err); + goto finish; + } + + /* + * Set the PKCS #11 strings + */ + manuChars = (char*) (*env)->GetStringUTFChars(env, manuString, NULL); + libraryChars = (char*) (*env)->GetStringUTFChars(env, libraryString, NULL); + tokChars = (char*) (*env)->GetStringUTFChars(env, tokString, NULL); + keyTokChars = (char*) (*env)->GetStringUTFChars(env, keyTokString, NULL); + slotChars = (char*) (*env)->GetStringUTFChars(env, slotString, NULL); + keySlotChars = (char*) (*env)->GetStringUTFChars(env, keySlotString, NULL); + fipsChars = (char*) (*env)->GetStringUTFChars(env, fipsString, NULL); + fipsKeyChars = (char*) (*env)->GetStringUTFChars(env, fipsKeyString, NULL); + if( (*env)->ExceptionOccurred(env) ) { + ASSERT_OUTOFMEM(env); + goto finish; + } + PR_ASSERT( strlen(manuChars) == 33 ); + PR_ASSERT( strlen(libraryChars) == 33 ); + PR_ASSERT( strlen(tokChars) == 33 ); + PR_ASSERT( strlen(keyTokChars) == 33 ); + PR_ASSERT( strlen(slotChars) == 65 ); + PR_ASSERT( strlen(keySlotChars) == 65 ); + PR_ASSERT( strlen(fipsChars) == 65 ); + PR_ASSERT( strlen(fipsKeyChars) == 65 ); + PK11_ConfigurePKCS11( PL_strdup(manuChars), + PL_strdup(libraryChars), + PL_strdup(tokChars), + PL_strdup(keyTokChars), + PL_strdup(slotChars), + PL_strdup(keySlotChars), + PL_strdup(fipsChars), + PL_strdup(fipsKeyChars), + 0, /* minimum pin length */ + PR_FALSE /* password required */ + ); + + /* + * Open the PKCS #11 Module database + */ + szDBName = (char *) (*env)->GetStringUTFChars(env, modDBName, NULL); + PR_ASSERT(szDBName != NULL); + SECMOD_init(szDBName); + /* !!! SECMOD_init doesn't return an error code: Bug #262562 */ + (*env)->ReleaseStringUTFChars(env, modDBName, szDBName); + + /* + * Set default password callback. This is the only place this + * should ever be called if you are using Ninja. + */ + PK11_SetPasswordFunc(getPWFromCallback); + + /* + * Setup NSS to call the specified OCSP responder + */ + rv = ConfigureOSCP( + env, + cdb_handle, + ocspCheckingEnabled, + ocspResponderURL, + ocspResponderCertNickname ); + + if (rv != SECSuccess) { + goto finish; + } + + + /* + * Save the JavaVM pointer so we can retrieve the JNI environment + * later. This only works if there is only one Java VM. + */ + if( JNI_GetCreatedJavaVMs(VMs, 5, &numVMs) != 0) { + JSS_trace(env, JSS_TRACE_ERROR, + "Unable to to access Java virtual machine"); + PR_ASSERT(PR_FALSE); + goto finish; + } + if(numVMs != 1) { + char *str; + PR_smprintf(str, "Invalid number of Java VMs: %d", numVMs); + JSS_trace(env, JSS_TRACE_ERROR, str); + PR_smprintf_free(str); + PR_ASSERT(PR_FALSE); + } + javaVM = VMs[0]; + + initialized = PR_TRUE; + + status = PR_SUCCESS; + +finish: + if(status == PR_FAILURE) { + if(cdb_handle) { + if(CERT_GetDefaultCertDB() == cdb_handle) { + CERT_SetDefaultCertDB(NULL); + } + CERT_ClosePermCertDB(cdb_handle); + PR_Free(cdb_handle); + } + if(kdb_handle) { + if(SECKEY_GetDefaultKeyDB() == kdb_handle) { + SECKEY_SetDefaultKeyDB(NULL); + } + SECKEY_CloseKeyDB(kdb_handle); + /* CloseKeyDB also frees the handle */ + } + } + + /* LET'S BE CAREFUL. Unbraced if statements ahead. */ + if(manuChars) + (*env)->ReleaseStringUTFChars(env, manuString, manuChars); + if(libraryChars) + (*env)->ReleaseStringUTFChars(env, libraryString, libraryChars); + if(tokChars) + (*env)->ReleaseStringUTFChars(env, tokString, tokChars); + if(keyTokChars) + (*env)->ReleaseStringUTFChars(env, keyTokString, keyTokChars); + if(slotChars) + (*env)->ReleaseStringUTFChars(env, slotString, slotChars); + if(keySlotChars) + (*env)->ReleaseStringUTFChars(env, keySlotString, keySlotChars); + if(fipsChars) + (*env)->ReleaseStringUTFChars(env, fipsString, fipsChars); + if(fipsKeyChars) + (*env)->ReleaseStringUTFChars(env, fipsKeyString, fipsKeyChars); + + return; +} + + + + + +/********************************************************************** + * + * CryptoManager.setNativePasswordCallback + * + * Sets the global PasswordCallback object, which will be used to + * login to tokens implicitly if necessary. + * + */ +JNIEXPORT void JNICALL +Java_com_netscape_jss_CryptoManager_setNativePasswordCallback + (JNIEnv *env, jclass clazz, jobject callback) +{ + JSS_setPasswordCallback(env, callback); +} + +/********************************************************************** + * + * JSS_setPasswordCallback + * + * Sets the global PasswordCallback object, which will be used to + * login to tokens implicitly if necessary. + * + */ +PR_IMPLEMENT( void ) +JSS_setPasswordCallback(JNIEnv *env, jobject callback) +{ + PR_ASSERT(env!=NULL && callback!=NULL); + + /* Free the previously-registered password callback */ + if( globalPasswordCallback != NULL ) { + (*env)->DeleteGlobalRef(env, globalPasswordCallback); + globalPasswordCallback = NULL; + } + + /* Store the new password callback */ + globalPasswordCallback = (*env)->NewGlobalRef(env, callback); + if(globalPasswordCallback == NULL) { + JSS_throw(env, OUT_OF_MEMORY_ERROR); + } +} + +/******************************************************************** + * + * g e t P W F r o m C a l l b a c k + * + * Extracts a password from a password callback and returns + * it to PKCS #11. + * + * INPUTS + * slot + * The PK11SlotInfo* for the slot we are logging into. + * retry + * PR_TRUE if this is the first time we are trying to login, + * PR_FALSE if we tried before and our password was wrong. + * arg + * This can contain a Java PasswordCallback object reference, + * or NULL to use the default password callback. + * RETURNS + * The password as extracted from the callback, or NULL if the + * callback gives up. + */ +static char* +getPWFromCallback(PK11SlotInfo *slot, PRBool retry, void *arg) +{ + jobject pwcbInfo; + jobject pwObject; + jbyteArray pwArray=NULL; + char* pwchars; + char* returnchars=NULL; + jclass callbackClass; + jclass passwordClass; + jmethodID getPWMethod; + jmethodID getByteCopyMethod; + jmethodID clearMethod; + jthrowable exception; + jobject callback; + JNIEnv *env; + + PR_ASSERT(slot!=NULL); + if(slot==NULL) { + return NULL; + } + + /* Get the callback from the arg, or use the default */ + PR_ASSERT(sizeof(void*) == sizeof(jobject)); + callback = (jobject)arg; + if(callback == NULL) { + callback = globalPasswordCallback; + if(callback == NULL) { + /* No global password callback set, no way to get a password */ + return NULL; + } + } + + /* Get the JNI environment */ + if( (*javaVM)->AttachCurrentThread(javaVM, &env, NULL) != 0) { + PR_ASSERT(PR_FALSE); + goto finish; + } + PR_ASSERT(env != NULL); + + /***************************************** + * Construct the JSS_PasswordCallbackInfo + *****************************************/ + pwcbInfo = makePWCBInfo(env, slot); + if(pwcbInfo==NULL) { + goto finish; + } + + /***************************************** + * Get the callback class and methods + *****************************************/ + callbackClass = (*env)->GetObjectClass(env, callback); + if(callbackClass == NULL) { + JSS_trace(env, JSS_TRACE_ERROR, "Failed to find password " + "callback class"); + PR_ASSERT(PR_FALSE); + } + if(retry) { + getPWMethod = (*env)->GetMethodID( + env, + callbackClass, + PW_CALLBACK_GET_PW_AGAIN_NAME, + PW_CALLBACK_GET_PW_AGAIN_SIG); + } else { + getPWMethod = (*env)->GetMethodID( + env, + callbackClass, + PW_CALLBACK_GET_PW_FIRST_NAME, + PW_CALLBACK_GET_PW_FIRST_SIG); + } + if(getPWMethod == NULL) { + JSS_trace(env, JSS_TRACE_ERROR, + "Failed to find password callback accessor method"); + ASSERT_OUTOFMEM(env); + goto finish; + } + + /***************************************** + * Get the password from the callback + *****************************************/ + pwObject = (*env)->CallObjectMethod( + env, + callback, + getPWMethod, + pwcbInfo); + if( (*env)->ExceptionOccurred(env) != NULL) { + goto finish; + } + if( pwObject == NULL ) { + JSS_throw(env, GIVE_UP_EXCEPTION); + goto finish; + } + + /***************************************** + * Get Password class and methods + *****************************************/ + passwordClass = (*env)->GetObjectClass(env, pwObject); + if(passwordClass == NULL) { + JSS_trace(env, JSS_TRACE_ERROR, "Failed to find Password class"); + ASSERT_OUTOFMEM(env); + goto finish; + } + getByteCopyMethod = (*env)->GetMethodID( + env, + passwordClass, + PW_GET_BYTE_COPY_NAME, + PW_GET_BYTE_COPY_SIG); + clearMethod = (*env)->GetMethodID( env, + passwordClass, + PW_CLEAR_NAME, + PW_CLEAR_SIG); + if(getByteCopyMethod==NULL || clearMethod==NULL) { + JSS_trace(env, JSS_TRACE_ERROR, + "Failed to find Password manipulation methods from native " + "implementation"); + ASSERT_OUTOFMEM(env); + goto finish; + } + + /************************************************ + * Get the bytes from the password, then clear it + ***********************************************/ + pwArray = (*env)->CallObjectMethod( env, pwObject, getByteCopyMethod); + (*env)->CallVoidMethod(env, pwObject, clearMethod); + + exception = (*env)->ExceptionOccurred(env); + if(exception == NULL) { + PR_ASSERT(pwArray != NULL); + + /************************************************************* + * Copy the characters out of the byte array, + * then erase it + *************************************************************/ + pwchars = (char*) (*env)->GetByteArrayElements(env, pwArray, NULL); + PR_ASSERT(pwchars!=NULL); + + returnchars = PL_strdup(pwchars); + JSS_wipeCharArray(pwchars); + (*env)->ReleaseByteArrayElements(env, pwArray, (jbyte*)pwchars, 0); + } else { + returnchars = NULL; + } + +finish: + if( (exception=(*env)->ExceptionOccurred(env)) != NULL) { +#ifdef DEBUG + jclass giveupClass; + jmethodID printStackTrace; + jclass excepClass; +#endif + (*env)->ExceptionClear(env); +#ifdef DEBUG + giveupClass = (*env)->FindClass(env, GIVE_UP_EXCEPTION); + PR_ASSERT(giveupClass != NULL); + if( ! (*env)->IsInstanceOf(env, exception, giveupClass) ) { + excepClass = (*env)->GetObjectClass(env, exception); + printStackTrace = (*env)->GetMethodID(env, excepClass, + "printStackTrace", "()V"); + (*env)->CallVoidMethod(env, exception, printStackTrace); + PR_ASSERT( PR_FALSE ); + } + PR_ASSERT(returnchars==NULL); +#endif + } + return returnchars; +} + +/********************************************************************** + * + * m a k e P W C B I n f o + * + * Creates a Java PasswordCallbackInfo structure from a PKCS #11 token. + * Returns this object, or NULL if an exception was thrown. + */ +static jobject +makePWCBInfo(JNIEnv *env, PK11SlotInfo *slot) +{ + jclass infoClass; + jmethodID constructor; + jstring name; + jobject pwcbInfo=NULL; + + PR_ASSERT(env!=NULL && slot!=NULL); + + /***************************************** + * Turn the token name into a Java String + *****************************************/ + name = (*env)->NewStringUTF(env, PK11_GetTokenName(slot)); + if(name == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + /***************************************** + * Look up the class and constructor + *****************************************/ + infoClass = (*env)->FindClass(env, TOKEN_CBINFO_CLASS_NAME); + if(infoClass == NULL) { + JSS_trace(env, JSS_TRACE_ERROR, "Unable to find TokenCallbackInfo " + "class"); + ASSERT_OUTOFMEM(env); + goto finish; + } + constructor = (*env)->GetMethodID( env, + infoClass, + TOKEN_CBINFO_CONSTRUCTOR_NAME, + TOKEN_CBINFO_CONSTRUCTOR_SIG); + if(constructor == NULL) { + JSS_trace(env, JSS_TRACE_ERROR, "Unable to find " + "TokenCallbackInfo constructor"); + ASSERT_OUTOFMEM(env); + goto finish; + } + + /***************************************** + * Create the CallbackInfo object + *****************************************/ + pwcbInfo = (*env)->NewObject(env, infoClass, constructor, name); + if(pwcbInfo == NULL) { + JSS_trace(env, JSS_TRACE_ERROR, "Unable to create TokenCallbackInfo"); + ASSERT_OUTOFMEM(env); + } + +finish: + return pwcbInfo; +} + +/********************************************************************** + * CryptoManager.putModulesInVector + * + * Wraps all PKCS #11 modules in PK11Module Java objects, then puts + * these into a Vector. + */ +JNIEXPORT void JNICALL +Java_com_netscape_jss_CryptoManager_putModulesInVector + (JNIEnv *env, jobject this, jobject vector) +{ + SECMODListLock *listLock=NULL; + SECMODModuleList *list; + SECMODModule *modp=NULL; + jclass vectorClass; + jmethodID addElement; + jobject module; + + PR_ASSERT(env!=NULL && this!=NULL && vector!=NULL); + + /*************************************************** + * Get JNI ids + ***************************************************/ + vectorClass = (*env)->GetObjectClass(env, vector); + if(vectorClass == NULL) goto finish; + + addElement = (*env)->GetMethodID(env, + vectorClass, + VECTOR_ADD_ELEMENT_NAME, + VECTOR_ADD_ELEMENT_SIG); + if(addElement==NULL) goto finish; + + /*************************************************** + * Lock the list + ***************************************************/ + listLock = SECMOD_GetDefaultModuleListLock(); + PR_ASSERT(listLock!=NULL); + + SECMOD_GetReadLock(listLock); + + /*************************************************** + * Loop over the modules, adding each one to the vector + ***************************************************/ + for( list = SECMOD_GetDefaultModuleList(); list != NULL; list=list->next) { + PR_ASSERT(list->module != NULL); + + /** Make a PK11Module **/ + modp = SECMOD_ReferenceModule(list->module); + module = JSS_PK11_wrapPK11Module(env, &modp); + PR_ASSERT(modp==NULL); + if(module == NULL) { + goto finish; + } + + /** Stick the PK11Module in the Vector **/ + (*env)->CallVoidMethod(env, vector, addElement, module); + } + +finish: + /*** Unlock the list ***/ + if(listLock != NULL) { + SECMOD_ReleaseReadLock(listLock); + } + /*** Free this module if it wasn't properly Java-ized ***/ + if(modp!=NULL) { + SECMOD_DestroyModule(modp); + } + + return; +} + + +/********************************************************************** + * CryptoManager.enableFIPS + * + * Enables or disables FIPS mode. + * INPUTS + * fips + * true means turn on FIPS mode, false means turn it off. + * RETURNS + * true if a switch happened, false if the library was already + * in the requested mode. + * THROWS + * java.security.GeneralSecurityException if an error occurred with + * the PKCS #11 library. + */ +JNIEXPORT jboolean JNICALL +Java_com_netscape_jss_CryptoManager_enableFIPS + (JNIEnv *env, jclass clazz, jboolean fips) +{ + char *name=NULL; + jboolean switched = JNI_FALSE; + SECStatus status; + + if( ((fips==JNI_TRUE) && !PK11_IsFIPS()) || + ((fips==JNI_FALSE) && PK11_IsFIPS()) ) + { + name = PL_strdup(SECMOD_GetInternalModule()->commonName); + status = SECMOD_DeleteInternalModule(name); + PR_Free(name); + switched = JNI_TRUE; + } + + if(status != SECSuccess) { + JSS_throwMsg(env, + GENERAL_SECURITY_EXCEPTION, + "Failed to toggle FIPS mode"); + } + + return switched; +} + +/*********************************************************************** + * CryptoManager.FIPSEnabled + * + * Returns true if FIPS mode is currently on, false if it ain't. + */ +JNIEXPORT jboolean JNICALL +Java_com_netscape_jss_CryptoManager_FIPSEnabled(JNIEnv *env, jobject this) +{ + if( PK11_IsFIPS() ) { + return JNI_TRUE; + } else { + return JNI_FALSE; + } +} + +/*********************************************************************** + * CryptoManager.isDomestic + * + * Returns true if this build of jssjava is "domestic", false otherwise. + */ +JNIEXPORT jboolean JNICALL +Java_com_netscape_jss_CryptoManager_isDomestic(JNIEnv *env, jobject this) +{ + /* "C" data members */ + PRBool result; + + result = JSS_isDomestic(); + + /* Return a java boolean */ + if( result != PR_TRUE ) { + return JNI_FALSE; + } + + return JNI_TRUE; +} + +/*********************************************************************** + * CryptoManager.getPolicyTypeIndex + * + * Input export control policy from embedded utility policy table. + * + * Returns the index where the policy is stored in the JSS_PolicyTable[]. + */ +static jint +getPolicyTypeIndex( SVRPLCYPolicyType thisPolicy ) +{ + jint i; + + for( i = 0; i < NUM_POLICIES; i++ ) { + if( thisPolicy == JSS_PolicyTable[i] ) { + return i; + } + }; + + return( -1 ); +} + +/*********************************************************************** + * CryptoManager.getExportControlPolicyType + * + * Returns an integer related to the export control policy type + */ +JNIEXPORT jint JNICALL +Java_com_netscape_jss_CryptoManager_getExportControlPolicyType( JNIEnv *env, + jobject this ) +{ + /* "C" data members */ + SVRPLCYPolicyType policy; + + /* Get the export control policy from the embedded utility policy table */ + policy = JSS_getExportControlPolicyType(); + + /* Return a java int */ + return( getPolicyTypeIndex( policy ) ); +} + +/*********************************************************************** + * DatabaseCloser.closeDatabases + * + * Closes the cert and key database, rendering the security library + * unusable. + */ +JNIEXPORT void JNICALL +Java_com_netscape_jss_DatabaseCloser_closeDatabases + (JNIEnv *env, jobject this) +{ + PR_ASSERT( CERT_GetDefaultCertDB() != NULL ); + CERT_ClosePermCertDB( CERT_GetDefaultCertDB() ); + CERT_SetDefaultCertDB( NULL ); + + PR_ASSERT( SECKEY_GetDefaultKeyDB() != NULL ); + SECKEY_CloseKeyDB( SECKEY_GetDefaultKeyDB() ); + SECKEY_SetDefaultKeyDB( NULL ); +} diff --git a/mozilla/security/jss/org/mozilla/jss/manage/CryptoManager.java b/mozilla/security/jss/org/mozilla/jss/manage/CryptoManager.java new file mode 100644 index 00000000000..de44d7d1a5e --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/manage/CryptoManager.java @@ -0,0 +1,1273 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss; + +import com.netscape.jss.crypto.*; +import com.netscape.jss.util.*; +import com.netscape.jss.asn1.*; +import java.security.cert.CertificateException; +import java.security.GeneralSecurityException; +import com.netscape.jss.pkcs11.PK11Cert; +import java.util.*; +import com.netscape.jss.pkcs11.PK11Token; +import com.netscape.jss.pkcs11.PK11Module; +import com.netscape.jss.pkcs11.PK11SecureRandom; +import java.security.cert.CertificateEncodingException; +import com.netscape.jss.CRLImportException; + +/** + * This class is the starting poing for the crypto package. + * Use it to initialize the subsystem and to lookup certs, keys, and tokens. + * Initialization is done with static methods, and must be done before + * an instance can be created. All other operations are done with instance + * methods. + * @version $Revision: 1.1 $ $Date: 2000-12-15 20:49:37 $ + */ +public final class CryptoManager implements TokenSupplier +{ + public final static class NotInitializedException extends Exception {} + public final static class NicknameConflictException extends Exception {} + public final static class UserCertConflictException extends Exception {} + public final static class InvalidLengthException extends Exception {} + + /** + * The various options that can be used to initialize CryptoManager. + */ + public final static class InitializationValues { + protected InitializationValues() { + Assert.notReached("Default constructor"); + } + + ///////////////////////////////////////////////////////////// + // Constants + ///////////////////////////////////////////////////////////// + /** + * Token names must be this length exactly. + */ + public final int TOKEN_LENGTH = 33; + /** + * Slot names must be this length exactly. + */ + public final int SLOT_LENGTH = 65; + /** + * ManufacturerID must be this length exactly. + */ + public final int MANUFACTURER_LENGTH = 33; + /** + * Library description must be this length exactly. + */ + public final int LIBRARY_LENGTH = 33; + + /** + * This class enumerates the possible modes for FIPS compliance. + */ + public static final class FIPSMode { + private FIPSMode() {} + + /** + * Enable FIPS mode. + */ + public static final FIPSMode ENABLED = new FIPSMode(); + /** + * Disable FIPS mode. + */ + public static final FIPSMode DISABLED = new FIPSMode(); + /** + * Leave FIPS mode unchanged. All servers except Admin + * Server should use this, because only Admin Server should + * be altering FIPS mode. + */ + public static final FIPSMode UNCHANGED = new FIPSMode(); + } + + /** + * Creates a new set of CryptoManager initialization values. + * These values should be passed into + * CryptoManager.initialize(). All the values have + * defaults, except for modDBName, keyDBName, and certDBName, + * which are passed in as parameters. All the values can be + * modified after this constructor has been called. + */ + public InitializationValues( String modDBName, + String keyDBName, + String certDBName ) + { + this.modDBName = modDBName; + this.keyDBName = keyDBName; + this.certDBName = certDBName; + } + + /** + * The path of the security module database (secmod[ule].db). + */ + public String modDBName; + + /** + * The path of the key database (key3.db). + */ + public String keyDBName; + + /** + * The path of the certificate database (cert7.db). + */ + public String certDBName; + + /** + * The password callback to be used by JSS whenever a password + * is needed. May be NULL, in which the library will immediately fail + * to get a password if it tries to login automatically while + * performing + * a cryptographic operation. It will still work if the token + * has been manually logged in with CryptoToken.login. + *

The default is a ConsolePasswordCallback. + */ + public PasswordCallback passwordCallback = + new ConsolePasswordCallback(); + + /** + * The FIPS mode of the security library. Servers should + * use FIPSMode.UNCHANGED, since only + * Admin Server is supposed to alter this value. + *

The default is FIPSMode.UNCHANGED. + */ + public FIPSMode fipsMode = FIPSMode.UNCHANGED; + + /** + * To open the databases in read-only mode, set this flag to + * true. The default is false, meaning + * the databases are opened in read-write mode. + */ + public boolean readOnly = false; + + //////////////////////////////////////////////////////////////////// + // Manufacturer ID + //////////////////////////////////////////////////////////////////// + /** + * Returns the Manufacturer ID of the internal PKCS #11 module. + *

The default is "Netscape Communications Corp ". + */ + public String getManufacturerID() { return manufacturerID; } + + /** + * Sets the Manufacturer ID of the internal PKCS #11 module. + * This value must be exactly MANUFACTURER_LENGTH + * characters long. + * @exception InvalidLengthException If s.length() is not + * exactly MANUFACTURER_LENGTH. + */ + public void setManufacturerID(String s) throws InvalidLengthException { + if( s.length() != MANUFACTURER_LENGTH ) { + throw new InvalidLengthException(); + } + manufacturerID = s; + } + private String manufacturerID = + "Netscape Communications Corp "; + + //////////////////////////////////////////////////////////////////// + // Library Description + //////////////////////////////////////////////////////////////////// + /** + * Returns the description of the internal PKCS #11 module. + *

The default is "Internal Crypto Services ". + */ + public String getLibraryDescription() { return libraryDescription; } + + /** + * Sets the description of the internal PKCS #11 module. + * This value must be exactly LIBRARY_LENGTH + * characters long. + * @exception InvalidLengthException If s.length() is + * not exactly LIBRARY_LENGTH. + */ + public void setLibraryDescription(String s) + throws InvalidLengthException + { + if( s.length() != LIBRARY_LENGTH ) { + throw new InvalidLengthException(); + } + libraryDescription = s; + } + private String libraryDescription = + "Internal Crypto Services "; + + //////////////////////////////////////////////////////////////////// + // Internal Token Description + //////////////////////////////////////////////////////////////////// + /** + * Returns the description of the internal PKCS #11 token. + *

The default is "Internal Crypto Services Token ". + */ + public String getInternalTokenDescription() { + return internalTokenDescription; + } + + /** + * Sets the description of the internal PKCS #11 token. + * This value must be exactly TOKEN_LENGTH characters long. + * @exception InvalidLengthException If s.length() is + * not exactly TOKEN_LENGTH. + */ + public void setInternalTokenDescription(String s) + throws InvalidLengthException + { + if(s.length() != TOKEN_LENGTH) { + throw new InvalidLengthException(); + } + internalTokenDescription = s; + } + private String internalTokenDescription = + "Internal Crypto Services Token "; + + //////////////////////////////////////////////////////////////////// + // Internal Key Storage Token Description + //////////////////////////////////////////////////////////////////// + /** + * Returns the description of the internal PKCS #11 key storage token. + *

The default is "Internal Key Storage Token ". + */ + public String getInternalKeyStorageTokenDescription() { + return internalKeyStorageTokenDescription; + } + + /** + * Sets the description of the internal PKCS #11 key storage token. + * This value must be exactly TOKEN_LENGTH characters long. + * @exception InvalidLengthException If s.length() is + * not exactly TOKEN_LENGTH. + */ + public void setInternalKeyStorageTokenDescription(String s) + throws InvalidLengthException + { + if(s.length() != TOKEN_LENGTH) { + throw new InvalidLengthException(); + } + internalKeyStorageTokenDescription = s; + } + private String internalKeyStorageTokenDescription = + "Internal Key Storage Token "; + + //////////////////////////////////////////////////////////////////// + // Internal Slot Description + //////////////////////////////////////////////////////////////////// + /** + * Returns the description of the internal PKCS #11 slot. + *

The default is "Netscape Internal Cryptographic Services ". + */ + public String getInternalSlotDescription() { + return internalSlotDescription; + } + + /** + * Sets the description of the internal PKCS #11 slot. + * This value must be exactly SLOT_LENGTH characters + * long. + * @exception InvalidLengthException If s.length() is + * not exactly SLOT_LENGTH. + */ + public void setInternalSlotDescription(String s) + throws InvalidLengthException + { + if(s.length() != SLOT_LENGTH) { + throw new InvalidLengthException(); + } + internalSlotDescription = s; + } + private String internalSlotDescription = + "Netscape Internal Cryptographic Services "; + + //////////////////////////////////////////////////////////////////// + // Internal Key Storage Slot Description + //////////////////////////////////////////////////////////////////// + /** + * Returns the description of the internal PKCS #11 key storage slot. + *

The default is "Netscape Internal Private Key and Certificate Storage ". + + */ + public String getInternalKeyStorageSlotDescription() { + return internalKeyStorageSlotDescription; + } + + /** + * Sets the description of the internal PKCS #11 key storage slot. + * This value must be exactly SLOT_LENGTH characters + * long. + * @exception InvalidLengthException If s.length() is + * not exactly SLOT_LENGTH. + */ + public void setInternalKeyStorageSlotDescription(String s) + throws InvalidLengthException + { + if(s.length() != SLOT_LENGTH) { + throw new InvalidLengthException(); + } + internalKeyStorageSlotDescription = s; + } + private String internalKeyStorageSlotDescription = + "Netscape Internal Private Key and Certificate Storage "; + + //////////////////////////////////////////////////////////////////// + // FIPS Slot Description + //////////////////////////////////////////////////////////////////// + /** + * Returns the description of the internal PKCS #11 FIPS slot. + *

The default is "Netscape Internal FIPS-140-1 Cryptographic Services ". + */ + public String getFIPSSlotDescription() { + return FIPSSlotDescription; + } + + /** + * Sets the description of the internal PKCS #11 FIPS slot. + * This value must be exactly SLOT_LENGTH characters + * long. + * @exception InvalidLengthException If s.length() is + * not exactly SLOT_LENGTH. + */ + public void setFIPSSlotDescription(String s) + throws InvalidLengthException + { + if(s.length() != SLOT_LENGTH) { + throw new InvalidLengthException(); + } + FIPSSlotDescription = s; + } + private String FIPSSlotDescription = + "Netscape Internal FIPS-140-1 Cryptographic Services "; + + //////////////////////////////////////////////////////////////////// + // FIPS Key Storage Slot Description + //////////////////////////////////////////////////////////////////// + /** + * Returns the description of the internal PKCS #11 FIPS + * Key Storage slot. + *

The default is "Netscape Internal FIPS-140-1 Private Key and Certificate Storage ". + */ + public String getFIPSKeyStorageSlotDescription() { + return FIPSKeyStorageSlotDescription; + } + + /** + * Sets the description of the internal PKCS #11 FIPS Key Storage slot. + * This value must be exactly SLOT_LENGTH characters + * long. + * @exception InvalidLengthException If s.length() is + * not exactly SLOT_LENGTH. + */ + public void setFIPSKeyStorageSlotDescription(String s) + throws InvalidLengthException + { + if(s.length() != SLOT_LENGTH) { + throw new InvalidLengthException(); + } + FIPSKeyStorageSlotDescription = s; + } + private String FIPSKeyStorageSlotDescription = + "Netscape Internal FIPS-140-1 Private Key and Certificate Storage "; + + /** + * To have NSS check the OCSP responder for when verifying + * certificates, set this flags to true. It is false by + * default. + */ + public boolean ocspCheckingEnabled = false; + + /** + * Specify the location and cert of the responder. + * If OCSP checking is enabled *and* this variable is + * set to some URL, all OCSP checking will be done via + * this URL. + * + * If this variable is null, the OCSP responder URL will + * be obtained from the AIA extension in the certificate + * being queried. + * + * If this is set, you must also set ocspResponderCertNickname + * + */ + + + public String ocspResponderURL = null; + + /** + * The nickname of the cert to trust (expected) to + * sign the OCSP responses. + * Only checked when the OCSPResponder value is set. + */ + public String ocspResponderCertNickname = null; + + } + + //////////////////////////////////////////////////// + // Module and Token Management + //////////////////////////////////////////////////// + + /** + * Retrieves the internal cryptographic services token. This is the + * token built into the Netscape Security Library that performs bulk + * cryptographic operations. + *

In FIPS mode, the internal cryptographic services token is the + * same as the internal key storage token. + * + * @return The internal cryptographic services token. + */ + public synchronized CryptoToken getInternalCryptoToken() { + return internalCryptoToken; + } + + /** + * Retrieves the internal key storage token. This is the token + * provided by the Netscape Security Library to store private keys. + * The keys stored in this token are stored in an encrypted key database. + *

In FIPS mode, the internal key storage token is the same as + * the internal cryptographic services token. + * + * @return The internal key storage token. + */ + public synchronized CryptoToken getInternalKeyStorageToken() { + return internalKeyStorageToken; + } + + /** + * Looks up the CryptoToken with the given name. Searches all + * loaded cryptographic modules for the token. + * + * @param name The name of the token. + * @exception com.netscape.jss.crypto.NoSuchTokenException If no token + * is found with the given name. + */ + public synchronized CryptoToken getTokenByName(String name) + throws NoSuchTokenException + { + Enumeration tokens = getAllTokens(); + CryptoToken token; + + while(tokens.hasMoreElements()) { + token = (CryptoToken) tokens.nextElement(); + try { + if( name.equals(token.getName()) ) { + return token; + } + } catch( TokenException e ) { + Assert.assert(false, "Got a token exception"); + } + } + throw new NoSuchTokenException(); + } + + /** + * Retrieves all tokens that support the given algorithm. + * + */ + public synchronized Enumeration getTokensSupportingAlgorithm(Algorithm alg) + { + Enumeration tokens = getAllTokens(); + Vector goodTokens = new Vector(); + CryptoToken tok; + + while(tokens.hasMoreElements()) { + tok = (CryptoToken) tokens.nextElement(); + if( tok.doesAlgorithm(alg) ) { + goodTokens.addElement(tok); + } + } + return goodTokens.elements(); + } + + /** + * Retrieves all tokens. This is an enumeration of all tokens on all + * modules. + * + * @return All tokens accessible from JSS. Each item of the enumeration + * is a CryptoToken + * @see com.netscape.jss.crypto.CryptoToken + */ + public synchronized Enumeration getAllTokens() { + Enumeration modules = getModules(); + Enumeration tokens; + Vector allTokens = new Vector(); + + while(modules.hasMoreElements()) { + tokens = ((PK11Module)modules.nextElement()).getTokens(); + while(tokens.hasMoreElements()) { + allTokens.addElement( tokens.nextElement() ); + } + } + return allTokens.elements(); + } + + /** + * Retrieves all tokens except those built into the Netscape Security + * Library. This excludes the internal token and the internal + * key storage token (which are one and the same in FIPS mode). + * + * @return All tokens accessible from JSS, except for the built-in + * internal tokens. + */ + public synchronized Enumeration getExternalTokens() { + Enumeration modules = getModules(); + Enumeration tokens; + PK11Token token; + Vector allTokens = new Vector(); + + while(modules.hasMoreElements()) { + tokens = ((PK11Module)modules.nextElement()).getTokens(); + while(tokens.hasMoreElements()) { + token = (PK11Token) tokens.nextElement(); + if( ! token.isInternalCryptoToken() && + ! token.isInternalKeyStorageToken() ) + { + allTokens.addElement( token ); + } + } + } + return allTokens.elements(); + } + + /** + * Retrieves all installed cryptographic modules. + * + * @return An enumeration of all installed PKCS #11 modules. Each + * item in the enumeration is a PK11Module. + * @see com.netscape.jss.pkcs11.PK11Module + */ + public synchronized Enumeration getModules() { + return moduleVector.elements(); + } + + // Need to reload modules after adding new one + //public native addModule(String name, String libraryName); + + /** + * The list of modules. This should be initialized by the constructor + * and updated whenever 1) a new module is added, 2) a module is deleted, + * or 3) FIPS mode is switched. + */ + private Vector moduleVector; + + /** + * Re-creates the Vector of modules that is stored by CryptoManager. + * This entails going into native code to enumerate all modules, + * wrap each one in a PK11Module, and storing the PK11Module in the vector. + */ + private synchronized void reloadModules() { + moduleVector = new Vector(); + putModulesInVector(moduleVector); + + // Get the internal tokens + Enumeration tokens = getAllTokens(); + + internalCryptoToken = null; + internalKeyStorageToken = null; + while(tokens.hasMoreElements()) { + PK11Token token = (PK11Token) tokens.nextElement(); + if( token.isInternalCryptoToken() ) { + Assert.assert(internalCryptoToken == null); + internalCryptoToken = token; + } + if( token.isInternalKeyStorageToken() ) { + Assert.assert(internalKeyStorageToken == null); + internalKeyStorageToken = token; + } + } + Assert.assert(internalKeyStorageToken != null); + Assert.assert(internalCryptoToken != null); + } + + /** + * The internal cryptographic services token. + */ + private CryptoToken internalCryptoToken; + + /** + * The internal key storage token. + */ + private CryptoToken internalKeyStorageToken; + + /** + * Native code to traverse all PKCS #11 modules, wrap each one in + * a PK11Module, and insert each PK11Module into the given vector. + */ + private native void putModulesInVector(Vector vector); + + + /////////////////////////////////////////////////////////////////////// + // Constructor and Accessors + /////////////////////////////////////////////////////////////////////// + + /** + * Constructor, for internal use only. + */ + protected CryptoManager() { + TokenSupplierManager.setTokenSupplier(this); + reloadModules(); + } + + /** + * Retrieve the single instance of CryptoManager. + * This cannot be called before initialization. + * + * @see #initialize(CryptoManager.InitializationValues) + * @exception NotInitializedException If + * initialize(InitializationValues has not yet been + * called. + */ + public synchronized static CryptoManager getInstance() + throws NotInitializedException + { + if(instance==null) { + throw new NotInitializedException(); + } + return instance; + } + + /** + * The singleton instance, and a static initializer to create it. + */ + private static CryptoManager instance=null; + + + /////////////////////////////////////////////////////////////////////// + // FIPS management + /////////////////////////////////////////////////////////////////////// + + /** + * Enables or disables FIPS-140-1 compliant mode. If this returns true, + * you must reloadModules(). This should only be called once in a program, + * at the beginning, because it invalidates tokens and modules. + * + * @param fips true to turn FIPS compliant mode on, false to turn it off. + */ + private static native boolean enableFIPS(boolean fips) + throws GeneralSecurityException; + + /** + * Determines whether FIPS-140-1 compliance is active. + * + * @return true if the security library is in FIPS-140-1 compliant mode. + */ + public synchronized native boolean FIPSEnabled(); + + /////////////////////////////////////////////////////////////////////// + // Export Control Policy management + /////////////////////////////////////////////////////////////////////// + + /** + * Determines whether this build of jssjava is "domestic". + * + * @return true if jssjava is "domestic", false otherwise. + */ + public synchronized native boolean isDomestic(); + + /** + * Determines what policy this build of jssjava contains. + * + * @return the policy type of this jssjava executable. + */ + public synchronized native int getExportControlPolicyType(); + + /////////////////////////////////////////////////////////////////////// + // Password Callback management + /////////////////////////////////////////////////////////////////////// + + /** + * This function sets the global password callback. It is + * not thread-safe to change this. A better strategy than using + * callbacks is to explicitly login to the tokens you need to use. + * Password callbacks are then only used as a last resort. + *

The callback may be NULL, in which case password callbacks will + * fail gracefully. + */ + public synchronized void setPasswordCallback(PasswordCallback pwcb) { + passwordCallback = pwcb; + setNativePasswordCallback( pwcb ); + } + private native void setNativePasswordCallback(PasswordCallback cb); + + /** + * Returns the currently registered password callback. + */ + public synchronized PasswordCallback getPasswordCallback() { + return passwordCallback; + } + + private PasswordCallback passwordCallback; + + + //////////////////////////////////////////////////// + // Initialization + //////////////////////////////////////////////////// + + /** + * Initialize the security subsystem. Initializes NSPR and the + * Random Number Generator, but does not open any databases or initialize + * PKCS #11. The only cryptographic operation that can be performed + * after this call is PQG parameter generation. This method can + * be called repeatedly, before or after the call to + * initialize(InitializationValues). + */ + public static synchronized void initialize() + { + NSSInit.loadNativeLibraries(); + initializeNative(); + } + private static native void initializeNative(); + + /** + * Initialize the security subsystem. Opens the databases, loads all + * PKCS #11 modules, initializes the internal random number generator. + * The initialize methods that take arguments should be + * called only once, otherwise they will throw + * an exception. It is OK to call them after calling + * initialize(). + * + * @param modDBName The full path, relative or absolute, of the security + * module database. + * @param keyDBName The full path, relative or absolute, of the key + * database. + * @param certDBName The full path, relative or absolute, of the + * certificate database. + * @exception com.netscape.jss.util.KeyDatabaseException Unable to open + * the key database, or it was currupted. + * @exception com.netscape.jss.util.CertDatabaseException Unable + * to open the certificate database, or it was currupted. + **/ + public static synchronized void initialize( String modDBName, + String keyDBName, + String certDBName ) + throws KeyDatabaseException, + CertDatabaseException, + AlreadyInitializedException, + GeneralSecurityException + { + InitializationValues vals = + new InitializationValues( modDBName, keyDBName, certDBName ); + initialize( vals ); + } + + /** + * Initialize the security subsystem. Opens the databases, loads all + * PKCS #11 modules, initializes the internal random number generator. + * The initialize methods that take arguments should be + * called only once, otherwise they will throw + * an exception. It is OK to call them after calling + * initialize(). + * + * @param values The options with which to initialize CryptoManager. + * @exception com.netscape.jss.util.KeyDatabaseException Unable to open + * the key database, or it was currupted. + * @exception com.netscape.jss.util.CertDatabaseException Unable + * to open the certificate database, or it was currupted. + **/ + public static synchronized void initialize( InitializationValues values ) + throws + KeyDatabaseException, + CertDatabaseException, + AlreadyInitializedException, + GeneralSecurityException + { + if(instance != null) { + throw new AlreadyInitializedException(); + } + NSSInit.loadNativeLibraries(); + if (values.ocspResponderURL != null) { + if (values.ocspResponderCertNickname == null) { + throw new GeneralSecurityException( + "Must set ocspResponderCertNickname"); + } + } + initializeAllNative(values.modDBName, + values.keyDBName, + values.certDBName, + values.readOnly, + values.getManufacturerID(), + values.getLibraryDescription(), + values.getInternalTokenDescription(), + values.getInternalKeyStorageTokenDescription(), + values.getInternalSlotDescription(), + values.getInternalKeyStorageSlotDescription(), + values.getFIPSSlotDescription(), + values.getFIPSKeyStorageSlotDescription(), + values.ocspCheckingEnabled, + values.ocspResponderURL, + values.ocspResponderCertNickname + ); + + instance = new CryptoManager(); + instance.setPasswordCallback(values.passwordCallback); + if( values.fipsMode != InitializationValues.FIPSMode.UNCHANGED) { + if( enableFIPS(values.fipsMode == + InitializationValues.FIPSMode.ENABLED) ) + { + instance.reloadModules(); + } + } + java.security.Security.removeProvider("SUN"); + int position = java.security.Security.insertProviderAt( + new com.netscape.jss.provider.Provider(), + 1); + if(position==-11) { + Debug.trace(Debug.ERROR, + "Unable to install Netscape provider"); + } + } + + private static native void + initializeAllNative(String modDBName, + String keyDBName, + String certDBName, + boolean readOnly, + String manufacturerID, + String libraryDescription, + String internalTokenDescription, + String internalKeyStorageTokenDescription, + String internalSlotDescription, + String internalKeyStorageSlotDescription, + String fipsSlotDescription, + String fipsKeyStorageSlotDescription, + boolean ocspCheckingEnabled, + String ocspResponderURL, + String ocspResponderCertNickname +) + throws KeyDatabaseException, + CertDatabaseException, + AlreadyInitializedException; + + ///////////////////////////////////////////////////////////// + // Cert Lookup + ///////////////////////////////////////////////////////////// + /** + * Retrieves all CA certificates in the trust database. This + * is a fairly expensive operation in that it involves traversing + * the entire certificate database. + * @return An array of all CA certificates stored permanently + * in the trust database. + */ + public native InternalCertificate[] + getCACerts(); + + /** + * Retrieves all certificates in the trust database. This + * is a fairly expensive operation in that it involves traversing + * the entire certificate database. + * @return An array of all certificates stored permanently + * in the trust database. + */ + public native InternalCertificate[] + getPermCerts(); + + /** + * Imports a chain of certificates. The leaf certificate may be a + * a user certificate, that is, a certificate that belongs to the + * current user and whose private key is available for use. + * If the leaf certificate is a user certificate, it is stored + * on the token + * that contains the corresponding private key, and is assigned the + * given nickname. + * + * @param certPackage An encoded certificate or certificate chain. + * Acceptable + * encodings are binary PKCS #7 SignedData objects and + * DER-encoded certificates, which may or may not be wrapped + * in a Base-64 encoding package surrounded by + * "-----BEGIN CERTIFICATE-----" and + * "-----END CERTIFICATE-----". + * @param nickname The nickname for the user certificate. It must + * be unique. It is ignored if there is no user certificate. + * @return The leaf certificate from the chain. + * @exception CertificateEncodingException If the package encoding + * was not recognized. + * @exception CertificateNicknameConflictException If the leaf certificate + * is a user certificate, and another certificate already has the + * given nickname. + * @exception UserCertConflictException If the leaf certificate + * is a user certificate, but it has already been imported. + * @exception NoSuchItemOnTokenException If the leaf certificate is + * a user certificate, but the matching private key cannot be found. + * @exception TokenException If an error occurs importing a leaf + * certificate into a token. + */ + public X509Certificate + importCertPackage(byte[] certPackage, String nickname ) + throws CertificateEncodingException, + NicknameConflictException, + UserCertConflictException, + NoSuchItemOnTokenException, + TokenException + { + return importCertPackageNative(certPackage, nickname, false, false); + } + + /** + * Imports a chain of certificates. The leaf of the chain is a CA + * certificate AND a user certificate (this would only be called by + * a CA installing its own certificate). + * + * @param certPackage An encoded certificate or certificate chain. + * Acceptable + * encodings are binary PKCS #7 SignedData objects and + * DER-encoded certificates, which may or may not be wrapped + * in a Base-64 encoding package surrounded by + * "-----BEGIN CERTIFICATE-----" and + * "-----END CERTIFICATE-----". + * @param nickname The nickname for the user certificate. It must + * be unique. + * @return The leaf certificate from the chain. + * @exception CertificateEncodingException If the package encoding + * was not recognized. + * @exception CertificateNicknameConflictException If the leaf certificate + * another certificate already has the given nickname. + * @exception UserCertConflictException If the leaf certificate + * has already been imported. + * @exception NoSuchItemOnTokenException If the the private key matching + * the leaf certificate cannot be found. + * @exception TokenException If an error occurs importing the leaf + * certificate into a token. + */ + public X509Certificate + importUserCACertPackage(byte[] certPackage, String nickname) + throws CertificateEncodingException, + NicknameConflictException, + UserCertConflictException, + NoSuchItemOnTokenException, + TokenException + { + return importCertPackageNative(certPackage, nickname, false, true); + } + + + + /** + * Imports a chain of certificates, none of which is a user certificate. + * + * @param certPackage An encoded certificate or certificate chain. + * Acceptable + * encodings are binary PKCS #7 SignedData objects and + * DER-encoded certificates, which may or may not be wrapped + * in a Base-64 encoding package surrounded by + * "-----BEGIN CERTIFICATE-----" and + * "-----END CERTIFICATE-----". + * @return The leaf certificate from the chain. + * @exception CertificateEncodingException If the package encoding + * was not recognized. + * @exception TokenException If an error occurs importing a leaf + * certificate into a token. + */ + public X509Certificate + importCACertPackage(byte[] certPackage) + throws CertificateEncodingException, + TokenException + { + try { + return importCertPackageNative(certPackage, null, true, false); + } catch(NicknameConflictException e) { + Assert.notReached("importing CA certs caused nickname conflict"); + Debug.trace(Debug.ERROR, + "importing CA certs caused nickname conflict"); + } catch(UserCertConflictException e) { + Assert.notReached("importing CA certs caused user cert conflict"); + Debug.trace(Debug.ERROR, + "importing CA certs caused user cert conflict"); + } catch(NoSuchItemOnTokenException e) { + Assert.notReached("importing CA certs caused NoSuchItemOnToken"+ + "Exception"); + Debug.trace(Debug.ERROR, + "importing CA certs caused NoSuchItemOnTokenException"); + } + return null; + } + + /** + * Imports a single certificate into the permanent certificate + * database. + * + * @param derCert the certificate you want to add + * @param nickname the nickname you want to refer to the certificate as + * (must not be null) + */ + + public InternalCertificate + importCertToPerm(X509Certificate cert, String nickname) + throws TokenException, InvalidNicknameException + { + if (nickname==null) { + throw new InvalidNicknameException("Nickname must be non-null"); + } + + if (cert instanceof InternalCertificate) { + return (InternalCertificate) cert; + } + else { + return importCertToPermNative(cert,nickname); + } + } + + private native InternalCertificate + importCertToPermNative(X509Certificate cert, String nickname) + throws TokenException; + + /** + * @param noUser true if we know that none of the certs are user certs. + * In this case, no attempt will be made to find a matching private + * key for the leaf certificate. + */ + private native X509Certificate + importCertPackageNative(byte[] certPackage, String nickname, + boolean noUser, boolean leafIsCA) + throws CertificateEncodingException, + NicknameConflictException, + UserCertConflictException, + NoSuchItemOnTokenException, + TokenException; + + /*============ CRL importing stuff ********************************/ + + private static int TYPE_KRL = 0; + private static int TYPE_CRL = 1; + /** + * Imports a CRL, and stores it into the cert7.db + * Validate CRL then import it to the dbase. If there is already a CRL with the + * same CA in the dbase, it will be replaced if derCRL is more up to date. + * + * @param crl the DER-encoded CRL. + * @param url the URL where this CRL can be retrieved from (for future updates). + * [ note that CRLs are not retrieved automatically ]. Can be null + * @exception CRLImportException If the package encoding + * was not recognized. + */ + public void + importCRL(byte[] crl,String url) + throws CRLImportException, + TokenException + { + importCRLNative(crl,url,TYPE_CRL); + } + + + /** + * Imports a CRL, and stores it into the cert7.db + * + * @param the DER-encoded CRL. + */ + private native + void importCRLNative(byte[] crl, String url, int rl_type) + throws CRLImportException, TokenException; + + + + /*============ Cert Exporting stuff ********************************/ + + + /** + * Exports one or more certificates into a PKCS #7 certificate container. + * This is just a SignedData object whose certificates + * field contains the given certificates but whose content field + * is empty. + * + * @param certs One or more certificates that should be exported into + * the PKCS #7 object. The leaf certificate should be the first + * in the chain. The output of buildCertificateChain + * would be appropriate here. + * @exception CertificateEncodingException If the array is empty, + * or an error occurred encoding the certificates. + * @return A byte array containing a PKCS #7 SignedData object. + * @see #buildCertificateChain + */ + public native byte[] + exportCertsToPKCS7(X509Certificate[] certs) + throws CertificateEncodingException; + + /** + * Looks up a certificate given its nickname. + * + * @param nickname The nickname of the certificate to look for. + * @return The certificate matching this nickname, if one is found. + * @exception ObjectNotFoundException If no certificate could be found + * with the given nickname. + * @exception TokenException If an error occurs in the security library. + */ + public com.netscape.jss.crypto.X509Certificate + findCertByNickname(String nickname) + throws ObjectNotFoundException, TokenException + { + Assert.assert(nickname!=null); + return findCertByNicknameNative(nickname); + } + + /** + * Returns all certificates with the given nickname. + * + * @param nickname The nickname of the certificate to look for. + * @return The certificates matching this nickname. The array may be empty + * if no matching certs were found. + * @exception TokenException If an error occurs in the security library. + */ + public com.netscape.jss.crypto.X509Certificate[] + findCertsByNickname(String nickname) + throws TokenException + { + Assert.assert(nickname!=null); + return findCertsByNicknameNative(nickname); + } + + /** + * Looks up a certificate by issuer and serial number. The internal + * database and all PKCS #11 modules are searched. + * + * @param derIssuer The DER encoding of the certificate issuer name. + * The issuer name has ASN.1 type Name, which is defined in + * X.501. + * @param serialNumber The certificate serial number. + * @exception ObjectNotFoundException If the certificate is not found + * in the internal certificate database or on any PKCS #11 token. + * @exception TokenException If an error occurs in the security library. + */ + public com.netscape.jss.crypto.X509Certificate + findCertByIssuerAndSerialNumber(byte[] derIssuer, INTEGER serialNumber) + throws ObjectNotFoundException, TokenException + { + try { + ANY sn = (ANY) ASN1Util.decode(ANY.getTemplate(), + ASN1Util.encode(serialNumber) ); + return findCertByIssuerAndSerialNumberNative(derIssuer, + sn.getContents() ); + } catch( InvalidBERException e ) { + Assert.notReached("Invalid BER encoding of INTEGER"); + return null; + } + } + + /** + * @param serialNumber The contents octets of a DER-encoding of the + * certificate serial number. + */ + private native com.netscape.jss.crypto.X509Certificate + findCertByIssuerAndSerialNumberNative(byte[] derIssuer, byte[] serialNumber) + throws ObjectNotFoundException, TokenException; + + protected native com.netscape.jss.crypto.X509Certificate + findCertByNicknameNative(String nickname) + throws ObjectNotFoundException, TokenException; + + protected native com.netscape.jss.crypto.X509Certificate[] + findCertsByNicknameNative(String nickname) + throws TokenException; + + ///////////////////////////////////////////////////////////// + // build cert chains + ///////////////////////////////////////////////////////////// + /** + * Given a certificate, constructs its certificate chain. It may + * or may not chain up to a trusted root. + * @param leaf The certificate that is the starting point of the chain. + * @return An array of certificates, starting at the leaf and ending + * with the highest certificate on the chain that was found. + * @throws CertificateException If the certificate is not recognized + * by the underlying provider. + */ + public com.netscape.jss.crypto.X509Certificate[] + buildCertificateChain(com.netscape.jss.crypto.X509Certificate leaf) + throws java.security.cert.CertificateException, TokenException + { + if( ! (leaf instanceof PK11Cert) ) { + throw new CertificateException( + "Certificate is not a PKCS #11 certificate"); + } + return buildCertificateChainNative((PK11Cert)leaf); + } + + native com.netscape.jss.crypto.X509Certificate[] + buildCertificateChainNative(PK11Cert leaf) + throws CertificateException, TokenException; + + + ///////////////////////////////////////////////////////////// + // lookup private keys + ///////////////////////////////////////////////////////////// + /** + * Looks up the PrivateKey matching the given certificate. + * + * @exception ObjectNotFoundException If no private key can be + * found matching the given certificate. + * @exception TokenException If an error occurs in the security library. + */ + public com.netscape.jss.crypto.PrivateKey + findPrivKeyByCert(com.netscape.jss.crypto.X509Certificate cert) + throws ObjectNotFoundException, TokenException + { + Assert.assert(cert!=null); + if(! (cert instanceof com.netscape.jss.pkcs11.PK11Cert)) { + Assert.notReached("non-pkcs11 cert passed to PK11Finder"); + throw new ObjectNotFoundException(); + } + return findPrivKeyByCertNative(cert); + } + + protected native com.netscape.jss.crypto.PrivateKey + findPrivKeyByCertNative(com.netscape.jss.crypto.X509Certificate cert) + throws ObjectNotFoundException, TokenException; + + ///////////////////////////////////////////////////////////// + // Provide Pseudo-Random Number Generation + ///////////////////////////////////////////////////////////// + + /** + * Retrieves a FIPS-140-1 validated random number generator. + * + * @return A JSS SecureRandom implemented with the FIPS-validated + * Netscape security library. + */ + public com.netscape.jss.crypto.JSSSecureRandom + createPseudoRandomNumberGenerator() + { + return new PK11SecureRandom(); + } + + /** + * Retrieves a FIPS-140-1 validated random number generator. + * + * @return A JSS SecureRandom implemented with the FIPS-validated + * Netscape security library. + */ + public com.netscape.jss.crypto.JSSSecureRandom + getSecureRNG() { + return new PK11SecureRandom(); + } + + // Policy Type indices. These must be kept in sync with the + // policy type array in CryptoManager.c. + public static final int NULL_POLICY=0; + public static final int DOMESTIC_POLICY=1; + public static final int EXPORT_POLICY=2; + public static final int FRANCE_POLICY=3; +} diff --git a/mozilla/security/jss/org/mozilla/jss/manage/DatabaseCloser.java b/mozilla/security/jss/org/mozilla/jss/manage/DatabaseCloser.java new file mode 100644 index 00000000000..e554977fb83 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/manage/DatabaseCloser.java @@ -0,0 +1,74 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss; + +/** + * A class for closing databases. Since closing the databases is + * very dangerous and breaks the JSS model, it may only be done from + * special applications. This class should be subclasses by + * authorized subclasses. It cannot be instantiated itself. + */ +public abstract class DatabaseCloser { + + private static final String authorizedClosers[] = + { "com.netscape.certsetup.apps.CertSetup$DatabaseCloser", + "com.netscape.jss.CloseDBs" }; + + /** + * Creates a new DatabaseCloser. This should only be called + * from an authorized subclass. This class cannot itself be + * instantiated. + * + * @throws Exception If the instantiation is not a valid subclass. + */ + public DatabaseCloser() throws Exception { + Class clazz = this.getClass(); + String name = clazz.getName(); + boolean approved = false; + for(int i=0; i < authorizedClosers.length; i++) { + if( name.equals( authorizedClosers[i] ) ) { + approved = true; + break; + } + } + if(!approved) { + throw new Exception(); + } + } + + /** + * Closes the certificate and key databases. This is extremely + * dangerous. + */ + protected native void closeDatabases(); +} diff --git a/mozilla/security/jss/org/mozilla/jss/manage/KeyDatabaseException.java b/mozilla/security/jss/org/mozilla/jss/manage/KeyDatabaseException.java new file mode 100644 index 00000000000..af5692b3b6d --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/manage/KeyDatabaseException.java @@ -0,0 +1,44 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss; + +/** + * This exception is thrown if the key database does not exist, or if + * an error occurs while opening it. + */ +public class KeyDatabaseException extends java.lang.Exception { + public KeyDatabaseException() {} + public KeyDatabaseException(String mesg) { + super(mesg); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/manage/Makefile b/mozilla/security/jss/org/mozilla/jss/manage/Makefile new file mode 100644 index 00000000000..9b72e07f79e --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/manage/Makefile @@ -0,0 +1,76 @@ +#! gmake +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +####################################################################### +# (1) Include initial platform-independent assignments (MANDATORY). # +####################################################################### + +include manifest.mn + +####################################################################### +# (2) Include "global" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/config.mk + +####################################################################### +# (3) Include "component" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/$(MODULE)/config/config.mk + +####################################################################### +# (4) Include "local" platform-dependent assignments (OPTIONAL). # +####################################################################### + +include config.mk + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### + + + diff --git a/mozilla/security/jss/org/mozilla/jss/manage/NSSInit.c b/mozilla/security/jss/org/mozilla/jss/manage/NSSInit.c new file mode 100644 index 00000000000..1b04790c1c8 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/manage/NSSInit.c @@ -0,0 +1,110 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +#include "_jni/com_netscape_jss_NSSInit.h" +#include +#include "jssinit.h" + +/********************************************************************/ +/* The following VERSION Strings should be updated in the following */ +/* files everytime a new release of JSS is generated: */ +/* */ +/* jssjava: ns/ninja/cmd/jssjava/jssjava.c */ +/* jss.jar: ns/ninja/com/netscape/jss/manage/NSSInit.java */ +/* jss.dll: ns/ninja/com/netscape/jss/manage/NSSInit.c */ +/* */ +/********************************************************************/ + +static const char* DLL_JSS_VERSION = "JSS_VERSION = JSS_2_1 11 Dec 2000"; +static const char* DLL_JDK_VERSION = "JDK_VERSION = JDK 1.2.2"; +static const char* DLL_SVRCORE_VERSION = "SVRCORE_VERSION = SVRCORE_2_5_1"; +static const char* DLL_NSS_VERSION = "NSS_VERSION = NSS_2_8_4_RTM"; +static const char* DLL_DBM_VERSION = "DBM_VERSION = DBM_1_54"; +static const char* DLL_NSPR_VERSION = "NSPR_VERSION = v3.5.1"; + +/*********************************************************************** + * NSSInit.initializeNative + * + * This just passes its arguments to CryptoManager.initializeAllNative. + */ +JNIEXPORT void JNICALL +Java_com_netscape_jss_NSSInit_initializeNative + (JNIEnv *env, jclass clazz, + jstring modDBName, + jstring keyDBName, + jstring certDBName, + jboolean readOnly, + jstring manuString, + jstring libraryString, + jstring tokString, + jstring keyTokString, + jstring slotString, + jstring keySlotString, + jstring fipsString, + jstring fipsKeyString ) +{ + jboolean ocsp = JNI_FALSE; + jstring ocsp_url = NULL; + jstring ocsp_nickname = NULL; + + JSS_completeInitialize( + env, + modDBName, + keyDBName, + certDBName, + readOnly, + manuString, + libraryString, + tokString, + keyTokString, + slotString, + keySlotString, + fipsString, + fipsKeyString, + ocsp, + ocsp_url, + ocsp_nickname); +} + + +/*********************************************************************** + * NSSInit.setPasswordCallback + * + * This just passes its arguments to CryptoManager.setNativePasswordCallback + */ +JNIEXPORT void JNICALL +Java_com_netscape_jss_NSSInit_setPasswordCallback + (JNIEnv *env, jclass clazz, jobject pwcb) +{ + JSS_setPasswordCallback(env, pwcb); +} diff --git a/mozilla/security/jss/org/mozilla/jss/manage/NSSInit.java b/mozilla/security/jss/org/mozilla/jss/manage/NSSInit.java new file mode 100644 index 00000000000..b00f5600fc4 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/manage/NSSInit.java @@ -0,0 +1,200 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss; + +import com.netscape.jss.util.Debug; +import com.netscape.jss.util.PasswordCallback; +import com.netscape.jss.util.ConsolePasswordCallback; +import com.netscape.jss.KeyDatabaseException; +import com.netscape.jss.CertDatabaseException; +import com.netscape.jss.crypto.AlreadyInitializedException; + +/** + * This class initializes Java NSS and sets up the password callback. + */ +public final class NSSInit { + + /********************************************************************/ + /* The following VERSION Strings should be updated in the following */ + /* files everytime a new release of JSS is generated: */ + /* */ + /* jssjava: ns/ninja/cmd/jssjava/jssjava.c */ + /* jss.jar: ns/ninja/com/netscape/jss/manage/NSSInit.java */ + /* jss.dll: ns/ninja/com/netscape/jss/manage/NSSInit.c */ + /* */ + /********************************************************************/ + + public static final String + JAR_JSS_VERSION = "JSS_VERSION = JSS_2_1 11 Dec 2000"; + public static final String + JAR_JDK_VERSION = "JDK_VERSION = JDK 1.2.2"; + public static final String + JAR_SVRCORE_VERSION = "SVRCORE_VERSION = SVRCORE_2_5_1"; + public static final String + JAR_NSS_VERSION = "NSS_VERSION = NSS_2_8_4_RTM"; + public static final String + JAR_DBM_VERSION = "DBM_VERSION = DBM_1_54"; + public static final String + JAR_NSPR_VERSION = "NSPR_VERSION = v3.5.1"; + + /** + * Loads the JSS dynamic library if necessary. + * The system property "jss.load" will be set to "no" by jssjava + * because it is statically linked to the jss libraries. If this + * property is not set, that means we are not running jssjava + * and need to dynamically load the library. + *

This method is idempotent. + */ + synchronized static void loadNativeLibraries() + { + if( ! mNativeLibrariesLoaded && + ! ("no").equals(System.getProperty("jss.load")) ) + { + try { + Debug.trace(Debug.VERBOSE, "about to load jss library"); + System.loadLibrary("jss21"); + Debug.trace(Debug.VERBOSE, "jss library loaded"); + } catch( UnsatisfiedLinkError e) { + Debug.trace(Debug.ERROR, "ERROR: Unable to load jss library"); + throw e; + } + mNativeLibrariesLoaded = true; + } + } + static private boolean mNativeLibrariesLoaded = false; + + /** + * Initialize Java NSS. This method opens the security module, key, + * and certificate databases and initializes the Random Number Generator. + * The certificate and key databases are opened in read-only mode. + * + *

This method also attempts to load the native implementation library. + * On UNIX systems, this library is named libjss.so, + * and it must be present in the LD_LIBRARY_PATH. + * On Windows systems, the library is named + * jss.dll and must be present in the PATH. + * If the library cannot be found, an UnsatisfiedLinkError + * is thrown. + * + *

This method should only be called once by an application, + * otherwise an + * AlreadyInitializedException will be thrown. + * + * @param modDBName The complete path, relative or absolute, of the + * security module database. + * If it does not exist, it will be created. + * @param keyDBName The complete path, relative or absolute, of the key + * database. It must already exist. + * @param certDBName The complete path, relative or absolute, of the + * certificate database. It must already exist. + * @exception KeyDatabaseException If the key database does not exist + * or cannot be opened. + * @exception CertDatabaseException If the certificate database does + * not exist or cannot be opened. + * @exception AlreadyInitializedException If this method has already + * been called. + * @exception UnsatisfiedLinkError If the implementation dynamic library + * cannot be found or loaded. + */ + public static synchronized void + initialize( String modDBName, String keyDBName, + String certDBName ) + throws KeyDatabaseException, CertDatabaseException, + AlreadyInitializedException + { + if (mNSSInitialized) throw new AlreadyInitializedException(); + + loadNativeLibraries(); + initializeNative(modDBName, + keyDBName, + certDBName, + true, // readOnly + "Netscape Communications Corp ", + "Internal Crypto Services ", + "Internal Crypto Services Token ", + "Internal Key Storage Token ", + "Netscape Internal Cryptographic Services ", + "Netscape Internal Private Key and Certificate Storage ", + "Netscape Internal FIPS-140-1 Cryptographic Services ", + "Netscape Internal FIPS-140-1 Private Key and Certificate Storage "); + + setPasswordCallback( new ConsolePasswordCallback() ); + mNSSInitialized = true; + } + static private boolean mNSSInitialized = false; + + /** + * Indicates whether Java NSS has been initialized. + * + * @return true if initialize has been called, + * false otherwise. + */ + public static synchronized boolean isInitialized() + { + return mNSSInitialized; + } + + private static native void initializeNative( + String modDBName, + String keyDBName, + String certDBName, + boolean readOnly, + String manuString, + String libraryString, + String tokString, + String keyTokString, + String slotString, + String keySlotString, + String fipsString, + String fipsKeyString) + throws KeyDatabaseException, CertDatabaseException, + AlreadyInitializedException; + + /** + * Sets the password callback. + * This password callback will be called when access is required + * to the key database, and to any PKCS #11 token. Once a token + * has been logged into successfully, it is not necessary to login to + * that token again. By default, + * a ConsolePasswordCallback is used to obtain passwords + * from the console. + * + *

This method may be called multiple times to alter the password + * callback. + * + * @see com.netscape.jss.util.PasswordCallback + * @see com.netscape.jss.util.ConsolePasswordCallback + */ + public static synchronized native void + setPasswordCallback(PasswordCallback cb); +} diff --git a/mozilla/security/jss/org/mozilla/jss/manage/NoSuchTokenException.java b/mozilla/security/jss/org/mozilla/jss/manage/NoSuchTokenException.java new file mode 100644 index 00000000000..c23a9baf106 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/manage/NoSuchTokenException.java @@ -0,0 +1,43 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss; + +/** + * Thrown if a token cannot be found. + */ +public class NoSuchTokenException extends java.lang.Exception { + public NoSuchTokenException() {} + public NoSuchTokenException(String mesg) { + super(mesg); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/manage/PK11Finder.c b/mozilla/security/jss/org/mozilla/jss/manage/PK11Finder.c new file mode 100644 index 00000000000..02f20329dbd --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/manage/PK11Finder.c @@ -0,0 +1,1879 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +#include "_jni/com_netscape_jss_CryptoManager.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include "pk11util.h" +#include + + +/***************************************************************** + * + * CryptoManager. f i n d C e r t B y N i c k n a m e N a t i v e + * + */ +JNIEXPORT jobject JNICALL +Java_com_netscape_jss_CryptoManager_findCertByNicknameNative + (JNIEnv *env, jobject this, jstring nickname) +{ + char *nick=NULL; + jobject certObject=NULL; + CERTCertificate *cert=NULL; + + PR_ASSERT(env!=NULL && this!=NULL && nickname!=NULL); + + nick = (char*) (*env)->GetStringUTFChars(env, nickname, NULL); + PR_ASSERT(nick!=NULL); + + cert = PK11_FindCertFromNickname(nick, NULL); + + if(cert == NULL) { + cert = CERT_FindCertByNickname( CERT_GetDefaultCertDB(), nick ); + if( cert == NULL ) { + JSS_nativeThrow(env, OBJECT_NOT_FOUND_EXCEPTION); + goto finish; + } + } + + certObject = JSS_PK11_wrapCert(env, &cert); + +finish: + if(nick != NULL) { + (*env)->ReleaseStringUTFChars(env, nickname, nick); + } + if(cert != NULL) { + CERT_DestroyCertificate(cert); + } + return certObject; +} + +/* + * Creates or adds to a list of all certs with a give nickname, sorted by + * validity time, newest first. Invalid certs are considered older than valid + * certs. If validOnly is set, do not include invalid certs on list. + */ +static CERTCertList * +CreateNicknameCertList(CERTCertList *certList, CERTCertDBHandle *handle, + char *nickname, int64 sorttime, PRBool validOnly) +{ + CERTCertificate *cert; + CERTCertList *ret; + + cert = CERT_FindCertByNickname(handle, nickname); + if ( cert == NULL ) { + cert = PK11_FindCertFromNickname(nickname,NULL); + if( cert == NULL ) { + return NULL; + } + } + + ret = CERT_CreateSubjectCertList(certList, handle, &cert->derSubject, + sorttime, validOnly); + + CERT_DestroyCertificate(cert); + + return(ret); +} + +/***************************************************************** + * + * CryptoManager. f i n d C e r t s B y N i c k n a m e N a t i v e + * + */ +JNIEXPORT jobjectArray JNICALL +Java_com_netscape_jss_CryptoManager_findCertsByNicknameNative + (JNIEnv *env, jobject this, jstring nickname) +{ + CERTCertList *list =NULL; + jobjectArray certArray=NULL; + CERTCertListNode *node; + const char *nickChars=NULL; + jboolean charsAreCopied; + jclass certClass; + int count; + int i; + + /* convert the nickname string */ + nickChars = (*env)->GetStringUTFChars(env, nickname, &charsAreCopied); + if( nickChars == NULL ) { + goto finish; + } + + /* get the list of certs with the given nickname */ + list = CreateNicknameCertList(NULL, CERT_GetDefaultCertDB(), + (char*)nickChars, PR_Now(), PR_FALSE /* validOnly */); + if( list == NULL ) { + count = 0; + } else { + /* Since this structure changed in NSS_2_7_RTM (the reference */ + /* to "count" was removed from the "list" structure) we must */ + /* now count up the number of nodes manually! */ + for( node = CERT_LIST_HEAD(list), count=0; + ! CERT_LIST_END(node, list); + node = CERT_LIST_NEXT(node), count++ ); + } + PR_ASSERT(count >= 0); + + /* create the cert array */ + certClass = (*env)->FindClass(env, X509_CERT_CLASS); + if( certClass == NULL ) { + goto finish; + } + certArray = (*env)->NewObjectArray(env, count, certClass, NULL); + if( certArray == NULL ) { + /* exception was thrown */ + goto finish; + } + + if( list == NULL ) { + goto finish; + } + + /* traverse the list, placing each cert into the array */ + for( node = CERT_LIST_HEAD(list), i=0; + ! CERT_LIST_END(node, list); + node = CERT_LIST_NEXT(node), i++ ) { + + CERTCertificate *cert; + jobject certObj; + + /* Create a Java certificate object from the current CERTCertificate */ + cert = CERT_DupCertificate(node->cert); + certObj = JSS_PK11_wrapCert(env, &cert); + if( certObj == NULL ) { + goto finish; + } + + /* put the Java certificate into the next element in the array */ + (*env)->SetObjectArrayElement(env, certArray, i, certObj); + + if( (*env)->ExceptionOccurred(env) ) { + goto finish; + } + } + + /* sanity check */ + PR_ASSERT( i == count ); + +finish: + if(list) { + CERT_DestroyCertList(list); + } + if( nickChars && charsAreCopied ) { + (*env)->ReleaseStringUTFChars(env, nickname, nickChars); + } + return certArray; +} + +/***************************************************************** + * + * CryptoManager.findCertByIssuerAndSerialNumberNative + * + */ +JNIEXPORT jobject JNICALL +Java_com_netscape_jss_CryptoManager_findCertByIssuerAndSerialNumberNative + (JNIEnv *env, jobject this, jbyteArray issuerBA, jbyteArray serialNumBA) +{ + jobject certObject=NULL; + CERTCertificate *cert=NULL; + SECItem *issuer=NULL, *serialNum=NULL; + CERTIssuerAndSN issuerAndSN; + PK11SlotInfo *slot=NULL; + + PR_ASSERT(env!=NULL && this!=NULL); + + /* validate args */ + if( issuerBA == NULL || serialNumBA == NULL ) { + JSS_throwMsg(env, ILLEGAL_ARGUMENT_EXCEPTION, + "NULL parameter passed to CryptoManager.findCertByIssuer" + "AndSerialNumberNative"); + goto finish; + } + + /* convert byte arrays to SECItems */ + issuer = JSS_ByteArrayToSECItem(env, issuerBA); + if( issuer == NULL ) { + goto finish; } + serialNum = JSS_ByteArrayToSECItem(env, serialNumBA); + if( serialNum == NULL ) { + goto finish; } + issuerAndSN.derIssuer = *issuer; + issuerAndSN.serialNumber = *serialNum; + + /* lookup with PKCS #11 first, then use cert database */ + cert = PK11_FindCertByIssuerAndSN(&slot, &issuerAndSN, NULL /*wincx*/); + if( cert == NULL ) { + cert = CERT_FindCertByIssuerAndSN( + CERT_GetDefaultCertDB(), + &issuerAndSN); + if( cert == NULL ) { + JSS_nativeThrow(env, OBJECT_NOT_FOUND_EXCEPTION); + goto finish; + } + } + + certObject = JSS_PK11_wrapCert(env, &cert); + +finish: + if(slot) { + PK11_FreeSlot(slot); + } + if(cert != NULL) { + CERT_DestroyCertificate(cert); + } + if(issuer) { + SECITEM_FreeItem(issuer, PR_TRUE /*freeit*/); + } + if(serialNum) { + SECITEM_FreeItem(serialNum, PR_TRUE /*freeit*/); + } + return certObject; +} + +/***************************************************************** + * + * CryptoManager. f i n d P r i v K e y B y C e r t N a t i v e + * + */ +JNIEXPORT jobject JNICALL +Java_com_netscape_jss_CryptoManager_findPrivKeyByCertNative + (JNIEnv *env, jobject this, jobject Cert) +{ + PRThread *pThread; + CERTCertificate *cert; + SECKEYPrivateKey *privKey=NULL; + jobject Key; + + pThread = PR_AttachThread(PR_SYSTEM_THREAD, 0, NULL); + PR_ASSERT( pThread != NULL); + PR_ASSERT( env!=NULL && this!=NULL && Cert!=NULL); + + if( JSS_PK11_getCertPtr(env, Cert, &cert) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + goto finish; + } + if(cert==NULL) { + PR_ASSERT(PR_FALSE); + JSS_throw(env, OBJECT_NOT_FOUND_EXCEPTION); + goto finish; + } + + privKey = PK11_FindKeyByAnyCert(cert, NULL); + if(privKey == NULL) { + JSS_throw(env, OBJECT_NOT_FOUND_EXCEPTION); + goto finish; + } + + Key = JSS_PK11_wrapPrivKey(env, &privKey); + +finish: + if(privKey != NULL) { + SECKEY_DestroyPrivateKey(privKey); + } + PR_DetachThread(); + return Key; +} + + +/*********************************************************************** + * Node in linked list of certificates + */ +typedef struct JSScertNode { + struct JSScertNode *next; + CERTCertificate *cert; +} JSScertNode; + + +/*********************************************************************** + * + * c e r t _ c h a i n _ f r o m _ c e r t + * + * Builds a certificate chain from a certificate. Returns a Java array + * of PK11Certs. + * + * INPUTS: + * env + * The JNI environment. Must not be NULL. + * handle + * The certificate database in which to search for the certificate + * chain. This should usually be the default cert db. Must not + * be NULL. + * leaf + * A CERTCertificate that is the leaf of the cert chain. Must not + * be NULL. + * RETURNS: + * NULL if an exception was thrown, or + * A Java array of PK11Cert objects which constitute the chain of + * certificates. The chains starts with the one passed in and + * continues until either a self-signed root is found or the next + * certificate in the chain cannot be found. At least one cert will + * be in the chain: the leaf certificate passed in. + */ +static jobjectArray +cert_chain_from_cert(JNIEnv *env, CERTCertDBHandle *handle, + CERTCertificate *leaf) +{ + CERTCertificate *c; + int i, len = 0; + JSScertNode *head=NULL, *tail, *node; + jobjectArray certArray = NULL; + jclass certClass; + + PR_ASSERT(env!=NULL && handle!=NULL && leaf!=NULL); + + head = tail = (JSScertNode*) PR_CALLOC( sizeof(JSScertNode) ); + if (head == NULL) goto no_memory; + + /* put primary cert first in the linked list */ + head->cert = c = CERT_DupCertificate(leaf); + head->next = NULL; + PR_ASSERT(c != NULL); /* CERT_DupCertificate really can't return NULL */ + len++; + + /* + * add certs until we come to a self-signed one + */ + while(SECITEM_CompareItem(&c->derIssuer, &c->derSubject) != SECEqual) { + c = CERT_FindCertByName(handle, &tail->cert->derIssuer); + if (c == NULL) break; + + tail->next = (JSScertNode*) PR_CALLOC( sizeof(JSScertNode) ); + tail = tail->next; + if (tail == NULL) goto no_memory; + + tail->cert = c; + len++; + } + + /* + * Turn the cert chain into a Java array of certificates + */ + certClass = (*env)->FindClass(env, CERT_CLASS_NAME); + if(certClass==NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + certArray = (*env)->NewObjectArray(env, len, certClass, (jobject)NULL); + if(certArray==NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + /* convert linked list to array, freeing the linked list as we go */ + for( i=0; head != NULL; ++i ) { + jobject certObj; + + node = head; + + PR_ASSERT(i < len); + PR_ASSERT(node->cert != NULL); + + /* Convert C cert to Java cert */ + certObj = JSS_PK11_wrapCert(env, &node->cert); + PR_ASSERT( node->cert == NULL ); + if(certObj == NULL) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL ); + goto finish; + } + + /* Insert Java cert into array */ + (*env)->SetObjectArrayElement(env, certArray, i, certObj); + if( (*env)->ExceptionOccurred(env) ) { + goto finish; + } + + /* Free this list element */ + head = head->next; + PR_Free(node); + } + + goto finish; +no_memory: + JSS_throw(env, OUT_OF_MEMORY_ERROR); +finish: + /* Free the linked list of certs if it hasn't been deleted already */ + while(head != NULL) { + node = head; + head = head->next; + if (node->cert != NULL) { + CERT_DestroyCertificate(node->cert); + } + PR_Free(node); + } + + return certArray; +} + +/***************************************************************** + * + * CryptoManager. b u i l d C e r t i f i c a t e C h a i n N a t i v e + * + * INPUTS: + * env + * The JNI environment. Must not be NULL. + * this + * The PK11Finder object. Must not be NULL. + * leafCert + * A PK11Cert object from which a cert chain will be built. + * Must not be NULL. + * RETURNS: + * NULL if an exception occurred, or + * An array of PK11Certs, the cert chain, with the leaf at the bottom. + * There will always be at least one element in the array (the leaf). + */ +JNIEXPORT jobjectArray JNICALL +Java_com_netscape_jss_CryptoManager_buildCertificateChainNative + (JNIEnv *env, jobject this, jobject leafCert) +{ + PRThread *pThread; + CERTCertificate *leaf; + jobjectArray chainArray=NULL; + CERTCertDBHandle *certdb; + + pThread = PR_AttachThread(PR_SYSTEM_THREAD, 0, NULL); + PR_ASSERT(pThread != NULL); + + PR_ASSERT(env!=NULL && this!=NULL && leafCert!=NULL); + + if( JSS_PK11_getCertPtr(env, leafCert, &leaf) != PR_SUCCESS) { + JSS_throwMsg(env, CERTIFICATE_EXCEPTION, + "Could not extract pointer from PK11Cert"); + goto finish; + } + PR_ASSERT(leaf!=NULL); + + certdb = CERT_GetDefaultCertDB(); + if(certdb == NULL) { + PR_ASSERT(PR_FALSE); + JSS_throwMsg(env, TOKEN_EXCEPTION, + "No default certificate database has been registered"); + goto finish; + } + + /* Get the cert chain */ + chainArray = cert_chain_from_cert(env, certdb, leaf); + if(chainArray == NULL) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + goto finish; + } + +finish: + + PR_DetachThread(); + return chainArray; +} + +/*********************************************************************** + * DERCertCollection + */ +typedef struct { + SECItem *derCerts; + int numCerts; +} DERCertCollection; + +/*********************************************************************** + * c o l l e c t _ c e r t s + * + * Copies certs into a new array. + * + * 'arg' is a pointer to a DERCertCollection structure, which will be filled in. + * 'certs' is an array of pointers to SECItems. + */ +static SECStatus +collect_der_certs(void *arg, SECItem **certs, int numcerts) +{ + int itemsCopied=0; + SECItem *certCopies; /* array of SECItem */ + SECStatus rv; + + PR_ASSERT(arg!=NULL); + + certCopies = PR_MALLOC( sizeof(SECItem) * numcerts); + ((DERCertCollection*)arg)->derCerts = certCopies; + ((DERCertCollection*)arg)->numCerts = numcerts; + if(certCopies == NULL) { + return SECFailure; + } + for(itemsCopied=0; itemsCopied < numcerts; itemsCopied++) { + rv=SECITEM_CopyItem(NULL, &certCopies[itemsCopied], certs[itemsCopied]); + if( rv == SECFailure ) { + goto loser; + } + } + PR_ASSERT(itemsCopied == numcerts); + + return SECSuccess; + +loser: + for(; itemsCopied >= 0; itemsCopied--) { + SECITEM_FreeItem( &certCopies[itemsCopied], PR_FALSE /*freeit*/); + } + PR_Free( certCopies ); + ((DERCertCollection*)arg)->derCerts = NULL; + ((DERCertCollection*)arg)->numCerts = 0; + return SECFailure; +} + +static SECStatus +ImportCAChain(SECItem *certs, int numcerts, SECCertUsage certUsage) +{ + SECStatus rv; + SECItem *derCert; + SECItem certKey; + PRArenaPool *arena; + CERTCertificate *cert = NULL; + CERTCertificate *newcert = NULL; + CERTCertDBHandle *handle; + CERTCertTrust trust; + PRBool isca; + char *nickname; + unsigned int certtype; + + handle = CERT_GetDefaultCertDB(); + + arena = NULL; + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( ! arena ) { + goto loser; + } + + while (numcerts--) { + derCert = certs; + certs++; + + /* get the key (issuer+cn) from the cert */ + rv = CERT_KeyFromDERCert(arena, derCert, &certKey); + if ( rv != SECSuccess ) { + goto loser; + } + + /* same cert already exists in the database, don't need to do + * anything more with it + */ + cert = CERT_FindCertByKey(handle, &certKey); + if ( cert ) { + CERT_DestroyCertificate(cert); + cert = NULL; + continue; + } + + /* decode my certificate */ + newcert = CERT_DecodeDERCertificate(derCert, PR_FALSE, NULL); + if ( newcert == NULL ) { + goto loser; + } + + /* does it have the CA extension */ + + /* + * Make sure that if this is an intermediate CA in the chain that + * it was given permission by its signer to be a CA. + */ + isca = CERT_IsCACert(newcert, &certtype); + + if ( isca ) { + + /* SSL ca's must have the ssl bit set */ + if ( ( certUsage == certUsageSSLCA ) && + ( ( certtype & NS_CERT_TYPE_SSL_CA ) != NS_CERT_TYPE_SSL_CA ) ){ + goto endloop; + } + + /* it passed all of the tests, so lets add it to the database */ + /* mark it as a CA */ + PORT_Memset((void *)&trust, 0, sizeof(trust)); + switch ( certUsage ) { + case certUsageSSLCA: + trust.sslFlags = CERTDB_VALID_CA; + break; + case certUsageUserCertImport: + if ( ( certtype & NS_CERT_TYPE_SSL_CA ) == NS_CERT_TYPE_SSL_CA){ + trust.sslFlags = CERTDB_VALID_CA; + } + if ( ( certtype & NS_CERT_TYPE_EMAIL_CA ) == + NS_CERT_TYPE_EMAIL_CA ) { + trust.emailFlags = CERTDB_VALID_CA; + } + if ( ( certtype & NS_CERT_TYPE_OBJECT_SIGNING_CA ) == + NS_CERT_TYPE_OBJECT_SIGNING_CA ) { + trust.objectSigningFlags = CERTDB_VALID_CA; + } + break; + default: + PORT_Assert(0); + break; + } + } else { + trust.sslFlags = CERTDB_VALID_CA; + trust.emailFlags = CERTDB_VALID_CA; + trust.objectSigningFlags = CERTDB_VALID_CA; + } + + cert = CERT_NewTempCertificate(handle, derCert, NULL, PR_FALSE, + PR_TRUE); + if ( cert == NULL ) { + goto loser; + } + + /* get a default nickname for it */ + nickname = CERT_MakeCANickname(cert); + + rv = CERT_AddTempCertToPerm(cert, nickname, &trust); + /* free the nickname */ + if ( nickname ) { + PORT_Free(nickname); + } + + CERT_DestroyCertificate(cert); + cert = NULL; + + if ( rv != SECSuccess ) { + goto loser; + } + +endloop: + if ( newcert ) { + CERT_DestroyCertificate(newcert); + newcert = NULL; + } + + } + + rv = SECSuccess; + goto done; +loser: + rv = SECFailure; +done: + + if ( newcert ) { + CERT_DestroyCertificate(newcert); + newcert = NULL; + } + + if ( cert ) { + CERT_DestroyCertificate(cert); + cert = NULL; + } + + if ( arena ) { + PORT_FreeArena(arena, PR_FALSE); + } + + return(rv); +} + + +/*********************************************************************** + * CryptoManager.importCertToPerm + * - add the certificate to the permanent database + * + * throws TOKEN_EXCEPTION + */ +JNIEXPORT jobject JNICALL +Java_com_netscape_jss_CryptoManager_importCertToPermNative + (JNIEnv *env, jobject this, jobject cert, jstring nickString) +{ + SECStatus rv; + CERTCertificate *newCert; + CERTCertTrust trustflags; + jobject result=NULL; + char *nickname=NULL; + + /* first, get the NSS cert pointer from the 'cert' object */ + + if ( JSS_PK11_getCertPtr(env, cert, &newCert) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + goto finish; + } + PR_ASSERT(newCert != NULL); + + if (nickString != NULL) { + nickname = (char*) (*env)->GetStringUTFChars(env, nickString, NULL); + } + + trustflags.sslFlags = 0; + trustflags.emailFlags = 0; + trustflags.objectSigningFlags = 0; + + /* Then, add to permanent database */ + + rv = CERT_AddTempCertToPerm(newCert, nickname, + &trustflags); + + if (rv == SECSuccess) { + /* build return object */ + result = JSS_PK11_wrapCert(env, &newCert); + } + else { + /* CERT_AddTempCertToPerm does not properly set NSPR + Error value, so no detail can be retrieved + */ + JSS_throwMsg(env, TOKEN_EXCEPTION, + "Unable to insert certificate into permanent database"); + + + } + if (nickname != NULL) { + (*env)->ReleaseStringUTFChars(env, nickString, nickname); + } + +finish: + return result; + +} + + +/** + * Returns + * -1 if operation error. + * 0 if no leaf found. + * 1 if leaf is found + */ +static int find_leaf_cert( + CERTCertDBHandle *certdb, + SECItem *derCerts, + int numCerts, + int *linked, + int cur_link, + int *leaf_link +) +{ + CERTCertificate *curCert = NULL; + CERTCertificate *theCert = NULL; + int i; + int status = 0; + + theCert= CERT_NewTempCertificate(certdb, &derCerts[cur_link], + NULL, PR_FALSE /* isperm */, PR_TRUE /*copyDER*/); + if (theCert == NULL) { + status = -1; + goto finish; + } + for (i=0; iderSubject, + &curCert->derIssuer) == SECEqual) { + linked[i] = 1; + *leaf_link = i; + status = 1; /* got it */ + goto finish; + } + CERT_DeleteTempCertificate(curCert); + curCert = NULL; + } /* for */ + +finish: + if (theCert != NULL) { + CERT_DeleteTempCertificate(theCert); + } + if (curCert != NULL) { + CERT_DeleteTempCertificate(curCert); + } + return status; +} + +/** + * This function handles unordered certificate chain also. + * Return: + * 1 on success + * 0 otherwise + */ +static int find_leaf_cert_in_chain( + CERTCertDBHandle *certdb, + SECItem *derCerts, + int numCerts, + SECItem *theDerCert +) +{ + int status = 1; + int found; + int i; + int cur_link, leaf_link; + int *linked = NULL; + + linked = PR_Malloc( sizeof(int) * numCerts ); + + /* initialize the bitmap */ + for (i = 0; i < numCerts; i++) { + linked[i] = 0; + } + + /* pick the first cert to start with */ + leaf_link = 0; + cur_link = leaf_link; + linked[leaf_link] = 1; + + while (((found = find_leaf_cert(certdb, + derCerts, numCerts, linked, cur_link, &leaf_link)) == 1)) + { + cur_link = leaf_link; + } + if (found == -1) { + /* the certificate chain is problemtic! */ + status = 0; + goto finish; + } + + *theDerCert = derCerts[leaf_link]; + +finish: + + if (linked != NULL) { + PR_Free(linked); + } + + return status; +} /* find_leaf_cert_in_chain */ + +/*********************************************************************** + * CryptoManager.importCertPackage + */ +JNIEXPORT jobject JNICALL +Java_com_netscape_jss_CryptoManager_importCertPackageNative + (JNIEnv *env, jobject this, jbyteArray packageArray, jstring nickString, + jboolean noUser, jboolean leafIsCA) +{ + SECItem *derCerts=NULL; + int certi= -1; + SECItem theDerCert; + int numCerts; + jbyte *packageBytes=NULL; + jsize packageLen; + SECStatus status; + int i, userCertFound = 0; + DERCertCollection collection; + CERTCertificate *leafCert=NULL; + CERTCertDBHandle *certdb = CERT_GetDefaultCertDB(); + CK_OBJECT_HANDLE keyID; + PK11SlotInfo *slot=NULL; + char *nickChars = NULL; + PRBool certExists = PR_FALSE; + jobject leafObject=NULL; + CERTIssuerAndSN *issuerAndSN; + PLArenaPool *arena=NULL; + int root_cert = -1; + + /*************************************************** + * Validate arguments + ***************************************************/ + PR_ASSERT( env!=NULL && this!=NULL ); + if(packageArray == NULL) { + PR_ASSERT(PR_FALSE); + JSS_throwMsg(env, CERTIFICATE_ENCODING_EXCEPTION, + "Certificate package is NULL"); + goto finish; + } + PR_ASSERT(certdb != NULL); + + /*************************************************** + * Convert package from byte array to jbyte* + ***************************************************/ + packageBytes = (*env)->GetByteArrayElements(env, packageArray, NULL); + if(packageBytes == NULL) { + PR_ASSERT( (*env)->ExceptionOccurred(env) ); + goto finish; + } + packageLen = (*env)->GetArrayLength(env, packageArray); + + /*************************************************** + * Decode package with HCL function + ***************************************************/ + status = CERT_DecodeCertPackage((char*) packageBytes, + (int) packageLen, + collect_der_certs, + (void*) &collection); + if( status != SECSuccess || collection.numCerts < 1 ) { + if( (*env)->ExceptionOccurred(env) == NULL) { + JSS_throwMsg(env, CERTIFICATE_ENCODING_EXCEPTION, + "Security library failed to decode certificate package"); + } + goto finish; + } + derCerts = collection.derCerts; + numCerts = collection.numCerts; + + /*************************************************** + * convert nickname to char* + ***************************************************/ + if(nickString == NULL) { + nickChars = NULL; + } else { + nickChars = (char*) (*env)->GetStringUTFChars(env, nickString, NULL); + } + + /*************************************************** + * user cert can be anywhere in the cert chain. loop and find it. + * The point is to find the user cert with keys on the db, then + * treat the other certs in the chain as CA certs to import. + * The real order of the cert chain shouldn't matter, and shouldn't + * be assumed, and the real location of this user cert in the chain, + * if present, shouldn't be assumed either. + ***************************************************/ + if (numCerts > 1) { + for (certi=0; certiderSubject, + certdb)) + { + JSS_throw(env, NICKNAME_CONFLICT_EXCEPTION); + goto finish; + } + + /*************************************************** + * Import this certificate onto its token. + ***************************************************/ + PK11_FreeSlot(slot); + slot = PK11_ImportCertForKey(leafCert, nickChars, NULL); + if( slot == NULL ) { + /* We already checked for this, shouldn't fail here */ + if(PR_GetError() == SEC_ERROR_ADDING_CERT) { + PR_ASSERT(PR_FALSE); + JSS_throw(env, NO_SUCH_ITEM_ON_TOKEN_EXCEPTION); + } else { + JSS_throw(env, TOKEN_EXCEPTION); + } + goto finish; + } + + if( ! leafIsCA ) { + ++userCertFound; + } + } + + /*************************************************** + * Destroy the leaf cert before calling ImportCAChain. + * If a cert is already present in the temp database, ImportCAChain + * will skip it. So we want to take the leaf cert of the database + * in case it is a CA cert that needs to be properly imported + * by ImportCAChain. + ***************************************************/ + if(leafCert != NULL) { + CERT_DestroyCertificate(leafCert); + leafCert = NULL; + } + + /*************************************************** + * Now add the rest of the certs (which should all be CAs) + ***************************************************/ + if( numCerts-userCertFound>= 1 ) { + SECCertUsage usage; + + if (certi == 0) { + status = ImportCAChain(derCerts+userCertFound, + numCerts-userCertFound, + certUsageUserCertImport); + if(status != SECSuccess) { + JSS_trace(env, JSS_TRACE_ERROR, + "CERT_ImportCAChain returned an error in " + "CryptoManager.importCertPackage."); + JSS_throwMsg(env, CERTIFICATE_ENCODING_EXCEPTION, + "CERT_ImportCAChain returned an error"); + goto finish; + } + } else if (certi == numCerts) { + status = ImportCAChain(derCerts, + numCerts-userCertFound, + certUsageUserCertImport); + if(status != SECSuccess) { + JSS_trace(env, JSS_TRACE_ERROR, + "CERT_ImportCAChain returned an error in " + "CryptoManager.importCertPackage."); + JSS_throwMsg(env, CERTIFICATE_ENCODING_EXCEPTION, + "CERT_ImportCAChain returned an error"); + goto finish; + } + } else { + status = ImportCAChain(derCerts, + certi, + certUsageUserCertImport); + if(status != SECSuccess) { + JSS_trace(env, JSS_TRACE_ERROR, + "CERT_ImportCAChain returned an error in " + "CryptoManager.importCertPackage."); + JSS_throwMsg(env, CERTIFICATE_ENCODING_EXCEPTION, + "CERT_ImportCAChain returned an error"); + goto finish; + } + + status = ImportCAChain(derCerts+certi+1, + numCerts-certi-1, + certUsageUserCertImport); + if(status != SECSuccess) { + JSS_trace(env, JSS_TRACE_ERROR, + "CERT_ImportCAChain returned an error in " + "CryptoManager.importCertPackage."); + JSS_throwMsg(env, CERTIFICATE_ENCODING_EXCEPTION, + "CERT_ImportCAChain returned an error"); + goto finish; + } + + } + + } + + /*************************************************** + * Now lookup the leaf cert and make it into a Java object. + * Apparently, the PK11 lookup checks external tokens first, + * while the CERT lookup checks the database first. If the leaf is + * a CA cert, we want to return the copy in the internal database + * rather than the copy on the token, so we use the CERT call. We + * use the PK11 call for user certs that aren't expected to be CAs + * by the caller. + ***************************************************/ + if(slot && !leafIsCA) { + PK11_FreeSlot(slot); + leafCert = PK11_FindCertByIssuerAndSN(&slot, issuerAndSN, NULL); + } else { + leafCert = CERT_FindCertByIssuerAndSN(certdb, issuerAndSN); + } + PR_ASSERT( leafCert != NULL ); + leafObject = JSS_PK11_wrapCert(env, &leafCert); + +finish: + if(slot!=NULL) { + PK11_FreeSlot(slot); + } + if(derCerts != NULL) { + for(i=0; i < numCerts; i++) { + SECITEM_FreeItem(&derCerts[i], PR_FALSE /*freeit*/); + } + PR_Free(derCerts); + } + if(packageBytes != NULL) { + (*env)->ReleaseByteArrayElements(env, packageArray, packageBytes, + JNI_ABORT); /* don't copy back */ + } + if(leafCert != NULL) { + CERT_DestroyCertificate(leafCert); + } + if(arena != NULL) { + PORT_FreeArena(arena, PR_FALSE); + } + + return leafObject; +} + +/********************************************************************** + * PKCS #7 Encoding data structures + */ +typedef struct BufferNodeStr { + char *data; + unsigned long len; + struct BufferNodeStr *next; +} BufferNode; + +typedef struct { + BufferNode *head; + BufferNode *tail; + unsigned long totalLen; +} EncoderCallbackInfo; + +/********************************************************************** + * c r e a t e E n c o d e r C a l l b a c k I n f o + * + * Constructor for EncoderCallbackInfo structure. + * Returns NULL if it runs out of memory, otherwise a new EncoderCallbackInfo. + */ +static EncoderCallbackInfo* +createEncoderCallbackInfo() +{ + EncoderCallbackInfo *info; + + info = PR_Malloc( sizeof(EncoderCallbackInfo) ); + if( info == NULL ) { + return NULL; + } + info->head = info->tail = NULL; + info->totalLen = 0; + + return info; +} + +/*********************************************************************** + * d e s t r o y E n c o d e r C a l l b a c k I n f o + * + * Destructor for EncoderCallbackInfo structure. + */ +static void +destroyEncoderCallbackInfo(EncoderCallbackInfo *info) +{ + BufferNode *node; + + PR_ASSERT(info != NULL); + + while(info->head != NULL) { + node = info->head; + info->head = info->head->next; + + if(node->data) { + PR_Free(node->data); + } + PR_Free(node); + } + PR_Free(info); +} + +/*********************************************************************** + * e n c o d e r O u t p u t C a l l b a c k + * + * Called by the PKCS #7 encoder whenever output is available. + * Appends the output to a linked list. + */ +static void +encoderOutputCallback( void *arg, const char *buf, unsigned long len) +{ + BufferNode *node; + EncoderCallbackInfo *info; + + /*************************************************** + * validate arguments + ***************************************************/ + PR_ASSERT(arg!=NULL); + info = (EncoderCallbackInfo*) arg; + if(len == 0) { + return; + } + PR_ASSERT(buf != NULL); + + /*************************************************** + * Create a new node to store this information + ***************************************************/ + node = PR_NEW( BufferNode ); + if( node == NULL ) { + PR_ASSERT(PR_FALSE); + goto finish; + } + node->len = len; + node->data = PR_Malloc( len ); + if( node->data == NULL ) { + PR_ASSERT(PR_FALSE); + goto finish; + } + memcpy( node->data, buf, len ); + node->next = NULL; + + /*************************************************** + * Stick the new node onto the end of the list + ***************************************************/ + if( info->head == NULL ) { + PR_ASSERT(info->tail == NULL); + + info->head = info->tail = node; + } else { + PR_ASSERT(info->tail != NULL); + info->tail->next = node; + info->tail = node; + } + node = NULL; + + info->totalLen += len; + +finish: + if(node != NULL) { + if( node->data != NULL) { + PR_Free(node->data); + } + PR_Free(node); + } + return; +} + +/*********************************************************************** + * CryptoManager.exportCertsToPKCS7 + */ +JNIEXPORT jbyteArray JNICALL +Java_com_netscape_jss_CryptoManager_exportCertsToPKCS7 + (JNIEnv *env, jobject this, jobjectArray certArray) +{ + int i, certcount; + SEC_PKCS7ContentInfo *cinfo=NULL; + CERTCertificate *cert; + jclass certClass; + jbyteArray pkcs7ByteArray=NULL; + jbyte *pkcs7Bytes=NULL; + EncoderCallbackInfo *info=NULL; + SECStatus status; + + /************************************************** + * Validate arguments + **************************************************/ + PR_ASSERT(env!=NULL && this!=NULL); + if(certArray == NULL) { + JSS_throw(env, NULL_POINTER_EXCEPTION); + goto finish; + } + + certcount = (*env)->GetArrayLength(env, certArray); + if(certcount < 1) { + JSS_throwMsg(env, CERTIFICATE_ENCODING_EXCEPTION, + "At least one certificate must be passed to exportCertsToPKCS7"); + goto finish; + } + + /* + * JNI ID lookup + */ + certClass = (*env)->FindClass(env, CERT_CLASS_NAME); + if(certClass == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + /*************************************************** + * Add each cert to the PKCS #7 context. Create the context + * for the first cert. + ***************************************************/ + for(i=0; i < certcount; i++) { + jobject certObject; + + certObject = (*env)->GetObjectArrayElement(env, certArray, i); + if( (*env)->ExceptionOccurred(env) != NULL) { + goto finish; + } + PR_ASSERT( certObject != NULL ); + + /* + * Make sure this is a PK11Cert + */ + if( ! (*env)->IsInstanceOf(env, certObject, certClass) ) { + JSS_throwMsg(env, CERTIFICATE_ENCODING_EXCEPTION, + "Certificate was not a PK11 Certificate"); + goto finish; + } + + /* + * Convert it to a CERTCertificate + */ + if( JSS_PK11_getCertPtr(env, certObject, &cert) != PR_SUCCESS) { + JSS_trace(env, JSS_TRACE_ERROR, + "Unable to convert Java certificate to CERTCertificate"); + goto finish; + } + PR_ASSERT(cert != NULL); + + if( i == 0 ) { + /* + * First certificate: create a new PKCS #7 cert-only context + */ + PR_ASSERT(cinfo == NULL); + cinfo = SEC_PKCS7CreateCertsOnly(cert, + PR_FALSE, /* don't include chain */ + NULL /* cert db */ ); + if(cinfo == NULL) { + JSS_throwMsg(env, CERTIFICATE_ENCODING_EXCEPTION, + "Failed to create PKCS #7 encoding context"); + goto finish; + } + } else { + /* + * All remaining certificates: add cert to context + */ + PR_ASSERT(cinfo != NULL); + + if( SEC_PKCS7AddCertificate(cinfo, cert) != SECSuccess ) { + JSS_throwMsg(env, CERTIFICATE_ENCODING_EXCEPTION, + "Failed to add certificate to PKCS #7 encoding context"); + goto finish; + } + } + } + PR_ASSERT( i == certcount ); + PR_ASSERT( cinfo != NULL ); + + /************************************************** + * Encode the PKCS #7 context into its DER encoding + **************************************************/ + info = createEncoderCallbackInfo(); + if(info == NULL) { + JSS_throw(env, OUT_OF_MEMORY_ERROR); + goto finish; + } + + status = SEC_PKCS7Encode(cinfo, + encoderOutputCallback, + (void*)info, + NULL /* bulk key */, + NULL /* password function */, + NULL /* password function arg */ ); + if( status != SECSuccess ) { + JSS_throwMsg(env, CERTIFICATE_ENCODING_EXCEPTION, + "Failed to encode PKCS #7 context"); + } + /* Make sure we got at least some data from the encoder */ + PR_ASSERT(info->totalLen > 0); + PR_ASSERT(info->head != NULL); + + /************************************************** + * Create a new byte array to hold the encoded PKCS #7 + **************************************************/ + pkcs7ByteArray = (*env)->NewByteArray(env, info->totalLen); + if(pkcs7ByteArray == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + pkcs7Bytes = (*env)->GetByteArrayElements(env, pkcs7ByteArray, NULL); + if(pkcs7Bytes == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + /************************************************** + * Copy the PKCS #7 encoding into the byte array + **************************************************/ + { + BufferNode *node; + unsigned long processed=0; + + for(node=info->head; node!=NULL; node = node->next) { + PR_ASSERT(processed < info->totalLen); + PR_ASSERT(node->data != NULL); + PR_ASSERT(node->len > 0); + memcpy(pkcs7Bytes+processed, node->data, node->len); + processed += node->len; + } + PR_ASSERT( processed == info->totalLen ); + } + +finish: + /************************************************** + * Free allocated resources + **************************************************/ + if( cinfo != NULL) { + SEC_PKCS7DestroyContentInfo(cinfo); + } + if(pkcs7Bytes != NULL) { + PR_ASSERT(pkcs7ByteArray != NULL); + (*env)->ReleaseByteArrayElements(env, pkcs7ByteArray, pkcs7Bytes, 0); + } + if( info != NULL ) { + destroyEncoderCallbackInfo(info); + } + + /************************************************** + * Return the PKCS #7 information in a byte array, or NULL if an + * exception occurred + **************************************************/ + PR_ASSERT( (*env)->ExceptionOccurred(env)!=NULL || pkcs7ByteArray!=NULL ); + return pkcs7ByteArray; +} + +/*********************************************************************** + * + * Data structures for traversing certificates in the permanent + * database. + */ +typedef struct CertNode { + CERTCertificate *cert; + struct CertNode *next; +} CertNode; + +typedef struct { + CertNode *head; + CertNode *tail; + int numCACerts; + int numCerts; +} CertCollection; + +/*********************************************************************** + * c o l l e c t _ c e r t s + */ +static SECStatus +collect_certs(CERTCertificate *cert, SECItem *key, void *arg) +{ + CertCollection *collection = (CertCollection*)arg; + CertNode *node; + + PR_ASSERT( collection != NULL); + + node = PR_MALLOC( sizeof(CertNode) ); + if( node == NULL ) { + return SECFailure; + } + + /*************************************************** + * Add the cert to the linked list + ***************************************************/ + /*node->cert = CERT_DupCertificate(cert);*/ + /* + * We need to do it this way because the certs that come into this + * function aren't initialized properly. Many of their fields + * point to data on the stack, and isperm==0. + */ + node->cert = CERT_FindCertByKeyNoLocking(CERT_GetDefaultCertDB(), + &cert->certKey); + + node->next = NULL; + if( collection->head == NULL ) { + PR_ASSERT( collection->tail == NULL ); + collection->head = collection->tail = node; + } else { + PR_ASSERT( collection->tail != NULL ); + collection->tail->next = node; + collection->tail = node; + } + + /*************************************************** + * Count the number of CA certs. + ***************************************************/ + if( CERT_IsCACert(node->cert, NULL) ) { + collection->numCACerts++; + } + collection->numCerts++; + + return SECSuccess; +} + +/*********************************************************************** + * CryptoManager.getCACerts + */ +JNIEXPORT jobjectArray JNICALL +Java_com_netscape_jss_CryptoManager_getCACerts + (JNIEnv *env, jobject this) +{ + CERTCertDBHandle *certdb = CERT_GetDefaultCertDB(); + SECStatus rv; + CertCollection collection = { NULL, NULL, 0}; + jobjectArray certArray = NULL; + CertNode *node; + jclass certClass; + int i; + jobject certObject; + + PR_ASSERT(certdb != NULL); + + /*************************************************** + * Traverse all permanent certificates, building a linked + * list and counting the number of CA certs. + ***************************************************/ + rv = SEC_TraversePermCerts(certdb, collect_certs, (void*) &collection); + if(rv == SECFailure) { + JSS_trace(env, JSS_TRACE_ERROR, + "Traversing permanent certificates failed"); + goto finish; + } + + /************************************************** + * Create array of Java certificates + **************************************************/ + certClass = (*env)->FindClass(env, INTERNAL_CERT_CLASS_NAME); + if(certClass == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + certArray = (*env)->NewObjectArray( env, + collection.numCACerts, + certClass, + NULL ); + if( certArray == NULL ) { + ASSERT_OUTOFMEM(env); + goto finish; + } + PR_ASSERT( (*env)->ExceptionOccurred(env) == NULL ); + + + /************************************************** + * Put all the CA certs in the array + **************************************************/ + i = 0; + while( collection.head != NULL) { + node = collection.head; + + PR_ASSERT(node->cert != NULL); + + /* + * Only add CA certs + */ + if( CERT_IsCACert(node->cert, NULL) ) { + PR_ASSERT( i < collection.numCACerts ); + + certObject = JSS_PK11_wrapCert(env, &(node->cert)); + if( certObject == NULL ) { + goto finish; + } + (*env)->SetObjectArrayElement(env, certArray, i, certObject); + if( (*env)->ExceptionOccurred(env) ) { + goto finish; + } + ++i; + } + + /* + * Delete each node as we traverse it. + */ + collection.head = collection.head->next; + if( node->cert != NULL ) { + CERT_DestroyCertificate(node->cert); + } + PR_Free(node); + } + PR_ASSERT( i == collection.numCACerts ); + +finish: + /* Free any nodes that didn't already get deleted. */ + while( collection.head != NULL ) { + node = collection.head; + collection.head = collection.head->next; + if( node->cert != NULL) { + CERT_DestroyCertificate(node->cert); + } + PR_Free(node); + } + + return certArray; +} + +/*********************************************************************** + * CryptoManager.getPermCerts + */ +JNIEXPORT jobjectArray JNICALL +Java_com_netscape_jss_CryptoManager_getPermCerts + (JNIEnv *env, jobject this) +{ + CERTCertDBHandle *certdb = CERT_GetDefaultCertDB(); + SECStatus rv; + CertCollection collection = { NULL, NULL, 0}; + jobjectArray certArray = NULL; + CertNode *node; + jclass certClass; + int i; + jobject certObject; + + PR_ASSERT(certdb != NULL); + + /*************************************************** + * Traverse all permanent certificates, building a linked + * list and counting the number of CA certs. + ***************************************************/ + rv = SEC_TraversePermCerts(certdb, collect_certs, (void*) &collection); + if(rv == SECFailure) { + JSS_trace(env, JSS_TRACE_ERROR, + "Traversing permanent certificates failed"); + goto finish; + } + + /************************************************** + * Create array of Java certificates + **************************************************/ + certClass = (*env)->FindClass(env, INTERNAL_CERT_CLASS_NAME); + if(certClass == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + certArray = (*env)->NewObjectArray( env, + collection.numCerts, + certClass, + NULL ); + if( certArray == NULL ) { + ASSERT_OUTOFMEM(env); + goto finish; + } + PR_ASSERT( (*env)->ExceptionOccurred(env) == NULL ); + + + /************************************************** + * Put all the certs in the array + **************************************************/ + i = 0; + while( collection.head != NULL) { + node = collection.head; + + PR_ASSERT(node->cert != NULL); + + PR_ASSERT( i < collection.numCerts ); + + certObject = JSS_PK11_wrapCert(env, &(node->cert)); + if( certObject == NULL ) { + goto finish; + } + (*env)->SetObjectArrayElement(env, certArray, i, certObject); + if( (*env)->ExceptionOccurred(env) ) { + goto finish; + } + ++i; + + /* + * Delete each node as we traverse it. + */ + collection.head = collection.head->next; + if( node->cert != NULL ) { + CERT_DestroyCertificate(node->cert); + } + PR_Free(node); + } + PR_ASSERT( i == collection.numCerts ); + +finish: + /* Free any nodes that didn't already get deleted. */ + while( collection.head != NULL ) { + node = collection.head; + collection.head = collection.head->next; + if( node->cert != NULL) { + CERT_DestroyCertificate(node->cert); + } + PR_Free(node); + } + + return certArray; +} + + + + /* Imports a CRL, and stores it into the cert7.db + * + * @param the DER-encoded CRL. + */ + + +JNIEXPORT void JNICALL +Java_com_netscape_jss_CryptoManager_importCRLNative + (JNIEnv *env, jobject this, + jbyteArray der_crl, jstring url_jstr, jint rl_type) + +{ + CERTCertDBHandle *certdb = CERT_GetDefaultCertDB(); + jbyte *packageBytes=NULL; + jsize packageLen; + CERTSignedCrl *crl = NULL; + SECItem *packageItem = NULL; + int status = SECFailure; + char *url; + char *errmsg = NULL; + + /*************************************************** + * Validate arguments + ***************************************************/ + PR_ASSERT( env!=NULL && this!=NULL ); + if(der_crl == NULL) { + PR_ASSERT(PR_FALSE); + /* XXX need new exception here */ + JSS_throwMsg(env, CERTIFICATE_ENCODING_EXCEPTION, + "CRL package is NULL"); + goto finish; + } + PR_ASSERT(certdb != NULL); + + /* convert CRL byte[] into secitem */ + + packageItem = JSS_ByteArrayToSECItem(env, der_crl); + if ( packageItem == NULL ) { + goto finish; + } + /* XXX need to deal with if error */ + + if (url_jstr != NULL) { + url = (char*) (*env)->GetStringUTFChars(env, url_jstr, NULL); + PR_ASSERT(url!=NULL); + } + else { + url = NULL; + } + + crl = CERT_ImportCRL( certdb, packageItem, url, rl_type, NULL); + + if( crl == NULL ) { + status = PR_GetError(); + errmsg = NULL; + switch (status) { + case SEC_ERROR_OLD_CRL: + case SEC_ERROR_OLD_KRL: + /* not an error - leave as NULL */ + errmsg = NULL; + goto finish; + case SEC_ERROR_CRL_EXPIRED: + errmsg = "CRL Expired"; + break; + case SEC_ERROR_KRL_EXPIRED: + errmsg = "KRL Expired"; + break; + case SEC_ERROR_CRL_NOT_YET_VALID: + errmsg = "CRL Not yet valid"; + break; + case SEC_ERROR_KRL_NOT_YET_VALID: + errmsg = "KRL Not yet valid"; + break; + case SEC_ERROR_CRL_INVALID: + errmsg = "Invalid encoding of CRL"; + break; + case SEC_ERROR_KRL_INVALID: + errmsg = "Invalid encoding of KRL"; + break; + case SEC_ERROR_BAD_DATABASE: + errmsg = "Database error"; + break; + default: + /* printf("NSS ERROR = %d\n",status); */ + errmsg = "Failed to import Revocation List"; + } + if (errmsg) { + JSS_throwMsg(env, CRL_IMPORT_EXCEPTION, errmsg); + } + } + +finish: + + if (packageItem) { + SECITEM_FreeItem(packageItem, PR_TRUE /*freeit*/); + } + + if(url != NULL) { + (*env)->ReleaseStringUTFChars(env, url_jstr, url); + } + + if (crl) { + SEC_DestroyCrl(crl); + } +} + + diff --git a/mozilla/security/jss/org/mozilla/jss/manage/config.mk b/mozilla/security/jss/org/mozilla/jss/manage/config.mk new file mode 100644 index 00000000000..bb088a7f0ca --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/manage/config.mk @@ -0,0 +1,72 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +####################################################################### +# Set the LD_LIBS value to encompass all static JSS, security, and # +# dbm libraries # +####################################################################### + +LD_LIBS += $(LIBSVRPLCY) \ + $(LIBJSSPOLICY) \ + $(LIBJSSPKCS11) \ + $(LIBJSSCRYPTO) \ + $(LIBJSSUTIL) \ + $(LIBJSSHCLHACKS) \ + $(LIBPKCS7) \ + $(LIBSSL) \ + $(LIBSECMOD) \ + $(LIBCERT) \ + $(LIBKEY) \ + $(LIBCRYPTO) \ + $(LIBHASH) \ + $(LIBSECUTIL) \ + $(LIBDBM) \ + $(NULL) + +####################################################################### +# Append additional LD_LIBS value to encompass all dynamic NSPR 2.0, # +# java, and system libraries # +####################################################################### + +ifeq ($(OS_ARCH), WINNT) + LD_LIBS += $(JAVA_LIBS) $(DLLPLDS) $(DLLPLC) $(DLLPR) $(DLLSYSTEM) +else + LD_LIBS += $(JAVA_LIBS) -L$(SOURCE_LIB_DIR) -lplds3 -lplc3 -lnspr3 $(DLLSYSTEM) +endif + +####################################################################### +# Turn off any Export Control Policy for these libraries # +####################################################################### + +POLICY = + diff --git a/mozilla/security/jss/org/mozilla/jss/manage/jssinit.h b/mozilla/security/jss/org/mozilla/jss/manage/jssinit.h new file mode 100644 index 00000000000..e65fb3f0467 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/manage/jssinit.h @@ -0,0 +1,95 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +/* This header depends on: +#include +#include +*/ +#include "svrplcy.h" + +#ifndef JSS_INIT_H +#define JSS_INIT_H + +/*********************************************************************** + * JSS_completeInitialize + * + * Initialize the security library and open all the databases. + * + */ +PR_EXTERN( void ) +JSS_completeInitialize(JNIEnv *env, + jstring modDBName, + jstring keyDBName, + jstring certDBName, + jboolean readOnly, + jstring manuString, + jstring libraryString, + jstring tokString, + jstring keyTokString, + jstring slotString, + jstring keySlotString, + jstring fipsString, + jstring fipsKeyString, + jboolean ocspCheckingEnabled, + jstring ocspResponderURL, + jstring ocspResponderCertNickname ); + + +/********************************************************************** + * + * JSS_setPasswordCallback + * + * Sets the global PasswordCallback object, which will be used to + * login to tokens implicitly if necessary. + * + */ +PR_EXTERN( void ) +JSS_setPasswordCallback(JNIEnv *env, jobject callback); + + +/*********************************************************************** + * JSS_isDomestic + * + * Returns true if this build of jssjava is "domestic", false otherwise. + */ +PR_EXTERN( PRBool ) +JSS_isDomestic( void ); + +/*********************************************************************** + * JSS_getExportControlPolicyType + * + * Returns the export control policy type + */ +PR_EXTERN( SVRPLCYPolicyType ) +JSS_getExportControlPolicyType( void ); + +#endif diff --git a/mozilla/security/jss/org/mozilla/jss/manage/manifest.mn b/mozilla/security/jss/org/mozilla/jss/manage/manifest.mn new file mode 100644 index 00000000000..a11f2e7f827 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/manage/manifest.mn @@ -0,0 +1,76 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# +CORE_DEPTH = ../../../../.. + +MODULE = ninja + +NS_USE_JDK = 1 + +REQUIRES = nspr20 svrcore dbm security + +PACKAGE = com/netscape/jss + +JNI_GEN = \ + com.netscape.jss.DatabaseCloser \ + com.netscape.jss.CryptoManager \ + com.netscape.jss.NSSInit \ + $(NULL) + +CLASSES = \ + CertDatabaseException \ + CRLImportException \ + CryptoManager \ + KeyDatabaseException \ + NoSuchTokenException \ + NSSInit \ + DatabaseCloser \ + $(NULL) + +JSRCS = \ + CertDatabaseException.java \ + CRLImportException.java \ + CryptoManager.java \ + KeyDatabaseException.java \ + NoSuchTokenException.java \ + NSSInit.java \ + DatabaseCloser.java \ + $(NULL) + +CSRCS = \ + CryptoManager.c \ + PK11Finder.c \ + NSSInit.c \ + $(NULL) + + +LIBRARY_NAME = jssmanage diff --git a/mozilla/security/jss/org/mozilla/jss/manifest.mn b/mozilla/security/jss/org/mozilla/jss/manifest.mn new file mode 100644 index 00000000000..94772a0ce6d --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/manifest.mn @@ -0,0 +1,53 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +CORE_DEPTH = ../../../.. + +MODULE = ninja + +DIRS = hclhacks\ + policy \ + util \ + asn1 \ + crypto \ + pkcs11 \ + provider \ + manage \ + pkix/primitive \ + pkcs10 \ + pkix \ + pkcs7 \ + pkcs12 \ + ssl \ + tests \ + $(NULL) diff --git a/mozilla/security/jss/org/mozilla/jss/package.html b/mozilla/security/jss/org/mozilla/jss/package.html new file mode 100644 index 00000000000..39a24f925eb --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/package.html @@ -0,0 +1,37 @@ + + + +Configuration and top-level operations of the JSS system. + + diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs10/CertificationRequest.java b/mozilla/security/jss/org/mozilla/jss/pkcs10/CertificationRequest.java new file mode 100644 index 00000000000..19c907d75fa --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs10/CertificationRequest.java @@ -0,0 +1,341 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs10; + +import com.netscape.jss.asn1.*; +import com.netscape.jss.pkix.primitive.*; +import com.netscape.jss.crypto.*; +import com.netscape.jss.CryptoManager; +import java.security.cert.CertificateException; +import java.security.NoSuchAlgorithmException; +import java.security.InvalidKeyException; +import java.security.SignatureException; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; +import java.security.PublicKey; +import java.security.KeyPair; +import java.util.Date; +import java.util.Calendar; + +import java.io.BufferedInputStream; +import java.io.FileInputStream; + +/** + * A pkcs10 signed CertificationRequest. + */ +public class CertificationRequest implements ASN1Value { + + private CertificationRequestInfo info; + private byte[] infoEncoding; + private byte[] signature; + private AlgorithmIdentifier algId; + SEQUENCE sequence; + + private CertificationRequest() { } + + CertificationRequest(CertificationRequestInfo info, + //byte[] infoEncoding, + AlgorithmIdentifier algId, byte[] signature) throws IOException + { + this.info = info; + //this.infoEncoding = infoEncoding; + this.algId = algId; + this.signature = signature; + + // bundle everything into a SEQUENCE + sequence = new SEQUENCE(); + sequence.addElement( info ); + sequence.addElement( algId ); + sequence.addElement( new BIT_STRING( signature, 0 ) ); + } + + /** + * Creates and signs an X.509 CertificationRequest. + * @param info A CertificationRequestInfo (TBSCertificationRequest), + * which specifies + * the actual information of the CertificationRequest. + * @param privKey The private key with which to sign the certificat. + * @param signingAlg The algorithm to use to sign the CertificationRequest. + * It must match the algorithm specified in the CertificationRequestInfo. + * @exception IOException If an error occurred while encoding the + * CertificationRequest. + * @exception CryptoManager.NotInitializedException Because this + * operation involves cryptography (signing), CryptoManager must + * be initialized before calling it. + * @exception TokenException If an error occurs on a PKCS #11 token. + * @exception NoSuchAlgorithmException If the OID for the signing algorithm + * cannot be located. + * @exception CertificateException If the signing algorithm specified + * as a parameter does not match the one in the CertificationRequest info. + * @exception InvalidKeyException If the key does not match the signing + * algorithm. + * @exception SignatureException If an error occurs while signing the + * CertificationRequest. + */ + public CertificationRequest(CertificationRequestInfo info, java.security.PrivateKey privKey, + SignatureAlgorithm signingAlg) + throws IOException, CryptoManager.NotInitializedException, + TokenException, NoSuchAlgorithmException, CertificateException, + InvalidKeyException, SignatureException + { + // make sure key is a Ninja private key + if( !(privKey instanceof PrivateKey) ) { + throw new InvalidKeyException("Private Key is does not belong to"+ + " this provider"); + } + PrivateKey priv = (PrivateKey)privKey; + + // create algId + if(signingAlg.getSigningAlg() == SignatureAlgorithm.RSASignature) { + algId = new AlgorithmIdentifier( signingAlg.toOID(), null ); + } else { + algId = new AlgorithmIdentifier( signingAlg.toOID() ); + } + + // encode the cert info + this.info = info; + infoEncoding = ASN1Util.encode(info); + + // sign the info encoding + CryptoManager cm = CryptoManager.getInstance(); + CryptoToken token = priv.getOwningToken(); + Signature sig = token.getSignatureContext(signingAlg); + sig.initSign(priv); + sig.update(infoEncoding); + signature = sig.sign(); + + // bundle everything into a SEQUENCE + sequence = new SEQUENCE(); + sequence.addElement( info ); + sequence.addElement( algId ); + sequence.addElement( new BIT_STRING( signature, 0 ) ); + } + + /** + * Verifies the signature on this CertificationRequest. Does not indicate + * that the CertificationRequest is valid at any specific time. + */ + public void verify() + throws InvalidKeyException, CryptoManager.NotInitializedException, + NoSuchAlgorithmException, CertificateException, TokenException, + SignatureException, InvalidKeyFormatException + { + verify( info.getSubjectPublicKeyInfo().toPublicKey() ); + } + + /** + * Verifies the signature on this CertificationRequest, using the given public key. + * Does not indicate the CertificationRequest is valid at any specific time. + */ + public void verify(PublicKey key) + throws InvalidKeyException, CryptoManager.NotInitializedException, + NoSuchAlgorithmException, CertificateException, TokenException, + SignatureException + { + CryptoManager cm = CryptoManager.getInstance(); + verify(key, cm.getInternalCryptoToken()); + } + + /** + * Verifies the signature on this CertificationRequest, using the given public + * key and CryptoToken. Does not indicate the CertificationRequest is valid at + * any specific time. + */ + public void verify(PublicKey key, CryptoToken token) + throws NoSuchAlgorithmException, CertificateException, TokenException, + SignatureException, InvalidKeyException + { + Signature sig = token.getSignatureContext( + SignatureAlgorithm.fromOID( algId.getOID() ) ); + + sig.initVerify(key); + sig.update(infoEncoding); + if( ! sig.verify(signature) ) { + throw new CertificateException("Signature is invalid"); + } + } + + + /** + * Returns the information (TBSCertificationRequest) contained in this CertificationRequest. + */ + public CertificationRequestInfo getInfo() { + return info; + } + + private static final Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + encode(TAG, ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + sequence.encode(implicitTag, ostream); + } + + private static final Template templateInstance = new Template(); + public static Template getTemplate() { + return templateInstance; + } + + public static class Template implements ASN1Template { + + private SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + seqt.addElement( CertificationRequestInfo.getTemplate() ); + //seqt.addElement( new ANY.Template() ); + seqt.addElement( AlgorithmIdentifier.getTemplate() ); + seqt.addElement( BIT_STRING.getTemplate() ); + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws InvalidBERException, IOException + { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws InvalidBERException, IOException + { + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); + + //ANY infoAny = (ANY)seq.elementAt(0); + //byte[] infoEncoding = infoAny.getEncoded(); + /*CertificationRequestInfo info = (CertificationRequestInfo) infoAny.decodeWith( + CertificationRequestInfo.getTemplate() ); + */ + CertificationRequestInfo info = (CertificationRequestInfo) seq.elementAt(0); + // although signature is a bit string, all algorithms we use + // will produce an octet string. + BIT_STRING bs = (BIT_STRING) seq.elementAt(2); + if( bs.getPadCount() != 0 ) { + throw new InvalidBERException("signature does not fall into"+ + " an integral number of bytes"); + } + byte[] signature = bs.getBits(); + + return new CertificationRequest( info, + //infoEncoding, + (AlgorithmIdentifier) seq.elementAt(1), + signature + ); + } + } + + public static void main(String argv[]) { + + try { + + if(argv.length > 2 || argv.length < 1) { + System.out.println("Usage: CertificationRequest []"); + System.exit(0); + } + + CryptoManager.initialize( argv[0]+"/secmod.db", argv[0]+"/key3.db", + argv[0]+"/cert7.db"); + CryptoManager cm = CryptoManager.getInstance(); + + // read in a cert + BufferedInputStream bis = new BufferedInputStream( + new FileInputStream(argv[1]) ); + + CertificationRequest cert = (CertificationRequest) + CertificationRequest.getTemplate().decode(bis); + + CertificationRequestInfo info = cert.getInfo(); + + info.print(System.out); + + //X509CertificationRequest hardcore = cm.findCertByNickname("Hardcore"); + //PublicKey key = hardcore.getPublicKey(); + + cert.verify(); + System.out.println("verified"); + + FileOutputStream fos = new FileOutputStream("certinfo.der"); + info.encode(fos); + fos.close(); + + // make a new public key + CryptoToken token = cm.getInternalKeyStorageToken(); + KeyPairGenerator kpg = token.getKeyPairGenerator(KeyPairAlgorithm.RSA); + kpg.initialize(512); + System.out.println("Generating a new key pair..."); + KeyPair kp = kpg.genKeyPair(); + System.out.println("Generated key pair"); + + // set the CertificationRequest's public key + info.setSubjectPublicKeyInfo(kp.getPublic()); + + // make new Name + Name name = new Name(); + name.addCommonName("asldkj\u00dsdlkfj\u00e"); + name.addCountryName("US"); + name.addOrganizationName("Some Corp"); + name.addOrganizationalUnitName("Some Org Unit"); + name.addLocalityName("Silicon Valley"); + name.addStateOrProvinceName("California"); + info.setSubject(name); + + System.out.println("About to create a new cert request..."); + // create a new cert requestfrom this certReqinfo + CertificationRequest genCert = new CertificationRequest(info, kp.getPrivate(), + SignatureAlgorithm.RSASignatureWithMD5Digest); + System.out.println("Created new cert request"); + + genCert.verify(); + System.out.println("Cert verifies!"); + + fos = new FileOutputStream("gencert.der"); + genCert.encode(fos); + fos.close(); + + } catch( Exception e ) { + e.printStackTrace(); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs10/CertificationRequestInfo.java b/mozilla/security/jss/org/mozilla/jss/pkcs10/CertificationRequestInfo.java new file mode 100644 index 00000000000..f0f21c7cb26 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs10/CertificationRequestInfo.java @@ -0,0 +1,207 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.pkcs10; + +import com.netscape.jss.asn1.*; +import com.netscape.jss.pkix.primitive.*; +import com.netscape.jss.util.*; +import java.security.cert.CertificateException; +import java.security.PublicKey; +import java.util.Calendar; +import java.util.Date; +import java.util.TimeZone; +import java.io.InputStream; +import java.io.PrintStream; +import java.io.OutputStream; +import java.io.IOException; + +/** + * A TBSCertificationRequest (to-be-signed CertificationRequest), + * the actual information in + * a CertificationRequest apart from the signature. + */ +public class CertificationRequestInfo implements ASN1Value { + + + private INTEGER version = new INTEGER(0); + private Name subject; + private SubjectPublicKeyInfo subjectPublicKeyInfo; + private SET attributes; + + /** + * Creates a CertificationRequestInfo with the required fields. + */ + public CertificationRequestInfo(INTEGER version, Name subject, + SubjectPublicKeyInfo + subjectPublicKeyInfo, SET attributes) + { + setVersion(version); + setSubject(subject); + setSubjectPublicKeyInfo(subjectPublicKeyInfo); + setAttributes(attributes); + } + + public void setVersion(INTEGER version) { + verifyNotNull(version); + this.version = version; + } + public INTEGER getVersion() { + return version; + } + + public void setSubject(Name subject) { + verifyNotNull(subject); + this.subject = subject; + } + public Name getSubject() { + return subject; + } + + public void setSubjectPublicKeyInfo( + SubjectPublicKeyInfo subjectPublicKeyInfo) + { + verifyNotNull(subjectPublicKeyInfo); + this.subjectPublicKeyInfo = subjectPublicKeyInfo; + } + /** + * Extracts the SubjectPublicKeyInfo from the given public key and + * stores it in the CertificationRequestInfo. + * + * @exception InvalidBERException If an error occurs decoding the + * the information extracted from the public key. + */ + public void setSubjectPublicKeyInfo( PublicKey pubk ) + throws InvalidBERException, IOException + { + verifyNotNull(pubk); + setSubjectPublicKeyInfo( new SubjectPublicKeyInfo(pubk) ); + } + public SubjectPublicKeyInfo getSubjectPublicKeyInfo() { + return subjectPublicKeyInfo; + } + + public void setAttributes(SET attributes) { + //verifyNotNull(attributes); + this.attributes = attributes; + } + public SET getAttributes() { + return attributes; + } + + private void verifyNotNull(Object obj) { + if( obj == null ) { + throw new NullPointerException(); + } + } + + static final Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + encode(TAG, ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + SEQUENCE seq = new SEQUENCE(); + + seq.addElement(version ); + seq.addElement(subject); + seq.addElement(subjectPublicKeyInfo); + seq.addElement(new Tag(0), attributes); + + seq.encode(implicitTag, ostream); + } + + private static final Template templateInstance = new Template(); + public static Template getTemplate() { + return templateInstance; + } + + public void print(PrintStream ps) throws IOException, InvalidBERException { + ps.println("CertificationRequestInfo:"); + ps.println("Version: "+version); + ps.println("Subject: "+subject.getRFC1485()); + } + + /** + * Template class for decoding a CertificationRequestInfo. + */ + public static class Template implements ASN1Template { + + SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + + seqt.addElement(INTEGER.getTemplate()); //version + seqt.addElement(Name.getTemplate()); //subject + seqt.addElement(SubjectPublicKeyInfo.getTemplate()); + seqt.addElement(Tag.get(0), new SET.OF_Template(Attribute.getTemplate())); + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws InvalidBERException, IOException + { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws InvalidBERException, IOException + { + try { + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); + + + CertificationRequestInfo cinfo = new CertificationRequestInfo( + (INTEGER) seq.elementAt(0), // version + (Name) seq.elementAt(1), // subject + (SubjectPublicKeyInfo) seq.elementAt(2), + (SET) seq.elementAt(3) + ); + + return cinfo; + + } catch( Exception e ) { + throw new InvalidBERException(e.getMessage()); + } + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs10/Makefile b/mozilla/security/jss/org/mozilla/jss/pkcs10/Makefile new file mode 100644 index 00000000000..8e7b071acaf --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs10/Makefile @@ -0,0 +1,75 @@ +#! gmake +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +####################################################################### +# (1) Include initial platform-independent assignments (MANDATORY). # +####################################################################### + +include manifest.mn + +####################################################################### +# (2) Include "global" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/config.mk + +####################################################################### +# (3) Include "component" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/$(MODULE)/config/config.mk + + +####################################################################### +# (4) Include "local" platform-dependent assignments (OPTIONAL). # +####################################################################### +#include config.mk + + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### +#include rules.mk diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs10/manifest.mn b/mozilla/security/jss/org/mozilla/jss/pkcs10/manifest.mn new file mode 100644 index 00000000000..6d48feb62b1 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs10/manifest.mn @@ -0,0 +1,67 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +CORE_DEPTH = ../../../../.. + +MODULE = ninja + +NS_USE_JDK = 1 + +PACKAGE = com/netscape/jss/pkcs10 + +# These are meant to be used within Ninja only. +PRIVATE_EXPORTS = \ + $(NULL) + +JNI_GEN = \ + $(NULL) + +CLASSES = \ + CertificationRequest \ + CertificationRequestInfo \ + $(NULL) + +PRIVATE_CLASSES = \ + $(NULL) + + +JSRCS = \ + CertificationRequest.java \ + CertificationRequestInfo.java \ + $(NULL) + +PRIVATE_JSRCS = + + +CSRCS = \ + $(NULL) diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs10/package.html b/mozilla/security/jss/org/mozilla/jss/pkcs10/package.html new file mode 100644 index 00000000000..84cd73a800d --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs10/package.html @@ -0,0 +1,37 @@ + + + +Encoding and decoding pkcs10 request + + diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/CipherContextProxy.java b/mozilla/security/jss/org/mozilla/jss/pkcs11/CipherContextProxy.java new file mode 100644 index 00000000000..b2855fc3485 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/CipherContextProxy.java @@ -0,0 +1,44 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs11; + +import com.netscape.jss.util.NativeProxy; + +final class CipherContextProxy extends NativeProxy { + public CipherContextProxy(byte[] pointer) { + super(pointer); + } + + protected native void releaseNativeResources(); +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/KeyProxy.java b/mozilla/security/jss/org/mozilla/jss/pkcs11/KeyProxy.java new file mode 100644 index 00000000000..617c83036fe --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/KeyProxy.java @@ -0,0 +1,44 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.pkcs11; + +abstract class KeyProxy extends com.netscape.jss.util.NativeProxy { + + protected KeyProxy(byte[] pointer) { + super(pointer); + } + + protected void finalize() throws Throwable { + super.finalize(); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/KeyType.java b/mozilla/security/jss/org/mozilla/jss/pkcs11/KeyType.java new file mode 100644 index 00000000000..626c6b0396d --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/KeyType.java @@ -0,0 +1,219 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs11; + +import com.netscape.jss.crypto.Algorithm; +import com.netscape.jss.crypto.HMACAlgorithm; +import java.util.Hashtable; +import com.netscape.jss.util.*; +import java.security.NoSuchAlgorithmException; +import com.netscape.jss.crypto.SignatureAlgorithm; +import com.netscape.jss.crypto.KeyWrapAlgorithm; +import com.netscape.jss.crypto.EncryptionAlgorithm; + +/** + * PKCS #11 Key Types + * These are the possible types for keys in the + * wrapper library. + * Key types are implemented as flyweights. +**/ +final class KeyType { + protected KeyType() {} + + protected KeyType(Algorithm[] algs, String name) { + int i; + + Assert.assert(algs!=null); + + algorithms = (Algorithm[]) algs.clone(); + + // Register this key as the key type for each of its algorithms + for(i=0; i < algorithms.length; i++) { + Assert.assert(! algHash.containsKey(algorithms[i]) ); + algHash.put(algorithms[i], this); + } + this.name = name; + } + + /** + * Returns an array of algorithms supported by this key type. + */ + public Algorithm[] supportedAlgorithms() { + return algorithms; + } + + /** + * Returns the KeyType corresponding to the given Algorithm. If there + * is no KeyType registered for this algorithm, a NoSuchAlgorithmException + * is thrown. + */ + static public KeyType getKeyTypeFromAlgorithm(Algorithm alg) + throws NoSuchAlgorithmException + { + Assert.assert(alg!=null); + Object obj = algHash.get(alg); + + if(obj == null) { + throw new NoSuchAlgorithmException(); + } + + Assert.assert( obj instanceof KeyType ); + + return (KeyType) obj; + } + + + + ////////////////////////////////////////////////////////////// + // Instance Data + ////////////////////////////////////////////////////////////// + + // An array of algorithms supported by this key type + protected Algorithm[] algorithms; + + protected String name; + + + ////////////////////////////////////////////////////////////// + // Class Data + ////////////////////////////////////////////////////////////// + + // A hash table associating a key type with each algorithm + static protected Hashtable algHash; + static { + algHash = new Hashtable(); + } + + + + + ////////////////////////////////////////////////////////////// + // Key Types + ////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////// + static public final KeyType + NULL = new KeyType(new Algorithm[0], "NULL"); + + ////////////////////////////////////////////////////////////// + static public final KeyType + RSA = new KeyType (new Algorithm[] + { + SignatureAlgorithm.RSASignature, + SignatureAlgorithm.RSASignatureWithMD2Digest, + SignatureAlgorithm.RSASignatureWithMD5Digest, + SignatureAlgorithm.RSASignatureWithSHA1Digest, + KeyWrapAlgorithm.RSA + }, + "RSA" + ); + + ////////////////////////////////////////////////////////////// + static public final KeyType + DSA = new KeyType(new Algorithm[] + { + SignatureAlgorithm.DSASignature, + SignatureAlgorithm.DSASignatureWithSHA1Digest + }, + "DSA" + ); + + ////////////////////////////////////////////////////////////// + static public final KeyType + FORTEZZA = new KeyType(new Algorithm[0], "FORTEZZA"); + + ////////////////////////////////////////////////////////////// + static public final KeyType + DH = new KeyType(new Algorithm[0], "DH"); + + ////////////////////////////////////////////////////////////// + static public final KeyType + KEA = new KeyType(new Algorithm[0], "KEA"); + + ////////////////////////////////////////////////////////////// + static public final KeyType + DES = new KeyType(new Algorithm[] + { + KeyWrapAlgorithm.DES_ECB, + KeyWrapAlgorithm.DES_CBC, + KeyWrapAlgorithm.DES_CBC_PAD, + EncryptionAlgorithm.DES_ECB, + EncryptionAlgorithm.DES_CBC, + EncryptionAlgorithm.DES_CBC_PAD + }, + "DES" + ); + + ////////////////////////////////////////////////////////////// + static public final KeyType + DES3 = new KeyType(new Algorithm[] + { + KeyWrapAlgorithm.DES3_ECB, + KeyWrapAlgorithm.DES3_CBC, + KeyWrapAlgorithm.DES3_CBC_PAD, + EncryptionAlgorithm.DES3_ECB, + EncryptionAlgorithm.DES3_CBC, + EncryptionAlgorithm.DES3_CBC_PAD + }, + "DES" + ); + + ////////////////////////////////////////////////////////////// + static public final KeyType + RC4 = new KeyType(new Algorithm[] + { + EncryptionAlgorithm.RC4 + }, + "RC4" + ); + + ////////////////////////////////////////////////////////////// + static public final KeyType + RC2 = new KeyType(new Algorithm[] + { + EncryptionAlgorithm.RC2_CBC + }, + "RC2" + ); + + ////////////////////////////////////////////////////////////// + static public final KeyType + SHA1_HMAC = new KeyType(new Algorithm[] + { + HMACAlgorithm.SHA1 + }, + "SHA1_HMAC" + ); + +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/Makefile b/mozilla/security/jss/org/mozilla/jss/pkcs11/Makefile new file mode 100644 index 00000000000..9b72e07f79e --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/Makefile @@ -0,0 +1,76 @@ +#! gmake +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +####################################################################### +# (1) Include initial platform-independent assignments (MANDATORY). # +####################################################################### + +include manifest.mn + +####################################################################### +# (2) Include "global" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/config.mk + +####################################################################### +# (3) Include "component" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/$(MODULE)/config/config.mk + +####################################################################### +# (4) Include "local" platform-dependent assignments (OPTIONAL). # +####################################################################### + +include config.mk + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### + + + diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/ModuleProxy.java b/mozilla/security/jss/org/mozilla/jss/pkcs11/ModuleProxy.java new file mode 100644 index 00000000000..f0bc5ace4d5 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/ModuleProxy.java @@ -0,0 +1,48 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs11; + +import com.netscape.jss.util.*; + +final class ModuleProxy extends NativeProxy { + ModuleProxy(byte[] pointer) { + super(pointer); + } + + protected native void releaseNativeResources(); + + protected void finalize() throws Throwable { + super.finalize(); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Cert.c b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Cert.c new file mode 100644 index 00000000000..ee062350af9 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Cert.c @@ -0,0 +1,589 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +#include "_jni/com_netscape_jss_pkcs11_CertProxy.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "pk11util.h" +#include + + +/* + * Class: com_netscape_jss_pkcs11_PK11Cert + * Method: getEncoded + * Signature: ()[B + */ +JNIEXPORT jbyteArray JNICALL Java_com_netscape_jss_pkcs11_PK11Cert_getEncoded + (JNIEnv *env, jobject this) +{ + PRThread *pThread; + CERTCertificate *cert; + SECItem *derCert; + jbyteArray derArray=NULL; + jbyte *pByte; + + pThread = PR_AttachThread(PR_SYSTEM_THREAD, 0, NULL); + PR_ASSERT(pThread != NULL); + + PR_ASSERT(env!=NULL && this!=NULL); + + /* + * extract the DER cert from the CERTCertificate* + */ + if( JSS_PK11_getCertPtr(env, this, &cert) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + goto finish; + } + PR_ASSERT(cert != NULL); + + derCert = &cert->derCert; + /* the SECItem type does not have to be siDERCertBuffer */ + if(derCert->data==NULL || derCert->len<1) { + JSS_throw(env, CERTIFICATE_ENCODING_EXCEPTION); + goto finish; + } + + /* + * Copy the DER data to a new Java byte array + */ + derArray = (*env)->NewByteArray(env, derCert->len); + if(derArray==NULL) { + JSS_throw(env, OUT_OF_MEMORY_ERROR); + goto finish; + } + pByte = (*env)->GetByteArrayElements(env, derArray, NULL); + if(pByte==NULL) { + JSS_throw(env, OUT_OF_MEMORY_ERROR); + goto finish; + } + memcpy(pByte, derCert->data, derCert->len); + (*env)->ReleaseByteArrayElements(env, derArray, pByte, 0); + +finish: + PR_DetachThread(); + return derArray; +} + +/* + * Class: com_netscape_jss_pkcs11_PK11Cert + * Method: getVersion + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_netscape_jss_pkcs11_PK11Cert_getVersion + (JNIEnv *env, jobject this) +{ + PRThread *pThread; + CERTCertificate *cert; + long lVersion; + + pThread = PR_AttachThread(PR_SYSTEM_THREAD, 0, NULL); + PR_ASSERT(pThread != NULL); + + PR_ASSERT(env!=NULL && this!=NULL); + + /* + * Get the version from the CERTCertificate * + */ + if( JSS_PK11_getCertPtr(env, this, &cert) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + goto finish; + } + PR_ASSERT(cert!=NULL); + + if(cert->version.data==NULL || cert->version.len<=0) { + /* default value is 0 */ + lVersion = 0; + goto finish; + } + + lVersion = DER_GetInteger(&cert->version); + + /* jint is 2s complement 32 bits. The max value is 0111...111. */ + PR_ASSERT( (lVersion >= 0L) && (lVersion < (long)0x7fffffff) ); + +finish: + PR_DetachThread(); + return (jint) lVersion; +} + +/****************************************************************** + * + * C e r t P r o x y . g e t P u b l i c K e y + * + * Extracts the SECKEYPublicKey from the CERTCertificate, wraps it + * in a Java wrapper, and returns it. + */ +JNIEXPORT jobject JNICALL +Java_com_netscape_jss_pkcs11_PK11Cert_getPublicKey + (JNIEnv *env, jobject this) +{ + CERTCertificate *cert; + SECKEYPublicKey *pubk=NULL; + PRThread *pThread; + jobject pubKey=NULL; + + PR_ASSERT(env!=NULL && this!=NULL); + + pThread = PR_AttachThread(PR_SYSTEM_THREAD, 0, NULL); + PR_ASSERT(pThread != NULL); + + if( JSS_PK11_getCertPtr(env, this, &cert) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + goto finish; + } + + pubk = CERT_ExtractPublicKey(cert); + if(pubk==NULL) { + PR_ASSERT( PR_GetError() == SEC_ERROR_NO_MEMORY); + JSS_throw(env, OUT_OF_MEMORY_ERROR); + goto finish; + } + + pubKey = JSS_PK11_wrapPubKey(env, &pubk); + if(pubKey == NULL) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + goto finish; + } + +finish: + if(pubk!=NULL) { + SECKEY_DestroyPublicKey(pubk); + } + PR_DetachThread(); + return pubKey; +} + +/****************************************************************** + * + * C e r t P r o x y . r e l e a s e N a t i v e R e s o u r c e s + * + * Calls CERT_DestroyCertificate on the underlying CERTCertificate. + */ +JNIEXPORT void JNICALL +Java_com_netscape_jss_pkcs11_CertProxy_releaseNativeResources + (JNIEnv *env, jobject this) +{ + CERTCertificate *cert; + PRThread *pThread; + + PR_ASSERT(env!=NULL && this!=NULL); + + pThread = PR_AttachThread(PR_SYSTEM_THREAD, 0, NULL); + PR_ASSERT(pThread != NULL); + + /* Get the CERTCertificate structure */ + if(JSS_getPtrFromProxy(env, this, (void**)&cert) != PR_SUCCESS) { + PR_ASSERT( PR_FALSE ); + goto finish; + } + PR_ASSERT(cert != NULL); + + CERT_DestroyCertificate(cert); + +finish: + PR_DetachThread(); +} + + +/****************************************************************** + * + * J S S _ P K 1 1 _ g e t C e r t P t r + * + * Given a Certificate object, extracts the CERTCertificate* and + * stores it at the given address. + * + * certObject: A JNI reference to a JSS Certificate object. + * ptr: Address of a CERTCertificate* that will receive the pointer. + * Returns: PR_SUCCESS for success, PR_FAILURE if an exception was thrown. + */ +PR_IMPLEMENT( PRStatus ) +JSS_PK11_getCertPtr(JNIEnv *env, jobject certObject, CERTCertificate **ptr) +{ + PR_ASSERT(env!=NULL && certObject!=NULL && ptr!=NULL); + + /* Get the pointer from the cert proxy */ + return JSS_getPtrFromProxyOwner(env, certObject, CERT_PROXY_FIELD, + CERT_PROXY_SIG, (void**)ptr); +} + +/**************************************************************** + * + * J S S _ P K 1 1 _ w r a p C e r t + * + * Builds a Certificate wrapper around a CERTCertificate. + * cert: Will be eaten and erased whether the wrap was successful or not. + * returns: a new PK11Cert wrapping the CERTCertificate, or NULL if an + * exception was thrown. + */ +PR_IMPLEMENT( jobject ) +JSS_PK11_wrapCert(JNIEnv *env, CERTCertificate **cert) +{ + jclass certClass; + jmethodID constructor; + jbyteArray byteArray; + jobject Cert=NULL; + char *className; + PK11SlotInfo *certSlot = NULL; + CK_OBJECT_HANDLE certID; + + PR_ASSERT(env!=NULL && cert!=NULL && *cert!=NULL); + + byteArray = JSS_ptrToByteArray(env, *cert); + + /* + * This call will update the correct slot to cert->slot, which otherwise + * might not be accurate. + */ + certID = PK11_FindObjectForCert(*cert, NULL, &certSlot); + + /* + * Lookup the class and constructor + */ + if( (*cert)->slot ) { + if( (*cert)->isperm ) { + /* it has a slot and it's in the permanent database */ + className = INTERNAL_TOKEN_CERT_CLASS_NAME; + } else { + /* it has a slot, but it's not in the permanent database */ + className = TOKEN_CERT_CLASS_NAME; + } + } else { + if( (*cert)->isperm ) { + /* it is in the permanent database, but has no slot */ + className = INTERNAL_CERT_CLASS_NAME; + } else { + /* it is not in the permanent database, and it has no slot */ + className = CERT_CLASS_NAME; + } + } + + certClass = (*env)->FindClass(env, className); + if(certClass == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + constructor = (*env)->GetMethodID( + env, + certClass, + PLAIN_CONSTRUCTOR, + CERT_CONSTRUCTOR_SIG); + if(constructor == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + /* Call the constructor */ + Cert = (*env)->NewObject(env, certClass, constructor, byteArray); + if(Cert==NULL) { + goto finish; + } + +finish: + if(Cert==NULL) { + CERT_DestroyCertificate(*cert); + } + if(certSlot!=NULL) { + PK11_FreeSlot(certSlot); + } + *cert = NULL; + return Cert; +} + +/********************************************************************** + * PK11Cert.getOwningToken + */ +JNIEXPORT jobject JNICALL +Java_com_netscape_jss_pkcs11_PK11Cert_getOwningToken + (JNIEnv *env, jobject this) +{ + PK11SlotInfo *slot = NULL; + CERTCertificate *cert; + jobject token = NULL; + + PR_ASSERT(env!=NULL && this!=NULL); + + /* get the C Certificate structure */ + if( JSS_PK11_getCertPtr(env, this, &cert) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + goto finish; + } + + /* extract the slot from the certificate */ + slot = cert->slot; + PR_ASSERT(slot != NULL); + + /* wrap the slot in a Java PK11Token */ + token = JSS_PK11_wrapPK11Token(env, &slot); + if(token == NULL) { + PR_ASSERT( (*env)->ExceptionOccurred(env) ); + goto finish; + } + +finish: + return token; +} + +/********************************************************************** + * PK11Cert.getUniqueID + */ +JNIEXPORT jbyteArray JNICALL +Java_com_netscape_jss_pkcs11_PK11Cert_getUniqueID + (JNIEnv *env, jobject this) +{ + CERTCertificate *cert; + SECItem id = {0,0,0}; + jbyteArray byteArray=NULL; + + PR_ASSERT(env!=NULL && this!=NULL); + + /************************************************** + * Get the CERTCertificate structure + **************************************************/ + if( JSS_PK11_getCertPtr(env, this, &cert) != PR_SUCCESS) { + goto finish; + } + PR_ASSERT( cert->slot != NULL ); + + /*************************************************** + * Get the id attribute + ***************************************************/ + if( PK11_ReadAttribute( cert->slot, + cert->pkcs11ID, + CKA_ID, + NULL /*arena*/, + &id) != SECSuccess) + { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Unable to read ID attribute"); + goto finish; + } + + /*************************************************** + * Write the id to a new byte array + ***************************************************/ + byteArray = (*env)->NewByteArray(env, id.len); + if(byteArray == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + (*env)->SetByteArrayRegion(env, byteArray, 0, id.len, (jbyte*)id.data); + if( (*env)->ExceptionOccurred(env) != NULL) { + PR_ASSERT(PR_FALSE); + goto finish; + } + +finish: + SECITEM_FreeItem(&id, PR_FALSE /*freeit*/); + + return byteArray; +} + +/********************************************************************** + * PK11Cert.getNickname + */ +JNIEXPORT jstring JNICALL +Java_com_netscape_jss_pkcs11_PK11Cert_getNickname + (JNIEnv *env, jobject this) +{ + CERTCertificate *cert; + + PR_ASSERT(env!=NULL && this!=NULL); + + if( JSS_PK11_getCertPtr(env, this, &cert) != PR_SUCCESS) { + return NULL; + } + if(cert->nickname == NULL) { + return NULL; + } else { + return (*env)->NewStringUTF(env, cert->nickname); + } +} + +/********************************************************************** + * PK11Cert.setTrust + */ +JNIEXPORT void JNICALL +Java_com_netscape_jss_pkcs11_PK11Cert_setTrust + (JNIEnv *env, jobject this, jint type, jint newTrust) +{ + CERTCertificate *cert; + CERTCertTrust trust; + + PR_ASSERT(env!=NULL && this!=NULL); + + if( JSS_PK11_getCertPtr(env, this, &cert) != PR_SUCCESS) { + return; + } + + if( CERT_GetCertTrust( cert, &trust ) != SECSuccess) { + PR_ASSERT(PR_FALSE); + return; + } + + switch(type) { + case 0: /* SSL */ + trust.sslFlags = newTrust; + break; + case 1: /* email */ + trust.emailFlags = newTrust; + break; + case 2: /* object signing */ + trust.objectSigningFlags = newTrust; + break; + default: + PR_ASSERT(PR_FALSE); + return; + } + + if( CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), cert, &trust) + != SECSuccess) + { + PR_ASSERT(PR_FALSE); + return; + } + return; +} + +/********************************************************************** + * PK11Cert.getTrust + */ +JNIEXPORT jint JNICALL +Java_com_netscape_jss_pkcs11_PK11Cert_getTrust + (JNIEnv *env, jobject this, jint type) +{ + CERTCertificate *cert; + CERTCertTrust trust; + + PR_ASSERT(env!=NULL && this!=NULL); + + if( JSS_PK11_getCertPtr(env, this, &cert) != PR_SUCCESS) { + return 0; + } + + if( CERT_GetCertTrust( cert, &trust ) != SECSuccess) { + PR_ASSERT(PR_FALSE); + return 0; + } + + switch(type) { + case 0: /* SSL */ + return trust.sslFlags; + case 1: /* email */ + return trust.emailFlags; + case 2: /* object signing */ + return trust.objectSigningFlags; + default: + PR_ASSERT(PR_FALSE); + return 0; + } +} + +/********************************************************************** + * PK11Cert.getSerialNumberByteArray + */ +JNIEXPORT jbyteArray JNICALL +Java_com_netscape_jss_pkcs11_PK11Cert_getSerialNumberByteArray + (JNIEnv *env, jobject this) +{ + CERTCertificate *cert; + + if( JSS_PK11_getCertPtr(env, this, &cert) != PR_SUCCESS) { + return NULL; + } + + PR_ASSERT(cert->serialNumber.len > 0); + PR_ASSERT(cert->serialNumber.data != NULL); + + return JSS_OctetStringToByteArray(env, &cert->serialNumber); +} + + +/********************************************************************** + * PK11Cert.getSubjectDNString + */ +JNIEXPORT jstring JNICALL +Java_com_netscape_jss_pkcs11_PK11Cert_getSubjectDNString + (JNIEnv *env, jobject this) +{ + CERTCertificate *cert; + char *ascii; + + if( JSS_PK11_getCertPtr(env, this, &cert) != PR_SUCCESS) { + return NULL; + } + + ascii = CERT_NameToAscii(&cert->subject); + + if( ascii ) { + return (*env)->NewStringUTF(env, ascii); + } else { + return NULL; + } +} + +/********************************************************************** + * PK11Cert.getIssuerDNString + */ +JNIEXPORT jstring JNICALL +Java_com_netscape_jss_pkcs11_PK11Cert_getIssuerDNString + (JNIEnv *env, jobject this) +{ + CERTCertificate *cert; + char *ascii; + + if( JSS_PK11_getCertPtr(env, this, &cert) != PR_SUCCESS) { + return NULL; + } + + ascii = CERT_NameToAscii(&cert->issuer); + + if( ascii ) { + return (*env)->NewStringUTF(env, ascii); + } else { + return NULL; + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Cert.java b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Cert.java new file mode 100644 index 00000000000..97d73a3e875 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Cert.java @@ -0,0 +1,164 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs11; + +import com.netscape.jss.crypto.*; +import com.netscape.jss.util.*; +import java.security.*; +import java.security.cert.*; +import java.util.*; +import java.math.BigInteger; + +public class PK11Cert implements com.netscape.jss.crypto.X509Certificate { + + public native byte[] getEncoded() throws CertificateEncodingException; + + //public native byte[] getUniqueID(); + + public native String getNickname(); + + /** + * A class that implements Principal with a String. + */ + protected static class StringPrincipal implements Principal { + public StringPrincipal(String str) { + this.str = str; + } + + public boolean + equals(Object other) { + if( ! (other instanceof StringPrincipal) ) { + return false; + } + return getName().equals( ((StringPrincipal)other).getName() ); + } + + public String getName() { + return str; + } + public int hashCode() { + return str.hashCode(); + } + + public String toString() { + return str; + } + protected String str; + } + + public Principal + getSubjectDN() { + return new StringPrincipal( getSubjectDNString() ); + } + + public Principal + getIssuerDN() { + return new StringPrincipal( getIssuerDNString() ); + } + + public BigInteger + getSerialNumber() { + return new BigInteger( getSerialNumberByteArray() ); + } + protected native byte[] getSerialNumberByteArray(); + + protected native String getSubjectDNString(); + + protected native String getIssuerDNString(); + + public native java.security.PublicKey getPublicKey(); + + public native int getVersion(); + + + /////////////////////////////////////////////////////////////////////// + // PKCS #11 Cert stuff. Must only be called on certs that have + // an associated slot. + /////////////////////////////////////////////////////////////////////// + protected native byte[] getUniqueID(); + + protected native CryptoToken getOwningToken(); + + /////////////////////////////////////////////////////////////////////// + // Trust Management. Must only be called on certs that live in the + // internal database. + /////////////////////////////////////////////////////////////////////// + /** + * Sets the trust flags for this cert. + * + * @param type SSL, EMAIL, or OBJECT_SIGNING. + * @param trust The trust flags for this type of trust. + */ + protected native void setTrust(int type, int trust); + + /** + * Gets the trust flags for this cert. + * + * @param type SSL, EMAIL, or OBJECT_SIGNING. + * @return The trust flags for this type of trust. + */ + protected native int getTrust(int type); + + ///////////////////////////////////////////////////////////// + // Construction + ///////////////////////////////////////////////////////////// + //PK11Cert(CertProxy proxy) { + // Assert.assert(proxy!=null); + // this.certProxy = proxy; + //} + + PK11Cert(byte[] pointer) { + Assert.assert(pointer!=null); + certProxy = new CertProxy(pointer); + } + + ///////////////////////////////////////////////////////////// + // private data + ///////////////////////////////////////////////////////////// + protected CertProxy certProxy; +} + +class CertProxy extends com.netscape.jss.util.NativeProxy { + + public CertProxy(byte[] pointer) { + super(pointer); + } + + protected native void releaseNativeResources(); + + protected void finalize() throws Throwable { + Debug.trace(Debug.OBNOXIOUS, "finalizing a certificate"); + super.finalize(); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Cipher.c b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Cipher.c new file mode 100644 index 00000000000..6e23d0d66d7 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Cipher.c @@ -0,0 +1,352 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +#include "_jni/com_netscape_jss_pkcs11_PK11Cipher.h" + +#include +#include +#include +#include +#include + +/* JSS includes */ +#include +#include +#include +#include +#include + +/*********************************************************************** + * + * PK11Cipher.initContext + */ +JNIEXPORT jobject JNICALL +Java_com_netscape_jss_pkcs11_PK11Cipher_initContext + (JNIEnv *env, jclass clazz, jboolean encrypt, jobject keyObj, + jobject algObj, jbyteArray ivBA) +{ + CK_MECHANISM_TYPE mech; + PK11SymKey *key=NULL; + SECItem *param=NULL; + SECItem *iv=NULL; + PK11Context *context=NULL; + CK_ATTRIBUTE_TYPE op; + jobject contextObj; + + PR_ASSERT(env!=NULL && clazz!=NULL && keyObj!=NULL && algObj!=NULL); + + /* get mechanism */ + mech = JSS_getPK11MechFromAlg(env, algObj); + if(mech == CKM_INVALID_MECHANISM) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Unable to resolve algorithm to" + " PKCS #11 mechanism"); + goto finish; + } + + /* get operation type */ + if( encrypt ) { + op = CKA_ENCRYPT; + } else { + op = CKA_DECRYPT; + } + + /* get key */ + if( JSS_PK11_getSymKeyPtr(env, keyObj, &key) != PR_SUCCESS) { + goto finish; + } + + /* get param, if there is one */ + if( ivBA != NULL ) { + iv = JSS_ByteArrayToSECItem(env, ivBA); + if( iv == NULL ) { + /* exception was thrown */ + goto finish; + } + } + param = PK11_ParamFromIV(mech, iv); + + /* HACK! The previous function doesn't know the key size, so it can't + * set the RC2 effective key length correctly. We have to set it by + * hand in this case. */ + switch(mech) { + case CKM_RC2_CBC: + case CKM_RC2_CBC_PAD: + ((CK_RC2_CBC_PARAMS*)param->data)->ulEffectiveBits = + PK11_GetKeyStrength(key, NULL); + } + + + /* create crypto context */ + context = PK11_CreateContextBySymKey(mech, op, key, param); + if(context == NULL ) { + JSS_throwMsg(env, TOKEN_EXCEPTION, + "Failed to generate crypto context"); + goto finish; + } + + /* wrap crypto context. This sets context to NULL. */ + contextObj = JSS_PK11_wrapCipherContextProxy(env, &context); + +finish: + if( param != NULL ) { + SECITEM_FreeItem(param, PR_TRUE /*freeit*/); + } + if(iv) { + SECITEM_FreeItem(iv, PR_TRUE /*freeit*/); + } + if(context != NULL) { + /* if the function succeeded, context would be NULL */ + PK11_DestroyContext(context, PR_TRUE /*freeit*/); + } + PR_ASSERT( contextObj || (*env)->ExceptionOccurred(env) ); + return contextObj; +} + +/*********************************************************************** + * + * PK11Cipher.updateContext + */ +JNIEXPORT jbyteArray JNICALL +Java_com_netscape_jss_pkcs11_PK11Cipher_updateContext + (JNIEnv *env, jclass clazz, jobject contextObj, jbyteArray inputBA, + jint blockSize) +{ + PK11Context *context=NULL; + jbyte *inbuf=NULL; + unsigned int inlen; + unsigned char *outbuf=NULL; + unsigned int outlen; + jbyteArray outArray=NULL; + + PR_ASSERT(env!=NULL && clazz!=NULL && contextObj!=NULL && inputBA!=NULL); + + /* get the context */ + if( JSS_PK11_getCipherContext(env, contextObj, &context) != PR_SUCCESS) { + goto finish; + } + + /* extract input from byte array */ + inlen = (*env)->GetArrayLength(env, inputBA); + PR_ASSERT(inlen >= 0); + inbuf = (*env)->GetByteArrayElements(env, inputBA, NULL); + if(inbuf == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + /* create output buffer */ + outlen = inlen + blockSize; /* this will hold the output */ + outbuf = PR_Malloc(outlen); + if(outbuf == NULL) { + JSS_throw(env, OUT_OF_MEMORY_ERROR); + goto finish; + } + + /* do the operation */ + if( PK11_CipherOp(context, outbuf, (int*)&outlen, outlen, + (unsigned char*)inbuf, inlen) != SECSuccess) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Cipher Operation failed"); + goto finish; + } + PR_ASSERT(outlen >= 0); + + /* convert output buffer to byte array */ + outArray = (*env)->NewByteArray(env, outlen); + if(outArray == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + (*env)->SetByteArrayRegion(env, outArray, 0, outlen, (jbyte*)outbuf); + +finish: + if(inbuf) { + (*env)->ReleaseByteArrayElements(env, inputBA, inbuf, JNI_ABORT); + } + if(outbuf) { + PR_Free(outbuf); + } + return outArray; +} + +/*********************************************************************** + * + * PK11Cipher.finalizeContext + * + */ +JNIEXPORT jbyteArray JNICALL +Java_com_netscape_jss_pkcs11_PK11Cipher_finalizeContext + (JNIEnv *env, jclass clazz, jobject contextObj, jint blockSize, + jboolean padded) +{ + PK11Context *context=NULL; + char *outBuf = NULL; + unsigned int outLen, newOutLen; + jobject outBA=NULL; + SECStatus status; + + PR_ASSERT(env!=NULL && contextObj!=NULL); + + /* get context */ + if( JSS_PK11_getCipherContext(env, contextObj, &context) != PR_SUCCESS) { + goto finish; + } + + /* create output buffer */ + outLen = blockSize; /* maximum amount needed */ + outBuf = PR_Malloc(outLen); + if(outBuf == NULL) { + JSS_throw(env, OUT_OF_MEMORY_ERROR); + goto finish; + } + + /* perform the finalization */ + status = PK11_DigestFinal(context, outBuf, &newOutLen, outLen); + if( (status != SECSuccess) ) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Cipher operation failed on token"); + goto finish; + } + + /* convert output buffer to byte array */ + PR_ASSERT(newOutLen >= 0); + outBA = (*env)->NewByteArray(env, newOutLen); + if(outBA == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + (*env)->SetByteArrayRegion(env, outBA, 0, newOutLen, (jbyte*)outBuf); + +finish: + if(outBuf) { + PR_Free(outBuf); + } + PR_ASSERT( outBA || (*env)->ExceptionOccurred(env) ); + return outBA; +} + + + +/*********************************************************************** + * + * J S S _ P K 1 1 _ g e t C i p h e r C o n t e x t + * + * Extracts the PK11Context from a CipherContextProxy. + * + * proxy + * A CipherContextProxy. + * + * pContext + * Address of a PK11Context*, which will be filled with the pointer + * extracted from the CipherContextProxy. + * + * RETURNS + * PR_SUCCESS for success, or PR_FAILURE if an exception was thrown. + */ +PR_IMPLEMENT( PRStatus ) +JSS_PK11_getCipherContext(JNIEnv *env, jobject proxy, PK11Context **pContext) +{ + + PR_ASSERT(env!=NULL && proxy!=NULL && pContext!=NULL); + + return JSS_getPtrFromProxy(env, proxy, (void**)pContext); +} + +/*********************************************************************** + * + * J S S _ P K 1 1 _ m a k e C i p h e r C o n t e x t P r o x y + * + * Wraps a PK11Context in a CipherContextProxy. + * + * context + * address of a poitner to a PK11Context, which must not be NULL. + * It will be eaten by the wrapper and set to NULL, even if the + * function returns NULL. + * + * RETURNS + * A new CipherContextProxy, or NULL if an exception was thrown. + */ +PR_IMPLEMENT( jobject ) +JSS_PK11_wrapCipherContextProxy(JNIEnv *env, PK11Context **context) { + + jbyteArray pointer=NULL; + jclass proxyClass; + jmethodID constructor; + jobject contextObj=NULL; + + PR_ASSERT( env!=NULL && context!=NULL && *context!=NULL ); + + /* convert pointer to byte array */ + pointer = JSS_ptrToByteArray(env, *context); + + /* + * Lookup the class and constructor + */ + proxyClass = (*env)->FindClass(env, CIPHER_CONTEXT_PROXY_CLASS_NAME); + if(proxyClass == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + constructor = (*env)->GetMethodID(env, proxyClass, + PLAIN_CONSTRUCTOR, + CIPHER_CONTEXT_PROXY_CONSTRUCTOR_SIG); + if(constructor == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + /* call the constructor */ + contextObj = (*env)->NewObject(env, proxyClass, constructor, pointer); + +finish: + if(contextObj == NULL) { + /* didn't work, so free resources */ + PK11_DestroyContext( (PK11Context*)*context, PR_TRUE /*freeit*/ ); + } + *context=NULL; + PR_ASSERT( contextObj || (*env)->ExceptionOccurred(env) ); + return contextObj; +} + +/*********************************************************************** + * + * CipherContextProxy.releaseNativeResources + */ +JNIEXPORT void JNICALL +Java_com_netscape_jss_pkcs11_CipherContextProxy_releaseNativeResources + (JNIEnv *env, jobject this) +{ + PK11Context *context; + + if( JSS_PK11_getCipherContext(env, this, &context) == PR_SUCCESS ) { + PK11_DestroyContext(context, PR_TRUE /*freeit*/); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Cipher.java b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Cipher.java new file mode 100644 index 00000000000..2189dab806e --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Cipher.java @@ -0,0 +1,267 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs11; + +import com.netscape.jss.crypto.*; +import com.netscape.jss.util.NativeProxy; +import java.security.InvalidKeyException; +import java.security.InvalidAlgorithmParameterException; +import java.security.spec.AlgorithmParameterSpec; +import com.netscape.jss.util.Assert; +import java.security.NoSuchAlgorithmException; + +final class PK11Cipher extends com.netscape.jss.crypto.Cipher { + + // set once in the constructor + private PK11Token token; + + // set once in the constructor + private EncryptionAlgorithm algorithm; + + // set with initXXX() + private AlgorithmParameterSpec parameters=null; + + // set with initXXX() + private SymmetricKey key=null; + + // set with initXXX() + private byte[] IV=null; + + // set with initXXX() + private CipherContextProxy contextProxy = null; + + // modified by various operations + private int state=UNINITIALIZED; + + // States + private static final int UNINITIALIZED=0; + private static final int ENCRYPT=1; + private static final int DECRYPT=2; + + private PK11Cipher() { } + + PK11Cipher(PK11Token token, EncryptionAlgorithm algorithm) { + this.token = token; + this.algorithm = algorithm; + } + + public void initEncrypt(SymmetricKey key) + throws InvalidKeyException, InvalidAlgorithmParameterException, + TokenException + { + initEncrypt(key, null); + } + + public void initDecrypt(SymmetricKey key) + throws InvalidKeyException, InvalidAlgorithmParameterException, + TokenException + { + initDecrypt(key, null); + } + + public void initEncrypt(SymmetricKey key, AlgorithmParameterSpec parameters) + throws InvalidKeyException, InvalidAlgorithmParameterException, + TokenException + { + reset(); + + checkKey(key); + checkParams(parameters); + + if( parameters instanceof IVParameterSpec ) { + IV = ((IVParameterSpec)parameters).getIV(); + } + this.key = key; + this.parameters = parameters; + state = ENCRYPT; + + contextProxy = initContext( true, key, algorithm, IV ); + } + + public void initDecrypt(SymmetricKey key, AlgorithmParameterSpec parameters) + throws InvalidKeyException, InvalidAlgorithmParameterException, + TokenException + { + reset(); + + checkKey(key); + checkParams(parameters); + + if( parameters instanceof IVParameterSpec ) { + IV = ((IVParameterSpec)parameters).getIV(); + } + this.key = key; + this.parameters = parameters; + state = DECRYPT; + + contextProxy = initContext(false, key, algorithm, IV); + } + + public byte[] update(byte[] bytes) + throws IllegalStateException, TokenException + { + if( state == UNINITIALIZED ) { + throw new IllegalStateException(); + } + + return updateContext( contextProxy, bytes, algorithm.getBlockSize()); + } + + public byte[] update(byte[] bytes, int offset, int length) + throws IllegalStateException, TokenException + { + byte[] sub = new byte[length]; + + System.arraycopy( bytes, offset, sub, 0, length ); + + return update(sub); + } + + public byte[] doFinal(byte[] bytes) + throws IllegalStateException, IllegalBlockSizeException, + BadPaddingException, TokenException + { + if( state == UNINITIALIZED ) { + throw new IllegalStateException(); + } + + byte[] first = update(bytes); + + byte[] last = finalizeContext(contextProxy, algorithm.getBlockSize(), + algorithm.isPadded() ); + + byte[] combined = new byte[ first.length+last.length ]; + System.arraycopy(first, 0, combined, 0, first.length); + System.arraycopy(last, 0, combined, first.length, last.length); + return combined; + } + + public byte[] doFinal(byte[] bytes, int offset, int length) + throws IllegalStateException, IllegalBlockSizeException, + BadPaddingException, TokenException + { + byte[] sub = new byte[length]; + + System.arraycopy(bytes, offset, sub, 0, length); + + return doFinal(sub); + } + + public byte[] doFinal() + throws IllegalStateException, IllegalBlockSizeException, + BadPaddingException, TokenException + { + if( state == UNINITIALIZED ) { + throw new IllegalStateException(); + } + return finalizeContext(contextProxy, algorithm.getBlockSize(), + algorithm.isPadded() ); + } + + private static native CipherContextProxy + initContext( boolean encrypt, SymmetricKey key, EncryptionAlgorithm alg, + byte[] IV) + throws TokenException; + + private static native byte[] + updateContext( CipherContextProxy context, byte[] input, int blocksize ) + throws TokenException; + + private static native byte[] + finalizeContext( CipherContextProxy context, int blocksize, boolean padded) + throws TokenException, IllegalBlockSizeException, BadPaddingException; + + private void reset() { + parameters = null; + key = null; + IV = null; + state = UNINITIALIZED; + contextProxy = null; + } + + /** + * Matches the params against those expected by the algorithm. + */ + private void checkParams(AlgorithmParameterSpec params) + throws InvalidAlgorithmParameterException + { + Class paramClass = algorithm.getParameterClass(); + if(params==null) { + if(paramClass != null) { + // this algorithm takes a parameter, but none was given + throw new InvalidAlgorithmParameterException(algorithm+ + " requires an algorithm parameter"); + } + } else { + if( paramClass == null ) { + //this algorithm doesn't take a param, but one was given + throw new InvalidAlgorithmParameterException(algorithm+ + " does not take a parameter"); + } else if( ! ( paramClass.isInstance(params) ) ) { + throw new InvalidAlgorithmParameterException(algorithm+ + " expects a parameter of type "+paramClass); + } + } + } + + + + /** + * Checks for null, makes sure the key lives on the correct token, + * makes sure it is a PKCS #11 key, makes sure it's the right type + * for this algorithm. + */ + private void checkKey(SymmetricKey key) throws InvalidKeyException { + if( key==null ) { + throw new InvalidKeyException("Key is null"); + } + if( ! key.getOwningToken().equals(token) ) { + throw new InvalidKeyException("Key does not reside on the "+ + "current token"); + } + if( ! (key instanceof PK11SymKey) ) { + throw new InvalidKeyException("Key is not a PKCS #11 key"); + } + try { + if( ((PK11SymKey)key).getKeyType() != + KeyType.getKeyTypeFromAlgorithm(algorithm) ) { + throw new InvalidKeyException("Key is not the right type for"+ + " this algorithm"); + } + } catch( NoSuchAlgorithmException e ) { + Assert.notReached("Unknown algorithm"); + } + } + +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11DSAPublicKey.java b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11DSAPublicKey.java new file mode 100644 index 00000000000..c468fb313f5 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11DSAPublicKey.java @@ -0,0 +1,74 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs11; + +import com.netscape.jss.util.Assert; +import java.security.interfaces.DSAPublicKey; +import java.security.interfaces.DSAParams; +import java.security.spec.DSAParameterSpec; +import java.math.BigInteger; + +public final class PK11DSAPublicKey extends PK11PubKey implements DSAPublicKey { + + public PK11DSAPublicKey(byte[] pointer) { + super(pointer); + } + + public DSAParams getParams() { + try { + BigInteger P = new BigInteger( getPByteArray() ); + BigInteger Q = new BigInteger( getQByteArray() ); + BigInteger G = new BigInteger( getGByteArray() ); + + return new DSAParameterSpec(P, Q, G); + } catch(NumberFormatException e) { + Assert.notReached("Unable to decode DSA parameters"); + return null; + } + } + + public BigInteger getY() { + try { + return new BigInteger( getYByteArray() ); + } catch(NumberFormatException e) { + Assert.notReached("Unable to decode DSA public value"); + return null; + } + } + + private native byte[] getPByteArray(); + private native byte[] getQByteArray(); + private native byte[] getGByteArray(); + private native byte[] getYByteArray(); +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11InternalCert.java b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11InternalCert.java new file mode 100644 index 00000000000..0a4e9b3d2b1 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11InternalCert.java @@ -0,0 +1,129 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs11; + +import com.netscape.jss.crypto.*; +import com.netscape.jss.util.*; +import java.security.*; +import java.security.cert.*; +import java.util.*; +import java.math.BigInteger; + +/** + * A certificate that lives in the internal cert database. + */ +public class PK11InternalCert extends PK11Cert + implements InternalCertificate +{ + /////////////////////////////////////////////////////////////////////// + // Trust Management. This is all package stuff because it can only + // be called from PK11InternalCert. + /////////////////////////////////////////////////////////////////////// + public static final int SSL = 0; + public static final int EMAIL = 1; + public static final int OBJECT_SIGNING=2; + + /** + * Set the SSL trust flags for this certificate. + * + * @param trust A bitwise OR of the trust flags VALID_PEER, VALID_CA, + * TRUSTED_CA, USER, and TRUSTED_CLIENT_CA. + */ + public void setSSLTrust(int trust) + { + super.setTrust(SSL, trust); + } + + /** + * Set the email (S/MIME) trust flags for this certificate. + * + * @param trust A bitwise OR of the trust flags VALID_PEER, VALID_CA, + * TRUSTED_CA, USER, and TRUSTED_CLIENT_CA. + */ + public void setEmailTrust(int trust) + { + super.setTrust(EMAIL, trust); + } + + /** + * Set the object signing trust flags for this certificate. + * + * @param trust A bitwise OR of the trust flags VALID_PEER, VALID_CA, + * TRUSTED_CA, USER, and TRUSTED_CLIENT_CA. + */ + public void setObjectSigningTrust(int trust) + { + super.setTrust(OBJECT_SIGNING, trust); + } + + /** + * Get the SSL trust flags for this certificate. + * + * @return A bitwise OR of the trust flags VALID_PEER, VALID_CA, + * TRUSTED_CA, USER, and TRUSTED_CLIENT_CA. + */ + public int getSSLTrust() + { + return super.getTrust(SSL); + } + + /** + * Get the email (S/MIME) trust flags for this certificate. + * + * @return A bitwise OR of the trust flags VALID_PEER, VALID_CA, + * TRUSTED_CA, USER, and TRUSTED_CLIENT_CA. + */ + public int getEmailTrust() + { + return super.getTrust(EMAIL); + } + + /** + * Get the object signing trust flags for this certificate. + * + * @return A bitwise OR of the trust flags VALID_PEER, VALID_CA, + * TRUSTED_CA, USER, and TRUSTED_CLIENT_CA. + */ + public int getObjectSigningTrust() + { + return super.getTrust(OBJECT_SIGNING); + } + + ///////////////////////////////////////////////////////////// + // Construction + ///////////////////////////////////////////////////////////// + PK11InternalCert(byte[] pointer) { + super(pointer); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11InternalTokenCert.java b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11InternalTokenCert.java new file mode 100644 index 00000000000..f35b756d301 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11InternalTokenCert.java @@ -0,0 +1,56 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs11; + +import com.netscape.jss.crypto.*; + +/** + * A certificate that lives on the internal token. It has database information + * (like trust flags) but also PKCS #11 information (like unique ID). + */ +public final class PK11InternalTokenCert extends PK11InternalCert + implements TokenCertificate +{ + public byte[] getUniqueID() { + return super.getUniqueID(); + } + + public CryptoToken getOwningToken() { + return super.getOwningToken(); + } + + PK11InternalTokenCert(byte[] pointer) { + super(pointer); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Key.java b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Key.java new file mode 100644 index 00000000000..becfa22de4d --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Key.java @@ -0,0 +1,101 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs11; + +import com.netscape.jss.crypto.*; +import com.netscape.jss.util.*; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.IOException; +import java.util.Hashtable; +import java.security.NoSuchAlgorithmException; +import com.netscape.jss.crypto.SignatureAlgorithm; + + +abstract class PK11Key { + + ////////////////////////////////////////////////////////// + // Public Interface + /////////////////////////////////////////////////////////// + public String getAlgorithm() { + Assert.notReached("Keys don't have algorithms"); + return null; + } + + /** + * Unimplemented way of getting a standard encoding of the key. Use + * a key factory instead. + */ + public byte[] getEncoded() { + Assert.notYetImplemented("PK11Key.getEncoded"); + return null; + } + + /** + * Unimplemented way of getting standard encoding format of the key. + * Use a key factory instead. + */ + public String getFormat() { + Assert.notYetImplemented("PK11Key.getFormat"); + return null; + } + + ///////////////////////////////////////////////////////////// + // Construction + ///////////////////////////////////////////////////////////// + protected PK11Key() {} + + + ///////////////////////////////////////////////////////////// + // Implementation + ///////////////////////////////////////////////////////////// + // **HACK** + // Override serialization methods so that we don't get serialized, + // even though we are supposed to support it as an implementation of Key. + private void writeObject(ObjectOutputStream out) throws IOException { + Assert.assert(false, "PKCS#11 Key is not really serializable"); + } + + private void readObject(ObjectInputStream in) + throws IOException, ClassNotFoundException { + Assert.assert(false, "PKCS#11 Key is not really serializable"); + } + + + ///////////////////////////////////////////////////////////// + // Members + ///////////////////////////////////////////////////////////// + protected KeyProxy keyProxy; + +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11KeyGenerator.c b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11KeyGenerator.c new file mode 100644 index 00000000000..4fcb326910b --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11KeyGenerator.c @@ -0,0 +1,545 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +#include "_jni/com_netscape_jss_pkcs11_PK11KeyGenerator.h" + +#include +#include +#include +#include +#include +#include /* for hand-generating SHA-1 PBA HMAC key */ + +#include "jssutil.h" +#include "pk11util.h" +#include +#include +#include + +#define HCLHACK +#ifdef HCLHACK +/* PKCS #11 HACK */ +#include +#endif + +/*********************************************************************** + * + * PK11KeyGenerator.generateNormal + * + * Generates a non-PBE symmetric key on a token. + * + */ +JNIEXPORT jobject JNICALL +Java_com_netscape_jss_pkcs11_PK11KeyGenerator_generateNormal + (JNIEnv *env, jclass clazz, jobject token, jobject alg, jint strength) +{ + PK11SlotInfo *slot=NULL; + PK11SymKey *skey=NULL; + CK_MECHANISM_TYPE mech; + jobject keyObj=NULL; + + PR_ASSERT( env!=NULL && clazz!=NULL && token!=NULL && alg!=NULL ); + + /* Get the slot */ + if( JSS_PK11_getTokenSlotPtr(env, token, &slot) != PR_SUCCESS ) { + goto finish; + } + + /* Get the algorithm info */ + mech = JSS_getPK11MechFromAlg(env, alg); + PR_ASSERT(mech != CKM_INVALID_MECHANISM); + + /* + * HACK...to workaround bug 333440. + * You can't actually pass a keygen mech into PK11_KeyGen. You have + * to pass in an actual crypto mech, and it will translate it internally + * to the appropriate keygen mech. Very lame bug with an easy fix. + */ + switch(mech) { + case CKM_DES_KEY_GEN: + mech = CKM_DES_ECB; + break; + case CKM_DES3_KEY_GEN: + mech = CKM_DES3_ECB; + break; + case CKM_RC4_KEY_GEN: + mech = CKM_RC4; + break; + default: + break; + } + + /* generate the key */ + skey = PK11_KeyGen(slot, mech, NULL /*param*/, + strength/8 /*in bytes*/, NULL /*wincx*/ ); + + if(skey==NULL) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "KeyGen failed on token"); + goto finish; + } + + /* wrap the key. This sets skey to NULL. */ + keyObj = JSS_PK11_wrapSymKey(env, &skey); + +finish: + if(skey!=NULL) { + /* will only be non-NULL if keygen succeeded but wrapSymKey failed */ + PK11_FreeSymKey(skey); + } + return keyObj; +} + +/* We do the translation in Java now, but I'll leave this here just in case */ +#if 0 +/*********************************************************************** + * + * C o p y P a s s w o r d T o S E C I t e m + * + * pass + * A Java Password object. + * + * RETURNS + * A new SECItem containing a copy of the bytes in the password, + * or NULL iff an exception occurred. Be sure to zero it when + * you free it. + */ +static SECItem* +CopyPasswordToSECItem(JNIEnv *env, jobject pass) { + + jclass passClass=NULL; + jmethodID byteCopyMethod=NULL; + jbyteArray pwArray=NULL; + jbyte *bytes=NULL; + SECItem *item=NULL; + int numBytes=0; + + PR_ASSERT(env!=NULL && pass!=NULL); + + /* get password class and method */ + passClass = (*env)->GetObjectClass(env, pass); + if(passClass == NULL) { + JSS_trace(env, JSS_TRACE_ERROR, "Failed to find Password class"); + ASSERT_OUTOFMEM(env); + goto finish; + } + byteCopyMethod = (*env)->GetMethodID( env, + passClass, + PW_GET_BYTE_COPY_NAME, + PW_GET_BYTE_COPY_SIG); + if(byteCopyMethod==NULL) { + JSS_trace(env, JSS_TRACE_ERROR, "Failed to find Password manipulation" + " methods from native implementation"); + ASSERT_OUTOFMEM(env); + goto finish; + } + + /* copy to a byte array */ + pwArray = (*env)->CallObjectMethod(env, pass, byteCopyMethod); + if(pwArray == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + numBytes = (*env)->GetArrayLength(env, pwArray); + + /* copy from the byte array to a jbyte array */ + bytes = (*env)->GetByteArrayElements(env, pwArray, NULL); + if(bytes == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + /* copy from the jbyte array to a new SECItem */ + item = PR_NEW(SECItem); + /* last byte is null termination */ + PR_ASSERT( bytes[numBytes-1] == 0 ); + item->len = numBytes - 1; + item->data = PR_Malloc(item->len); + if(item->data==NULL) { + JSS_throw(env, OUT_OF_MEMORY_ERROR); + goto finish; + } + memcpy(item->data, bytes, item->len); + +finish: + if(bytes!=NULL) { + /* clear the password */ + PR_ASSERT(numBytes > 0); + memset(bytes, 0, numBytes); + (*env)->ReleaseByteArrayElements(env, pwArray, bytes, 0); + } else { + PR_ASSERT(pwArray!=NULL); + } + return item; +} +#endif + +static void +print_secitem(SECItem *item) { + int i; + int online; + + if(item==NULL) { + return; + } + + for(i=0, online=0; i < item->len; i++, online++) { + if(online > 25) { + printf("\n"); + online = 0; + } + printf("%.2x ", item->data[i]); + } +} + +/*********************************************************************** + * + * c o n s t r u c t S H A 1 P B A K e y + * + * Constructs a PBE key using CKM_PBA_SHA1_WITH_SHA1_HMAC. This should + * be supported by NSS automatically, but isn't (bug #336587). + * + * RETURNS + * A symmetric key from the given password, salt, and iteration count, + * or NULL if an exception was thrown. + * THROWS + * TokenException if an error occurs. + */ +static PK11SymKey* +constructSHA1PBAKey(JNIEnv *env, SECItem *pwitem, SECItem *salt, + int iterationCount) +{ + PBEBitGenContext* pbeCtxt=NULL; + SECItem *keyBits=NULL; + PK11SymKey *key=NULL; + + pbeCtxt = PBE_CreateContext( SEC_OID_SHA1, pbeBitGenIntegrityKey, + pwitem, salt, 160 /* SHA1 key length */, iterationCount); + if( pbeCtxt == NULL ) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Failed to create PBE context"); + goto finish; + } + + keyBits = PBE_GenerateBits(pbeCtxt); + if( keyBits == NULL ) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Failed to generate bits from" + "PBE context"); + goto finish; + } + + key = PK11_ImportSymKey( PK11_GetInternalSlot(), CKM_SHA_1, + PK11_OriginGenerated, CKA_SIGN, keyBits, NULL); + if( key == NULL ) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Failed to import PBA key from" + " PBA-generated bits"); + goto finish; + } + +finish: + if( pbeCtxt ) { + PBE_DestroyContext(pbeCtxt); + } + if(keyBits) { + SECITEM_ZfreeItem(keyBits, PR_TRUE /*freeit*/); + } + return key; +} + +/*********************************************************************** + * + * PK11KeyGenerator.generatePBE + * + */ +JNIEXPORT jobject JNICALL +Java_com_netscape_jss_pkcs11_PK11KeyGenerator_generatePBE + (JNIEnv *env, jclass clazz, jobject token, jobject alg, jbyteArray passBA, + jbyteArray saltBA, jint iterationCount) +{ + PK11SlotInfo *slot=NULL; + PK11SymKey *skey=NULL; + SECOidTag oidTag; + SECAlgorithmID *algid=NULL; + SECItem *salt=NULL; + SECItem *pwitem=NULL; + jobject keyObj=NULL; + CK_MECHANISM_TYPE mech=CKM_INVALID_MECHANISM; + + PR_ASSERT(env!=NULL && clazz!=NULL && token!=NULL && alg!=NULL + && passBA!=NULL && saltBA!=NULL); + + /* get the slot */ + if( JSS_PK11_getTokenSlotPtr(env, token, &slot) != PR_SUCCESS) { + goto finish; + } + + /* convert salt to SECItem */ + salt = JSS_ByteArrayToSECItem(env, saltBA); + if(salt == NULL) { + goto finish; + } + + /* convert password to SECItem */ + pwitem = JSS_ByteArrayToSECItem(env, passBA); + if(pwitem==NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + /* print_secitem(pwitem); */ + + + mech = JSS_getPK11MechFromAlg(env, alg); + + if( mech == CKM_PBA_SHA1_WITH_SHA1_HMAC ) { + + /* special case, construct key by hand. Bug #336587 */ + + skey = constructSHA1PBAKey(env, pwitem, salt, iterationCount); + if( skey==NULL ) { + /* exception was thrown */ + goto finish; + } + + } else { + + /* get the algorithm info */ + oidTag = JSS_getOidTagFromAlg(env, alg); + PR_ASSERT(oidTag != SEC_OID_UNKNOWN); + + /* create algid */ + algid = PK11_CreatePBEAlgorithmID(oidTag, iterationCount, salt); + if( algid == NULL ) { + JSS_throwMsg(env, TOKEN_EXCEPTION, + "Unable to process PBE parameters"); + goto finish; + } + + /* generate the key */ + skey = PK11_PBEKeyGen(slot, algid, pwitem, PR_FALSE /*faulty3DES*/, + NULL /*wincx*/); + if( skey == NULL ) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Failed to generate PBE key"); + goto finish; + } + } + + /* wrap the key. This sets skey to NULL. */ + keyObj = JSS_PK11_wrapSymKey(env, &skey); + +finish: + if(algid) { + SECOID_DestroyAlgorithmID(algid, PR_TRUE /*freeit*/); + } + if(salt) { + SECITEM_FreeItem(salt, PR_TRUE /*freeit*/); + } + if(pwitem) { + SECITEM_ZfreeItem(pwitem, PR_TRUE /*freeit*/); + } + if(skey) { + /* skey will be NULL if everything worked */ + PK11_FreeSymKey(skey); + } + return keyObj; +} + + +/*********************************************************************** + * + * PK11KeyGenerator.generatePBE_IV + * + */ +JNIEXPORT jobject JNICALL +Java_com_netscape_jss_pkcs11_PK11KeyGenerator_generatePBE_1IV + (JNIEnv *env, jclass clazz, jobject alg, jbyteArray passBA, + jbyteArray saltBA, jint iterationCount) +{ + SECOidTag oidTag; + SECAlgorithmID *algid=NULL; + SECItem *salt=NULL; + SECItem *pwitem=NULL; + SECItem *ivItem=NULL; + jbyteArray ivBA=NULL; + + PR_ASSERT(env!=NULL && clazz!=NULL && alg!=NULL + && passBA!=NULL && saltBA!=NULL); + + /* get the algorithm info */ + oidTag = JSS_getOidTagFromAlg(env, alg); + PR_ASSERT(oidTag != SEC_OID_UNKNOWN); + + /* convert salt to SECItem */ + salt = JSS_ByteArrayToSECItem(env, saltBA); + if(salt == NULL) { + goto finish; + } + + /* create algid */ + algid = PK11_CreatePBEAlgorithmID(oidTag, iterationCount, salt); + if( algid == NULL ) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Unable to process PBE parameters"); + goto finish; + } + + /* convert password to SECItem */ + pwitem = JSS_ByteArrayToSECItem(env, passBA); + if(pwitem==NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + /* generate the IV */ + ivItem = SEC_PKCS5GetIV(algid, pwitem, PR_FALSE /*faulty3DES*/); + if(ivItem==NULL) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Unable to generate PBE " + "initialization vector"); + goto finish; + } + + /* convert IV to byte array */ + ivBA = JSS_SECItemToByteArray(env, ivItem); + +finish: + if(algid) { + SECOID_DestroyAlgorithmID(algid, PR_TRUE /*freeit*/); + } + if(salt) { + SECITEM_FreeItem(salt, PR_TRUE /*freeit*/); + } + if(pwitem) { + SECITEM_ZfreeItem(pwitem, PR_TRUE /*freeit*/); + } + if(ivItem) { + SECITEM_FreeItem(ivItem, PR_TRUE /*freeit*/); + } + return ivBA; +} + +JNIEXPORT jobject JNICALL +Java_com_netscape_jss_pkcs11_PK11KeyGenerator_nativeClone + (JNIEnv *env, jclass clazz, jobject tokenObj, jobject toBeClonedObj) +{ + PK11SlotInfo *slot=NULL; + PK11SymKey *toBeCloned=NULL; + PK11SymKey *clone=NULL; + CK_BBOOL cktrue = CK_TRUE; + CK_OBJECT_CLASS ckclass = CKO_SECRET_KEY; + CK_KEY_TYPE keyType; + CK_ATTRIBUTE keyTemplate[] = { + { CKA_CLASS, NULL, 0}, + { CKA_KEY_TYPE, NULL, 0}, + { CKA_ENCRYPT, NULL, 0}, + { CKA_DECRYPT, NULL, 0}, + { CKA_WRAP, NULL, 0}, + { CKA_UNWRAP, NULL, 0}, + { CKA_VALUE, NULL, 0}, + }; + SECStatus rv; + CK_RV crv; + jobject cloneObj=NULL; + + PR_ASSERT(env!=NULL && tokenObj!=NULL && toBeClonedObj!=NULL); + + /* get slot */ + if( JSS_PK11_getTokenSlotPtr(env, tokenObj, &slot) != PR_SUCCESS) { + /* exception was thrown */ + goto finish; + } + + /* get toBeCloned */ + if( JSS_PK11_getSymKeyPtr(env, toBeClonedObj, &toBeCloned) != PR_SUCCESS) { + /* exception was thrown */ + goto finish; + } + + /* extract the key value */ + rv = PK11_ExtractKeyValue(toBeCloned); + if( rv != SECSuccess ) { + JSS_throw(env, NOT_EXTRACTABLE_EXCEPTION); + goto finish; + } + + /* create the new symkey structure */ + clone = PK11_CreateSymKey(slot, toBeCloned->type, NULL /*wincx*/); + if( clone == NULL ) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Unable to create symmetric key"); + goto finish; + } + clone->size = toBeCloned->size; + if( SECITEM_CopyItem(NULL, &clone->data, &toBeCloned->data) != SECSuccess) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Failed to copy key data"); + goto finish; + } + + /* setup the template */ + keyType = PK11_GetKeyType(toBeCloned->type, toBeCloned->size); + keyTemplate[0].pValue = &ckclass; + keyTemplate[0].ulValueLen = sizeof(ckclass); + keyTemplate[1].pValue = &keyType; + keyTemplate[1].ulValueLen = sizeof(keyType); + keyTemplate[2].pValue = &cktrue; + keyTemplate[2].ulValueLen = sizeof(cktrue); /* CKA_ENCRYPT */ + keyTemplate[3].pValue = &cktrue; + keyTemplate[3].ulValueLen = sizeof(cktrue); /* CKA_DECRYPT */ + keyTemplate[4].pValue = &cktrue; + keyTemplate[4].ulValueLen = sizeof(cktrue); /* CKA_WRAP */ + keyTemplate[5].pValue = &cktrue; + keyTemplate[5].ulValueLen = sizeof(cktrue); /* CKA_UNWRAP */ + keyTemplate[6].pValue = toBeCloned->data.data; + keyTemplate[6].ulValueLen = toBeCloned->data.len; + + /* import the key */ + if( !clone->sessionOwner || !clone->slot->isThreadSafe) { + PK11_EnterSlotMonitor(slot); + } + crv = PK11_GETTAB(slot)->C_CreateObject(clone->session, keyTemplate, + 7, &clone->objectID); + if( !clone->sessionOwner || !clone->slot->isThreadSafe) { + PK11_ExitSlotMonitor(slot); + } + + if( crv != CKR_OK ) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Failed to create new symmetric" + " key object"); + goto finish; + } + + /* wrap the new key in a Java object */ + cloneObj = JSS_PK11_wrapSymKey(env, &clone); + +finish: + if( clone!=NULL ) { + /* clone would be NULL if we completed successfully */ + PK11_FreeSymKey(clone); + } + return cloneObj; +} + diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11KeyGenerator.java b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11KeyGenerator.java new file mode 100644 index 00000000000..768f5d488fc --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11KeyGenerator.java @@ -0,0 +1,269 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs11; + +import com.netscape.jss.crypto.*; +import java.security.InvalidKeyException; +import java.security.InvalidAlgorithmParameterException; +import java.security.spec.AlgorithmParameterSpec; +import com.netscape.jss.util.Password; +import com.netscape.jss.util.UTF8Converter; +import java.io.CharConversionException; + +public final class PK11KeyGenerator implements KeyGenerator { + + // The token this key will be generated on. + private PK11Token token; + + // The algorithm to use to generate the key + private KeyGenAlgorithm algorithm; + + // The strength of the key to be generated in bits. A value of 0 means + // that the strength has not been set. This is OK for most algorithms. + private int strength=0; + + // The parameters for this algorithm. May be null for some algorithms. + private AlgorithmParameterSpec parameters; + + // Used to convert Java Password into a byte[]. + private KeyGenerator.CharToByteConverter charToByte; + + private PK11KeyGenerator() { } + + // package private constructor + PK11KeyGenerator(PK11Token token, KeyGenAlgorithm algorithm) { + if( token==null || algorithm==null ) { + throw new NullPointerException(); + } + this.token = token; + this.algorithm = algorithm; + charToByte = new KeyGenerator.CharToByteConverter() { + public byte[] convert(char[] chars) throws CharConversionException { + return UTF8Converter.UnicodeToUTF8(chars); + } + }; + } + + + /** + * Sets the character to byte converter for passwords. The default + * conversion is UTF8 with no null termination. + */ + public void setCharToByteConverter( + KeyGenerator.CharToByteConverter charToByte) + { + if( charToByte==null ) { + throw new IllegalArgumentException("CharToByteConverter is null"); + } + this.charToByte = charToByte; + } + + /** + * @param strength Key size in bits. Must be evenly divisible by 8. + */ + public void initialize(int strength) + throws InvalidAlgorithmParameterException + { + // validate the strength for our algorithm + if( PBEKeyGenParams.class.equals(algorithm.getParameterClass())) { + throw new InvalidAlgorithmParameterException("PBE keygen "+ + "algorithms require PBEKeyGenParams "); + } + if( ! algorithm.isValidStrength(strength) ) { + throw new InvalidAlgorithmParameterException(strength+ + " is not a valid strength for "+algorithm); + } + + if( strength % 8 != 0 ) { + throw new InvalidAlgorithmParameterException( + "Key strength must be divisible by 8"); + } + + this.strength = strength; + } + + public void initialize(AlgorithmParameterSpec parameters) + throws InvalidAlgorithmParameterException + { + if( PBEKeyGenParams.class.equals(algorithm.getParameterClass())) { + if( ! (parameters instanceof PBEKeyGenParams) ) { + throw new InvalidAlgorithmParameterException( + "PBE keygen algorithms require PBEKeyGenParams"); + } + this.parameters = parameters; + } else { + throw new InvalidAlgorithmParameterException( + algorithm+" does not take any parameters"); + } + } + + + /** + * Generates the key. This is the public interface, the actual + * work is done by native methods. + */ + public SymmetricKey generate() + throws IllegalStateException, TokenException, CharConversionException + { + if( PBEKeyGenParams.class.equals(algorithm.getParameterClass())) { + if(parameters==null || !(parameters instanceof PBEKeyGenParams)) { + throw new IllegalStateException( + "PBE keygen algorithms require PBEKeyGenParams"); + } + PBEKeyGenParams kgp = (PBEKeyGenParams)parameters; + + byte[] pwbytes=null; + try { + pwbytes = charToByte.convert( kgp.getPassword().getChars() ); + return generatePBE(token, algorithm, pwbytes, + kgp.getSalt(), kgp.getIterations()); + } finally { + if( pwbytes!=null ) { + Password.wipeBytes(pwbytes); + } + } + } else if( algorithm==KeyGenAlgorithm.RC4 ) { + // RC4 is the only non-PBE algorithm without a fixed key size + if( strength==0 ) { + throw new IllegalStateException( + "RC4 keygen must be initialized with a strength"); + } + return generateNormal(token, algorithm, strength); + } else { + // fixed-length algorithm, use 0 for key strength + return generateNormal(token, algorithm, 0); + } + } + + /** + * Generates an Initialization Vector using a PBE algorithm. + * In order to call this method, the algorithm must be a PBE algorithm, + * and the KeyGenerator must have been initialized with an instance + * of PBEKeyGenParams. + * + * @return The initialization vector derived from the password and salt + * using the PBE algorithm. + */ + public byte[] generatePBE_IV() + throws TokenException, CharConversionException + { + if( PBEKeyGenParams.class.equals(algorithm.getParameterClass())) { + if(parameters==null || !(parameters instanceof PBEKeyGenParams)) { + throw new IllegalStateException( + "PBE keygen algorithms require PBEKeyGenParams"); + } + PBEKeyGenParams kgp = (PBEKeyGenParams)parameters; + + byte[] pwbytes=null; + try { + pwbytes = charToByte.convert(kgp.getPassword().getChars()); + return generatePBE_IV(algorithm, pwbytes, kgp.getSalt(), + kgp.getIterations() ); + } finally { + if(pwbytes!=null) { + Password.wipeBytes(pwbytes); + } + } + } else { + throw new IllegalStateException( + "IV generation can only be performed by PBE algorithms"); + } + } + + /** + * A native method to generate an IV using a PBE algorithm. + * None of the parameters should be NULL. + */ + private static native byte[] + generatePBE_IV(KeyGenAlgorithm alg, byte[] password, byte[] salt, + int iterations) throws TokenException; + + /** + * Allows a SymmetricKey to be cloned on a different token. + * + * @exception SymmetricKey.NotExtractableException If the key material + * cannot be extracted from the current token. + * @exception InvalidKeyException If the owning token cannot process + * the key to be cloned. + */ + public SymmetricKey clone(SymmetricKey key) + throws SymmetricKey.NotExtractableException, + InvalidKeyException, TokenException + { + return clone(key, token); + } + + /** + * Allows a SymmetricKey to be cloned on a different token. + * + * @param key The key to clone. + * @param token The token on which to clone the key. + * @exception SymmetricKey.NotExtractableException If the key material + * cannot be extracted from the current token. + * @exception InvalidKeyException If the owning token cannot process + * the key to be cloned. + */ + public static SymmetricKey clone(SymmetricKey key, PK11Token token) + throws SymmetricKey.NotExtractableException, InvalidKeyException, + TokenException + { + if( ! (key instanceof PK11SymKey) ) { + throw new InvalidKeyException("Key is not a PKCS #11 key"); + } + return nativeClone(token, key); + } + + private static native SymmetricKey + nativeClone(PK11Token token, SymmetricKey toBeCloned) + throws SymmetricKey.NotExtractableException, TokenException; + + + /** + * A native method to generate a non-PBE key. + * @param strength The key size in bits, should be 0 for fixed-length + * key algorithms. + */ + private static native SymmetricKey + generateNormal(PK11Token token, KeyGenAlgorithm algorithm, int strength) + throws TokenException; + + /** + * A native method to generate a PBE key. None of the parameters should + * be null. + */ + private static native SymmetricKey + generatePBE(PK11Token token, KeyGenAlgorithm algorithm, byte[] pass, + byte[] salt, int iterationCount) throws TokenException; + +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11KeyPairGenerator.c b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11KeyPairGenerator.c new file mode 100644 index 00000000000..7aa91b97eec --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11KeyPairGenerator.c @@ -0,0 +1,338 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +#include "_jni/com_netscape_jss_pkcs11_PK11KeyPairGenerator.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + +/*********************************************************************** + * + * k e y s T o K e y P a i r + * + * Turns a SECKEYPrivateKey and a SECKEYPublicKey into a Java KeyPair + * object. + * + * INPUTS + * pPrivk + * Address of a SECKEYPrivateKey* which will be consumed by the + * KeyPair. The pointer will be set to NULL. It is not necessary + * to free this private key if the function exits successfully. + * pPubk + * Address of a SECKEYPublicKey* which will be consumed by this + * KeyPair. The pointer will be set to NULL. It is not necessary + * to free this public key if the function exits successfully. + */ +static jobject +keysToKeyPair(JNIEnv *env, SECKEYPrivateKey **pPrivk, + SECKEYPublicKey **pPubk) +{ + jobject privateKey; + jobject publicKey; + jobject keyPair=NULL; + jclass keyPairClass; + jmethodID keyPairConstructor; + + /************************************************** + * wrap the keys in Java objects + *************************************************/ + publicKey = JSS_PK11_wrapPubKey(env, pPubk); + privateKey = JSS_PK11_wrapPrivKey(env, pPrivk); + + if(publicKey==NULL || privateKey==NULL) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + goto finish; + } + + /************************************************** + * encapsulate the keys in a keypair + *************************************************/ + keyPairClass = (*env)->FindClass(env, KEY_PAIR_CLASS_NAME); + if(keyPairClass == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + keyPairConstructor = (*env)->GetMethodID( env, + keyPairClass, + KEY_PAIR_CONSTRUCTOR_NAME, + KEY_PAIR_CONSTRUCTOR_SIG); + if(keyPairConstructor == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + keyPair = (*env)->NewObject(env, + keyPairClass, + keyPairConstructor, + publicKey, + privateKey); + if(keyPair == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + +finish: + return keyPair; +} + +int PK11_NumberObjectsFor(PK11SlotInfo*, CK_ATTRIBUTE*, int); + +/********************************************************************** + * PK11KeyPairGenerator.generateRSAKeyPair + */ +JNIEXPORT jobject JNICALL +Java_com_netscape_jss_pkcs11_PK11KeyPairGenerator_generateRSAKeyPair + (JNIEnv *env, jobject this, jobject token, jint keySize, jlong publicExponent, + jboolean temporary) +{ + PK11SlotInfo* slot; + PK11RSAGenParams params; + SECKEYPrivateKey *privk=NULL; + SECKEYPublicKey *pubk=NULL; + jobject keyPair=NULL; + + PR_ASSERT(env!=NULL && this!=NULL && token!=NULL); + + /************************************************** + * get the slot pointer + *************************************************/ + if( JSS_PK11_getTokenSlotPtr(env, token, &slot) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + goto finish; + } + PR_ASSERT(slot != NULL); + + /************************************************** + * setup parameters + *************************************************/ + params.keySizeInBits = keySize; + params.pe = publicExponent; + + /************************************************** + * login to the token if necessary + *************************************************/ + if( PK11_Authenticate(slot, PR_TRUE /*loadcerts*/, NULL) + != SECSuccess) + { + JSS_throwMsg(env, TOKEN_EXCEPTION, "unable to login to token"); + goto finish; + } + + /************************************************** + * HACK to workaround bug #323494 + * On internal token, must call C_FindObjectsInit before creating + * any token objects. + *************************************************/ + if( slot==PK11_GetInternalSlot() || slot==PK11_GetInternalKeySlot() ) { + CK_ATTRIBUTE attr; + CK_OBJECT_CLASS class = CKO_PRIVATE_KEY; + + attr.type = CKA_CLASS; + attr.pValue = &class; + attr.ulValueLen = sizeof(class); + + PK11_NumberObjectsFor(slot, &attr, 1); + } + + /************************************************** + * generate the key pair on the token + *************************************************/ + privk = PK11_GenerateKeyPair( slot, + CKM_RSA_PKCS_KEY_PAIR_GEN, + (void*) ¶ms, /* params is not a ptr */ + &pubk, + !temporary, /* token (permanent) object */ + PR_TRUE, /* sensitive */ + NULL /* default PW callback */ ); + if( privk == NULL ) { + int errLength; + char *errBuf; + char *msgBuf; + + errLength = PR_GetErrorTextLength(); + if(errLength > 0) { + errBuf = PR_Malloc(errLength); + if(errBuf == NULL) { + JSS_throw(env, OUT_OF_MEMORY_ERROR); + goto finish; + } + PR_GetErrorText(errBuf); + } + msgBuf = PR_smprintf("Keypair Generation failed on token: %s", + errLength>0? errBuf : ""); + if(errLength>0) { + PR_Free(errBuf); + } + JSS_throwMsg(env, TOKEN_EXCEPTION, msgBuf); + PR_Free(msgBuf); + goto finish; + } + + /************************************************** + * wrap in a Java KeyPair object + *************************************************/ + keyPair = keysToKeyPair(env, &privk, &pubk); + if(keyPair == NULL ) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + goto finish; + } + +finish: + if(privk!=NULL) { + SECKEY_DestroyPrivateKey(privk); + } + if(pubk!=NULL) { + SECKEY_DestroyPublicKey(pubk); + } + return keyPair; +} + +#define ZERO_SECITEM(item) {(item).len=0; (item).data=NULL;} + +/********************************************************************** + * + * PK11KeyPairGenerator.generateDSAKeyPair + * + */ +JNIEXPORT jobject JNICALL +Java_com_netscape_jss_pkcs11_PK11KeyPairGenerator_generateDSAKeyPair + (JNIEnv *env, jobject this, jobject token, jbyteArray P, jbyteArray Q, + jbyteArray G, jboolean temporary) +{ + PK11SlotInfo *slot; + SECKEYPrivateKey *privk=NULL; + SECKEYPublicKey *pubk=NULL; + SECItem p, q, g; + PQGParams *params=NULL; + jobject keyPair=NULL; + + PR_ASSERT(env!=NULL && this!=NULL && token!=NULL && P!=NULL && Q!=NULL + && G!=NULL); + + /* zero these so we can free them indiscriminately later */ + ZERO_SECITEM(p); + ZERO_SECITEM(q); + ZERO_SECITEM(g); + + /************************************************** + * Get the slot pointer + *************************************************/ + if( JSS_PK11_getTokenSlotPtr(env, token, &slot) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + goto finish; + } + + /************************************************** + * Setup the parameters + *************************************************/ + if( JSS_ByteArrayToOctetString(env, P, &p) || + JSS_ByteArrayToOctetString(env, Q, &q) || + JSS_ByteArrayToOctetString(env, G, &g) ) + { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + goto finish; + } + params = PQG_NewParams(&p, &q, &g); + if(params == NULL) { + JSS_throw(env, OUT_OF_MEMORY_ERROR); + goto finish; + } + + /************************************************** + * login to the token if necessary + *************************************************/ + if( PK11_Authenticate(slot, PR_TRUE /*loadcerts*/, NULL /* default pwcb*/) + != SECSuccess) + { + JSS_throwMsg(env, TOKEN_EXCEPTION, "unable to login to token"); + goto finish; + } + + /************************************************** + * HACK to workaround bug #323494 + * On internal token, must call C_FindObjectsInit before creating + * any token objects. + *************************************************/ + if( slot==PK11_GetInternalSlot() || slot==PK11_GetInternalKeySlot() ) { + CK_ATTRIBUTE attr; + CK_OBJECT_CLASS class = CKO_PRIVATE_KEY; + + attr.type = CKA_CLASS; + attr.pValue = &class; + attr.ulValueLen = sizeof(class); + + PK11_NumberObjectsFor(slot, &attr, 1); + } + + /************************************************** + * generate the key pair on the token + *************************************************/ + privk = PK11_GenerateKeyPair( slot, + CKM_DSA_KEY_PAIR_GEN, + (void*) params, /*params is a ptr*/ + &pubk, + !temporary, /* token (permanent) object */ + PR_TRUE, /* sensitive */ + NULL /* default password callback */); + if( privk == NULL ) { + JSS_throwMsg(env, TOKEN_EXCEPTION, + "Keypair Generation failed on PKCS #11 token"); + goto finish; + } + + /************************************************** + * wrap in a Java KeyPair object + *************************************************/ + keyPair = keysToKeyPair(env, &privk, &pubk); + if(keyPair == NULL) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + goto finish; + } + +finish: + SECITEM_FreeItem(&p, PR_FALSE); + SECITEM_FreeItem(&q, PR_FALSE); + SECITEM_FreeItem(&g, PR_FALSE); + PQG_DestroyParams(params); + return keyPair; +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11KeyPairGenerator.java b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11KeyPairGenerator.java new file mode 100644 index 00000000000..850ea0adaa5 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11KeyPairGenerator.java @@ -0,0 +1,357 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs11; + +import com.netscape.jss.crypto.*; +import com.netscape.jss.util.*; +import java.math.BigInteger; +import java.security.*; +import java.security.SecureRandom; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.DSAParameterSpec; + +/** + * A Key Pair Generator implemented using PKCS #11. + * + * @see com.netscape.jss.crypto.PQGParams + */ +public final class PK11KeyPairGenerator + extends com.netscape.jss.crypto.KeyPairGeneratorSpi +{ + + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + // Constructors + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + + /** + * Constructor for PK11KeyPairGenerator. + * @param token The PKCS #11 token that the keypair will be generated on. + * @param algorithm The type of key that will be generated. Currently, + * KeyPairAlgorithm.RSA and + * KeyPairAlgorithm.DSA are supported. + */ + public PK11KeyPairGenerator(PK11Token token, KeyPairAlgorithm algorithm) + throws NoSuchAlgorithmException, TokenException + { + Assert.assert(token!=null && algorithm!=null); + + mKeygenOnInternalToken = false; + + // Make sure we can do this kind of keygen + if( ! token.doesAlgorithm(algorithm) ) { + if( token.doesAlgorithm( algorithm.getAlgFamily() ) && + token.isWritable() ) + { + // HCL will do the keygen on the internal module + // and move the key to the token. We'll say this is + // OK for now. + mKeygenOnInternalToken = true; + } else { + throw new NoSuchAlgorithmException(); + } + } + + this.token = token; + this.algorithm = algorithm; + } + + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + // Public Methods + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + + /** + * Initializes this KeyPairGenerator with the given key strength. + * + *

For DSA key generation, pre-cooked PQG values will be used + * be used if the key size is 512, 768, or 1024. Otherwise, an + * InvalidParameterException will be thrown. + * + * @param strength The strength (size) of the keys that will be generated. + * @param random Ignored + * @exception InvalidParameterException If the key strength is not + * supported by the algorithm or this implementation. + */ + public void initialize(int strength, SecureRandom random) + throws InvalidParameterException + { + if(algorithm == KeyPairAlgorithm.RSA) { + params = + new RSAParameterSpec(strength, DEFAULT_RSA_PUBLIC_EXPONENT); + } else { + Assert.assert( algorithm == KeyPairAlgorithm.DSA ); + if(strength==512) { + params = PQG512; + } else if(strength==768) { + params = PQG768; + } else if(strength==1024) { + params = PQG1024; + } else { + throw new InvalidParameterException( + "In order to use pre-cooked PQG values, key strength must"+ + "be 512, 768, or 1024."); + } + } + } + + /** + * Initializes this KeyPairGenerator with the given algorithm-specific + * parameters. + * + * @param params The algorithm-specific parameters that will govern + * key pair generation. + * @param random Ignored + * @throws InvalidAlgorithmParameterException If the parameters + * are inappropriate for the key type or are not supported by + * this implementation. + */ + public void initialize(AlgorithmParameterSpec params, SecureRandom random) + throws InvalidAlgorithmParameterException + { + if(params == null) { + Assert.notReached("Don't pass in null parameters"); + throw new InvalidAlgorithmParameterException(); + } + + if(algorithm == KeyPairAlgorithm.RSA) { + if(! (params instanceof RSAParameterSpec) ) { + throw new InvalidAlgorithmParameterException(); + } + + // Security library stores public exponent in an unsigned long + if( ((RSAParameterSpec)params).getPublicExponent().bitLength() + > 31) { + throw new InvalidAlgorithmParameterException( + "RSA Public Exponent must fit in 31 or fewer bits."); + } + } else { + Assert.assert( algorithm == KeyPairAlgorithm.DSA); + if(! (params instanceof DSAParameterSpec) ) { + throw new InvalidAlgorithmParameterException(); + } + } + this.params = params; + } + + /** + * Generates a key pair on a token. Uses parameters if they were passed + * in through a call to initialize, otherwise uses defaults. + */ + public KeyPair generateKeyPair() + throws TokenException + { + if(algorithm == KeyPairAlgorithm.RSA) { + if(params != null) { + RSAParameterSpec rsaparams = (RSAParameterSpec)params; + return generateRSAKeyPair( + token, + rsaparams.getKeySize(), + rsaparams.getPublicExponent().longValue(), + temporaryPairMode); + } else { + return generateRSAKeyPair( + token, + DEFAULT_RSA_KEY_SIZE, + DEFAULT_RSA_PUBLIC_EXPONENT.longValue(), + temporaryPairMode); + } + } else { + Assert.assert( algorithm == KeyPairAlgorithm.DSA ); + if(params==null) { + params = PQG1024; + } + DSAParameterSpec dsaParams = (DSAParameterSpec)params; + return generateDSAKeyPair( + token, + PQGParams.BigIntegerToUnsignedByteArray(dsaParams.getP()), + PQGParams.BigIntegerToUnsignedByteArray(dsaParams.getQ()), + PQGParams.BigIntegerToUnsignedByteArray(dsaParams.getG()), + temporaryPairMode ); + } + } + + /** + * @return true if the keypair generation will be done on the + * internal token and then moved to this token. + */ + public boolean + keygenOnInternalToken() { + return mKeygenOnInternalToken; + } + + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + // Native Implementation Methods + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + + /** + * Generates an RSA key pair with the given size and public exponent. + */ + private native KeyPair + generateRSAKeyPair(PK11Token token, int keySize, long publicExponent, + boolean temporary) + throws TokenException; + + /** + * Generates a DSA key pair with the given P, Q, and G values. + * P, Q, and G are stored as big-endian twos-complement octet strings. + */ + private native KeyPair + generateDSAKeyPair(PK11Token token, byte[] P, byte[] Q, byte[] G, + boolean temporary) + throws TokenException; + + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + // Defaults + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + private static final int + DEFAULT_RSA_KEY_SIZE = 2048; + + private static final BigInteger + DEFAULT_RSA_PUBLIC_EXPONENT = BigInteger.valueOf(65537); + + ////////////////////////////////////////////////////////////////////// + // 1024-bit PQG parameters + // These were generated and verified using the + // com.netscape.jss.crypto.PQGParams class. + ////////////////////////////////////////////////////////////////////// + private static final String p1024= "135839652435190934085800139191680301864221874900900696919010316554114342871389066526982023513828891845682496590926522957486592076092819515303251959435284578074745022943475516750500021440278782993316814165831392449756706958779266394680687474113495272524355075654433600922751920548192539119568200162784715902571"; + private static final String q1024= "1289225024022202541601051225376429063716419728261"; + private static final String g1024= "9365079229044517973775853147905914670746128595481021901304748201231245287028018351117994470223961367498481071639148009750748608477086914440940765659773400233006204556380834403997210445996745757996115285802608489502160956380238739417382954486304730446079375880915926936667959108637040861595671319957190194969"; + private static final String h1024= "52442921523337940900621893014039829709890959980326720828933601226740749524581606283131306291278616835323956710592993182613544059214633911716533418368425327413628234095671352084418677611348898811691107611640282098605730539089258655659910952545940615065321018163879856499128636989240131903260975031351698627473"; + private static final String seed1024= "99294487279227522120410987308721952265545668206337642687581596155167227884587528576179879564731162765515189527566190299324927751299864501359105446993895763527646668003992063667962831489586752303126546478655915858883436326503676798267446073013163508014466163441488290854738816489359449082537210762470653355837"; + private static final int counter1024 = 159; + + /** + * Pre-cooked PQG values for 1024-bit keypairs, along with the seed, + * counter, and H values needed to verify them. + */ + public static final + PQGParams PQG1024 = new PQGParams( + new BigInteger(p1024), + new BigInteger(q1024), + new BigInteger(g1024), + new BigInteger(seed1024), + counter1024, + new BigInteger(h1024)); + + + ////////////////////////////////////////////////////////////////////// + // 768-bit PQG parameters + // These were generated and verified using the + // com.netscape.jss.crypto.PQGParams class. + ////////////////////////////////////////////////////////////////////// + private static final String p768 = "1334591549939035619289567230283054603122655003980178118026955029363553392594293499178687789871628588392413078786977899109276604404053531960657701920766542891720144660923735290663050045086516783083489369477138289683344192203747015183"; + private static final String q768 = "1356132865877303155992130272917916166541739006871"; + private static final String g768 = "1024617924160404238802957719732914916383807485923819254303813897112921288261546213295904612554364830820266594592843780972915270096284099079324418834215265083315386166747220804977600828688227714319518802565604893756612386174125343163"; + private static final String seed768 = "818335465751997015393064637168438154352349887221925302425470688493624428407506863871577128315308555744979456856342994235252156194662586703244255741598129996211081771019031721876068721218509213355334043303099174315838637885951947797"; + private static final int counter768 = 80; + private static final String h768 = "640382699969409389484886950168366372251172224987648937408021020040753785108834000620831523080773231719549705102680417704245010958792653770817759388668805215557594892534053348624875390588773257372677159854630106242075665177245698591"; + + /** + * Pre-cooked PQG values for 768-bit keypairs, along with the seed, + * counter, and H values needed to verify them. + */ + public static final + PQGParams PQG768 = new PQGParams( + new BigInteger(p768), + new BigInteger(q768), + new BigInteger(g768), + new BigInteger(seed768), + counter768, + new BigInteger(h768)); + + + ////////////////////////////////////////////////////////////////////// + // 512-bit PQG parameters + // These were generated and verified using the + // com.netscape.jss.crypto.PQGParams class. + ////////////////////////////////////////////////////////////////////// + private static final String p512 = "6966483207285155416780416172202915863379050665227482416115451434656043093992853756903066653962454938528584622842487778598918381346739078775480034378802841"; + private static final String q512 = "1310301134281640075932276656367326462518739803527"; + private static final String g512 = "1765808308320938820731237312304158486199455718816858489736043318496656574508696475222741642343469219895005992985361010111736160340009944528784078083324884"; + private static final String h512 = "1166033533097555931825481846268490827226947692615252570752313574243187654088977281409544725210974913958636100321681636002587474728477655589742540645702652"; + private static final String seed512 = "1823071686803672528716836609217295942310764795778335243232708299998660956064222751939859670873282519585591423918449571513004815205037154878988595168291600"; + private static final int counter512 = 186; + + /** + * Pre-cooked PQG values for 512-bit keypairs, along with the seed, + * counter, and H values needed to verify them. + */ + public static final + PQGParams PQG512 = new PQGParams( + new BigInteger(p512), + new BigInteger(q512), + new BigInteger(g512), + new BigInteger(seed512), + counter512, + new BigInteger(h512)); + + /////////////////////////////////////////////////////////////////////// + // Test the PQG parameters + /////////////////////////////////////////////////////////////////////// + private static boolean defaultsTested = false; + private static synchronized void + testDefaults() { + if(Debug.DEBUG && !defaultsTested) { + Assert.assert(PQG1024.paramsAreValid()); + Assert.assert(PQG768.paramsAreValid()); + Assert.assert(PQG512.paramsAreValid()); + System.out.println("Default PQG Parameters passed!"); + defaultsTested = true; + } + } + + public void temporaryPairs(boolean temp) { + temporaryPairMode = temp; + } + + + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + // Private members + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + private PK11Token token; + private AlgorithmParameterSpec params; + private KeyPairAlgorithm algorithm; + private boolean mKeygenOnInternalToken; + private boolean temporaryPairMode = false; +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11KeyWrapper.c b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11KeyWrapper.c new file mode 100644 index 00000000000..66cf4df7d7d --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11KeyWrapper.c @@ -0,0 +1,833 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +#include "_jni/com_netscape_jss_pkcs11_PK11KeyWrapper.h" + +#include +#include +#include +#include +#include +#include +#include + +/* JSS includes */ +#include +#include +#include +#include +#include + +#define LITTLE_HCLHACK +#ifdef LITTLE_HCLHACK +/* PKCS #11 HACK */ +#include +#endif + +#define MAX_PRIVATE_KEY_LEN MAX_RSA_MODULUS_LEN + +/* + * This is bytes, not bits. A 2048-bit wrapped RSA private key takes up around + * 1200 bytes, because lots of "helper" values are stored along with the + * modulus and exponent. 4096 bytes will hold at least a 4096-bit RSA key. + */ +#define MAX_WRAPPED_KEY_LEN 4096 + +#ifdef LITTLE_HCLHACK + +static void +pk11_EnterKeyMonitor(PK11SymKey *symKey) { + if (!symKey->sessionOwner || !(symKey->slot->isThreadSafe)) + PK11_EnterSlotMonitor(symKey->slot); +} + +static void +pk11_ExitKeyMonitor(PK11SymKey *symKey) { + if (!symKey->sessionOwner || !(symKey->slot->isThreadSafe)) + PK11_ExitSlotMonitor(symKey->slot); +} +#endif + +/*********************************************************************** + * + * PK11KeyWrapper.nativeWrapSymWithSym + */ +JNIEXPORT jbyteArray JNICALL +Java_com_netscape_jss_pkcs11_PK11KeyWrapper_nativeWrapSymWithSym + (JNIEnv *env, jobject this, jobject tokenObj, jobject toBeWrappedObj, + jobject wrappingKeyObj, jobject algObj, jbyteArray ivBA) +{ + PK11SymKey *wrapping = NULL; + PK11SymKey *toBeWrapped = NULL; + CK_MECHANISM_TYPE mech; + SECItem wrapped; + jbyteArray wrappedBA=NULL; + SECItem *iv=NULL, *param=NULL; + SECStatus status; + + /* initialize so we can goto finish */ + wrapped.data = NULL; + wrapped.len = 0; + + /* get wrapping key */ + if( JSS_PK11_getSymKeyPtr(env, wrappingKeyObj, &wrapping)!= PR_SUCCESS) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Unable to extract symmetric " + "wrapping key"); + return NULL; + } + + /* get toBeWrapped key */ + if( JSS_PK11_getSymKeyPtr(env, toBeWrappedObj, &toBeWrapped) != PR_SUCCESS){ + JSS_throwMsg(env, TOKEN_EXCEPTION, "Unable to extract symmetric " + "to be wrapped key"); + return NULL; + } + + /* get the mechanism */ + mech = JSS_getPK11MechFromAlg(env, algObj); + if(mech == CKM_INVALID_MECHANISM) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Unrecognized algorithm"); + goto finish; + } + + /* get the parameter */ + if( ivBA ) { + iv = JSS_ByteArrayToSECItem(env, ivBA); + if( iv == NULL ) { + goto finish; /* exception was thrown */ + } + param = PK11_ParamFromIV(mech, iv); + if( param == NULL ) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Unable to create mechanism" + " parameter from initialization vector"); + goto finish; + } + } + + /* setup space for wrapped key */ + wrapped.len = MAX_WRAPPED_KEY_LEN; /* yuk! */ + wrapped.data = PR_Malloc(wrapped.len); + if(wrapped.data == NULL) { + JSS_throw(env, OUT_OF_MEMORY_ERROR); + goto finish; + } + + /* perform the wrap */ + status = PK11_WrapSymKey(mech, param, wrapping, toBeWrapped, &wrapped); + if( status != SECSuccess ) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Wrap operation failed on token"); + goto finish; + } + + /* package the wrapped data into a byte array */ + wrappedBA = JSS_SECItemToByteArray(env, &wrapped); + +finish: + if(iv) { + SECITEM_FreeItem(iv, PR_TRUE /*freeit*/); + } + if(param) { + SECITEM_FreeItem(param, PR_TRUE /*freeit*/); + } + SECITEM_FreeItem(&wrapped, PR_FALSE /*freeit*/); + + return wrappedBA; +} + +/*********************************************************************** + * + * PK11KeyWrapper.nativeWrapSymWithPub + */ +JNIEXPORT jbyteArray JNICALL +Java_com_netscape_jss_pkcs11_PK11KeyWrapper_nativeWrapSymWithPub + (JNIEnv *env, jobject this, jobject tokenObj, jobject toBeWrappedObj, + jobject wrappingKeyObj, jobject algObj, jbyteArray ivBA) +{ + SECKEYPublicKey *wrapping = NULL; + PK11SymKey *toBeWrapped = NULL; + CK_MECHANISM_TYPE mech; + SECItem wrapped; + jbyteArray wrappedBA=NULL; + SECStatus status; + + /* initialize so we can goto finish */ + wrapped.data = NULL; + wrapped.len = 0; + + /* get wrapping key */ + if( JSS_PK11_getPubKeyPtr(env, wrappingKeyObj, &wrapping)!= PR_SUCCESS) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Unable to extract public " + "wrapping key"); + return NULL; + } + + /* get toBeWrapped key */ + if( JSS_PK11_getSymKeyPtr(env, toBeWrappedObj, &toBeWrapped) != PR_SUCCESS){ + JSS_throwMsg(env, TOKEN_EXCEPTION, "Unable to extract symmetric " + "to be wrapped key"); + return NULL; + } + + /* get the mechanism */ + mech = JSS_getPK11MechFromAlg(env, algObj); + if(mech == CKM_INVALID_MECHANISM) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Unrecognized algorithm"); + goto finish; + } + + /* setup space for wrapped key */ + wrapped.len = MAX_WRAPPED_KEY_LEN; /* yuk! */ + wrapped.data = PR_Malloc(wrapped.len); + if(wrapped.data == NULL) { + JSS_throw(env, OUT_OF_MEMORY_ERROR); + goto finish; + } + + /* perform the wrap */ + status = PK11_PubWrapSymKey(mech, wrapping, toBeWrapped, &wrapped); + if( status != SECSuccess ) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Wrap operation failed on token"); + goto finish; + } + + /* package the wrapped data into a byte array */ + wrappedBA = JSS_SECItemToByteArray(env, &wrapped); + +finish: + SECITEM_FreeItem(&wrapped, PR_FALSE /*freeit*/); + + return wrappedBA; +} + + +/*********************************************************************** + * + * PK11KeyWrapper.nativeWrapPrivWithSym + */ +JNIEXPORT jbyteArray JNICALL +Java_com_netscape_jss_pkcs11_PK11KeyWrapper_nativeWrapPrivWithSym + (JNIEnv *env, jobject this, jobject tokenObj, jobject toBeWrappedObj, + jobject wrappingKeyObj, jobject algObj, jbyteArray ivBA) +{ + PK11SymKey *wrapping = NULL; + SECKEYPrivateKey *toBeWrapped= NULL; + CK_MECHANISM_TYPE mech; + SECStatus status; + SECItem wrapped; + PK11SlotInfo *slot=NULL; + jbyteArray wrappedBA=NULL; + SECItem *iv=NULL, *param=NULL; + + /* setup space for wrapped key */ + wrapped.len = MAX_WRAPPED_KEY_LEN; + wrapped.data = PR_Malloc(wrapped.len); + if(wrapped.data == NULL) { + wrapped.len = 0; + JSS_throw(env, OUT_OF_MEMORY_ERROR); + goto finish; + } + + /* get wrapping key */ + if( JSS_PK11_getSymKeyPtr(env, wrappingKeyObj, &wrapping) != PR_SUCCESS) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Unable to extract symmetric " + "wrapping key"); + return NULL; + } + + /* get toBeWrapped key */ + if( JSS_PK11_getPrivKeyPtr(env, toBeWrappedObj, &toBeWrapped) !=PR_SUCCESS){ + JSS_throwMsg(env, TOKEN_EXCEPTION, "Unable to extract private " + "to be wrapped key"); + return NULL; + } + + /* get the slot */ + if( JSS_PK11_getTokenSlotPtr(env, tokenObj, &slot) != PR_SUCCESS) { + /* exception was thrown */ + goto finish; + } + + /* get the mechanism */ + mech = JSS_getPK11MechFromAlg(env, algObj); + if(mech == CKM_INVALID_MECHANISM) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Unrecognized algorithm"); + goto finish; + } + + /* get the mechanism parameter (IV) */ + if( ivBA ) { + iv = JSS_ByteArrayToSECItem(env, ivBA); + if( iv == NULL ) { + goto finish; /* exception was thrown */ + } + param = PK11_ParamFromIV(mech, iv); + if( param == NULL ) { + JSS_throwMsg(env, TOKEN_EXCEPTION, + "Failed to convert initialization vector to parameter"); + goto finish; + } + } + + /* perform the wrap operation */ + status = PK11_WrapPrivKey(slot, wrapping, toBeWrapped, mech, param, + &wrapped, NULL /* wincx */ ); + if(status != SECSuccess) { + JSS_throwMsg(env, TOKEN_EXCEPTION, + "Wrapping operation failed on token"); + goto finish; + } + PR_ASSERT(wrapped.len>0 && wrapped.data!=NULL); + + /* package the wrapped data into a byte array */ + wrappedBA = JSS_SECItemToByteArray(env, &wrapped); + /* fall through if an exception occurs */ + +finish: + if(iv) { + SECITEM_FreeItem(iv, PR_TRUE /*freeit*/); + } + if(param) { + SECITEM_FreeItem(param, PR_TRUE /*freeit*/); + } + SECITEM_FreeItem(&wrapped, PR_FALSE /*freeit*/); + + return wrappedBA; +} + +/*********************************************************************** + * + * PK11KeyWrapper.nativeUnwrapPrivWithSym + */ +JNIEXPORT jobject JNICALL +Java_com_netscape_jss_pkcs11_PK11KeyWrapper_nativeUnwrapPrivWithSym + (JNIEnv *env, jclass clazz, jobject tokenObj, jobject unwrapperObj, + jbyteArray wrappedBA, jobject wrapAlgObj, jobject typeAlgObj, + jbyteArray publicValueBA, jbyteArray ivBA, jboolean temporary) +{ + PK11SlotInfo *slot; + PK11SymKey *unwrappingKey; + SECKEYPrivateKey *privk=NULL; + jobject privkObj=NULL; + CK_MECHANISM_TYPE wrapType, keyTypeMech; + CK_KEY_TYPE keyType; + SECItem *wrapped=NULL, *iv=NULL, *param=NULL, *pubValue=NULL; + SECItem label; /* empty secitem, doesn't need to be freed */ + PRBool token; + CK_ATTRIBUTE_TYPE attribs[4]; + int numAttribs; + + if( JSS_PK11_getTokenSlotPtr(env, tokenObj, &slot) != PR_SUCCESS) { + /* exception was thrown */ + goto finish; + } + + /* get unwrapping key */ + if( JSS_PK11_getSymKeyPtr(env, unwrapperObj, &unwrappingKey) + != PR_SUCCESS) { + /* exception was thrown */ + goto finish; + } + + /* get the wrapping mechanism */ + wrapType = JSS_getPK11MechFromAlg(env, wrapAlgObj); + if(wrapType == CKM_INVALID_MECHANISM) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Unknown algorithm"); + goto finish; + } + + /* get the mechanism parameter (IV) */ + if( ivBA ) { + iv = JSS_ByteArrayToSECItem(env, ivBA); + if( iv == NULL ) { + goto finish; /* exception was thrown */ + } + param = PK11_ParamFromIV(wrapType, iv); + if( param == NULL ) { + JSS_throwMsg(env, TOKEN_EXCEPTION, + "Failed to convert initialization vector to parameter"); + goto finish; + } + } + + /* get wrapped key from byte array */ + wrapped = JSS_ByteArrayToSECItem(env, wrappedBA); + if( wrapped == NULL ) { + /* exception was thrown */ + goto finish; + } + + /* initialize the label to be empty */ + label.len = 0; + label.data = NULL; + + /* get the public value */ + pubValue = JSS_ByteArrayToSECItem(env, publicValueBA); + if(pubValue == NULL ) { + /* exception was thrown */ + goto finish; + } + + if( temporary ) { + token = PR_FALSE; + } else { + token = PR_TRUE; + } + + /* get key type */ + keyTypeMech = JSS_getPK11MechFromAlg(env, typeAlgObj); + if( keyTypeMech == CKM_INVALID_MECHANISM ) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Unrecognized key type algorithm"); + goto finish; + } + keyType = PK11_GetKeyType(keyTypeMech, 0); + + /* figure out which operations to enable for this key */ + if( keyType == CKK_RSA ) { + attribs[0] = CKA_SIGN; + attribs[1] = CKA_DECRYPT; + attribs[2] = CKA_SIGN_RECOVER; + attribs[3] = CKA_UNWRAP; + numAttribs = 4; + } else if(keyType == CKK_DSA) { + attribs[0] = CKA_SIGN; + numAttribs = 1; + } else { + /* unknown key type */ + PR_ASSERT(PR_FALSE); + } + + /* perform the unwrap */ + privk = PK11_UnwrapPrivKey(slot, unwrappingKey, wrapType, param, wrapped, + &label, pubValue, token, PR_TRUE /*sensitive*/, keyType, + attribs, numAttribs, NULL /*wincx*/); + if( privk == NULL ) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Key Unwrap failed on token"); + goto finish; + } + + /* stuff the privk into a Java private key object. This sets privk to + * NULL */ + privkObj = JSS_PK11_wrapPrivKey(env, &privk); + +finish: + if(iv) { + SECITEM_FreeItem(iv, PR_TRUE /*free iv*/); + } + if(param) { + SECITEM_FreeItem(param, PR_TRUE /*free param*/); + } + if(wrapped) { + SECITEM_FreeItem(wrapped, PR_TRUE /*free wrapped*/); + } + if(pubValue) { + SECITEM_FreeItem(pubValue, PR_TRUE /*free pubValue*/); + } + PR_ASSERT(privk==NULL); + PR_ASSERT( privkObj!=NULL || (*env)->ExceptionOccurred(env) ); + return privkObj; +} + +/*********************************************************************** + * + * PK11KeyWrapper.nativeUnwrapSymWithSym + */ +JNIEXPORT jobject JNICALL +Java_com_netscape_jss_pkcs11_PK11KeyWrapper_nativeUnwrapSymWithSym + (JNIEnv *env, jclass clazz, jobject tokenObj, jobject unwrapperObj, + jbyteArray wrappedBA, jobject wrapAlgObj, jobject typeAlgObj, + jint keyLen, jbyteArray ivBA) +{ + CK_BBOOL cktrue = CK_TRUE; /* sigh */ + CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; + CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; + CK_ULONG key_size = 0; + CK_ATTRIBUTE keyTemplate[] = { + { CKA_CLASS, NULL, 0}, + { CKA_KEY_TYPE, NULL, 0}, + { CKA_ENCRYPT, NULL, 0}, + { CKA_DECRYPT, NULL, 0}, + { CKA_WRAP, NULL, 0}, + { CKA_UNWRAP, NULL, 0}, + { CKA_VALUE_LEN, NULL, 0}, + }; + int templateCount = sizeof(keyTemplate)/sizeof(keyTemplate[0]); + PK11SymKey *symKey=NULL, *wrappingKey=NULL; + CK_MECHANISM mechanism; + CK_MECHANISM_TYPE wrappingMech, keyTypeMech; + CK_RV crv; + CK_ATTRIBUTE *attrs = keyTemplate; + PK11SlotInfo *slot=NULL; + SECItem *wrappedKey=NULL, *iv=NULL, *param=NULL; + jobject keyObj = NULL; + + /* get the slot */ + if( JSS_PK11_getTokenSlotPtr(env, tokenObj, &slot) != PR_SUCCESS) { + /* exception was thrown */ + goto finish; + } + + /* get key type */ + keyTypeMech = JSS_getPK11MechFromAlg(env, typeAlgObj); + if( keyTypeMech == CKM_INVALID_MECHANISM ) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Unrecognized key type algorithm"); + goto finish; + } + + /* get wrapping key */ + if( JSS_PK11_getSymKeyPtr(env, unwrapperObj, &wrappingKey) != PR_SUCCESS) { + /* exception was thrown */ + goto finish; + } + + /* get wrapping mechanism */ + wrappingMech = JSS_getPK11MechFromAlg(env, wrapAlgObj); + if( keyTypeMech == CKM_INVALID_MECHANISM ) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Unrecognized wrapping algorithm"); + goto finish; + } + + /* set up the attribute template for the key */ + PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass)); attrs++; + PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType)); attrs++; + PK11_SETATTRS(attrs, CKA_ENCRYPT, &cktrue, 1); attrs++; + PK11_SETATTRS(attrs, CKA_DECRYPT, &cktrue, 1); attrs++; + PK11_SETATTRS(attrs, CKA_WRAP, &cktrue, 1); attrs++; + PK11_SETATTRS(attrs, CKA_UNWRAP, &cktrue, 1); attrs++; + PK11_SETATTRS(attrs, CKA_VALUE_LEN, &key_size, sizeof(key_size)); attrs++; + + /* create a key Structure */ + symKey = PK11_CreateSymKey(slot,keyTypeMech,NULL /*wincx*/); + if (symKey == NULL) { + JSS_throwMsg(env, TOKEN_EXCEPTION, + "Failed to create new symmetric key handle"); + goto finish; + } + + keyType = PK11_GetKeyType(keyTypeMech, keyLen); + key_size = keyLen; + symKey->size = keyLen; + symKey->origin = PK11_OriginUnwrap; + if (key_size == 0) templateCount--; + + mechanism.mechanism = wrappingMech; + /* get the mechanism parameter (IV) */ + if (ivBA == NULL) { + param = PK11_ParamFromIV(wrappingMech,NULL); + } else { + iv = JSS_ByteArrayToSECItem(env, ivBA); + if( iv == NULL ) { + goto finish; /* exception was thrown */ + } + param = PK11_ParamFromIV(wrappingMech, iv); + if( param == NULL ) { + JSS_throwMsg(env, TOKEN_EXCEPTION, + "Failed to convert initialization vector to parameter"); + goto finish; + } + } + if (param) { + mechanism.pParameter = param->data; + mechanism.ulParameterLen = param->len; + } else { + mechanism.pParameter = NULL; + mechanism.ulParameterLen = 0; + } + + /* get the wrapped key */ + wrappedKey = JSS_ByteArrayToSECItem(env, wrappedBA); + if( wrappedKey == NULL ) { + /* exception was thrown */ + goto finish; + } + + pk11_EnterKeyMonitor(symKey); + crv = PK11_GETTAB(slot)->C_UnwrapKey(symKey->session,&mechanism, + wrappingKey->objectID, + wrappedKey->data, wrappedKey->len, keyTemplate, templateCount, + &symKey->objectID); + pk11_ExitKeyMonitor(symKey); + if( crv != CKR_OK ) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Failed to unwrap key"); + goto finish; + } + + /* wrap the symmetric key in a Java object. This will clear symKey */ + keyObj = JSS_PK11_wrapSymKey(env, &symKey); + +finish: + if(wrappedKey) { + SECITEM_FreeItem(wrappedKey, PR_TRUE /*free wrappedKey*/); + } + if(iv) { + SECITEM_FreeItem(iv, PR_TRUE /*free iv*/); + } + if(param) { + SECITEM_FreeItem(param, PR_TRUE /*free param*/); + } + if( symKey ) { + PK11_FreeSymKey(symKey); + } + return keyObj; +} + +/*********************************************************************** + * + * PK11KeyWrapper.nativeUnwrapSymWithPriv + */ +JNIEXPORT jobject JNICALL +Java_com_netscape_jss_pkcs11_PK11KeyWrapper_nativeUnwrapSymWithPriv + (JNIEnv *env, jclass clazz, jobject tokenObj, jobject unwrapperObj, + jbyteArray wrappedBA, jobject wrapAlgObj, jobject typeAlgObj, + jint keyLen, jbyteArray ivBA) +{ + CK_BBOOL cktrue = CK_TRUE; /* sigh */ + CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; + CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; + CK_ULONG key_size = 0; + CK_ATTRIBUTE keyTemplate[] = { + { CKA_CLASS, NULL, 0}, + { CKA_KEY_TYPE, NULL, 0}, + { CKA_ENCRYPT, NULL, 0}, + { CKA_DECRYPT, NULL, 0}, + { CKA_WRAP, NULL, 0}, + { CKA_UNWRAP, NULL, 0}, + { CKA_VALUE_LEN, NULL, 0}, + }; + int templateCount = sizeof(keyTemplate)/sizeof(keyTemplate[0]); + PK11SymKey *symKey=NULL; + CK_MECHANISM mechanism; + CK_MECHANISM_TYPE wrappingMech, keyTypeMech; + CK_RV crv; + CK_ATTRIBUTE *attrs = keyTemplate; + PK11SlotInfo *slot=NULL; + SECItem *wrappedKey=NULL, *iv=NULL, *param=NULL; + jobject keyObj=NULL; + SECKEYPrivateKey *wrappingKey=NULL; + + /* get the slot */ + if( JSS_PK11_getTokenSlotPtr(env, tokenObj, &slot) != PR_SUCCESS) { + /* exception was thrown */ + goto finish; + } + + /* since this is a private key op, we may need to login */ + PK11_HandlePasswordCheck(slot, NULL /*wincx*/); + + /* get key type */ + keyTypeMech = JSS_getPK11MechFromAlg(env, typeAlgObj); + if( keyTypeMech == CKM_INVALID_MECHANISM ) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Unrecognized key type algorithm"); + goto finish; + } + + /* get wrapping key */ + if( JSS_PK11_getPrivKeyPtr(env, unwrapperObj, &wrappingKey) != PR_SUCCESS) { + /* exception was thrown */ + goto finish; + } + + /* get wrapping mechanism */ + wrappingMech = JSS_getPK11MechFromAlg(env, wrapAlgObj); + if( keyTypeMech == CKM_INVALID_MECHANISM ) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Unrecognized wrapping algorithm"); + goto finish; + } + + /* set up the attribute template for the key */ + PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass)); attrs++; + PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType)); attrs++; + PK11_SETATTRS(attrs, CKA_ENCRYPT, &cktrue, 1); attrs++; + PK11_SETATTRS(attrs, CKA_DECRYPT, &cktrue, 1); attrs++; + PK11_SETATTRS(attrs, CKA_WRAP, &cktrue, 1); attrs++; + PK11_SETATTRS(attrs, CKA_UNWRAP, &cktrue, 1); attrs++; + PK11_SETATTRS(attrs, CKA_VALUE_LEN, &key_size, sizeof(key_size)); attrs++; + + /* create a key Structure */ + symKey = PK11_CreateSymKey(slot,keyTypeMech,NULL /*wincx*/); + if (symKey == NULL) { + JSS_throwMsg(env, TOKEN_EXCEPTION, + "Failed to create new symmetric key handle"); + goto finish; + } + + keyType = PK11_GetKeyType(keyTypeMech, keyLen); + key_size = keyLen; + symKey->size = keyLen; + symKey->origin = PK11_OriginUnwrap; + if (key_size == 0) templateCount--; + + mechanism.mechanism = wrappingMech; + /* get the mechanism parameter (IV) */ + if (ivBA == NULL) { + param = PK11_ParamFromIV(wrappingMech, NULL); + } else { + iv = JSS_ByteArrayToSECItem(env, ivBA); + if( iv == NULL ) { + goto finish; /* exception was thrown */ + } + param = PK11_ParamFromIV(wrappingMech, iv); + if( param == NULL ) { + JSS_throwMsg(env, TOKEN_EXCEPTION, + "Failed to convert initialization vector to parameter"); + goto finish; + } + } + if (param) { + mechanism.pParameter = param->data; + mechanism.ulParameterLen = param->len; + } else { + mechanism.pParameter = NULL; + mechanism.ulParameterLen = 0; + } + + /* get the wrapped key */ + wrappedKey = JSS_ByteArrayToSECItem(env, wrappedBA); + if( wrappedKey == NULL ) { + /* exception was thrown */ + goto finish; + } + + pk11_EnterKeyMonitor(symKey); + crv = PK11_GETTAB(slot)->C_UnwrapKey(symKey->session,&mechanism, + wrappingKey->pkcs11ID, + wrappedKey->data, wrappedKey->len, keyTemplate, templateCount, + &symKey->objectID); + pk11_ExitKeyMonitor(symKey); + if( crv != CKR_OK ) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Failed to unwrap key"); + goto finish; + } + + /* Put the symmetric key into a Java object. This will clear symKey */ + keyObj = JSS_PK11_wrapSymKey(env, &symKey); + +finish: + if(wrappedKey) { + SECITEM_FreeItem(wrappedKey, PR_TRUE /*free wrappedKey*/); + } + if(iv) { + SECITEM_FreeItem(iv, PR_TRUE /*free iv*/); + } + if(param) { + SECITEM_FreeItem(param, PR_TRUE /*free param*/); + } + if( symKey ) { + PK11_FreeSymKey(symKey); + } + return keyObj; +} + +/*********************************************************************** + * + * J S S _ P K 1 1 _ g e t E r r o r S t r i n g + * + * Returns a simple error string for a given PKCS #11 error. + */ +PR_IMPLEMENT( char* ) +JSS_PK11_getErrorString(CK_RV crv) +{ + switch(crv) { + case CKR_ATTRIBUTE_READ_ONLY: + return "CKR_ATTRIBUTE_READ_ONLY"; + case CKR_ATTRIBUTE_TYPE_INVALID: + return "CKR_ATTRIBUTE_TYPE_INVALID"; + case CKR_ATTRIBUTE_VALUE_INVALID: + return "CKR_ATTRIBUTE_VALUE_INVALID"; + case CKR_BUFFER_TOO_SMALL: + return "CKR_BUFFER_TOO_SMALL"; + case CKR_CRYPTOKI_NOT_INITIALIZED: + return "CKR_CRYPTOKI_NOT_INITIALIZED"; + case CKR_DEVICE_ERROR: + return "CKR_DEVICE_ERROR"; + case CKR_DEVICE_MEMORY: + return "CKR_DEVICE_MEMORY"; + case CKR_DEVICE_REMOVED: + return "CKR_DEVICE_REMOVED"; + case CKR_FUNCTION_CANCELED: + return "CKR_FUNCTION_CANCELED"; + case CKR_FUNCTION_FAILED: + return "CKR_FUNCTION_FAILED"; + case CKR_GENERAL_ERROR: + return "CKR_GENERAL_ERROR"; + case CKR_HOST_MEMORY: + return "CKR_HOST_MEMORY"; + case CKR_KEY_HANDLE_INVALID: + return "CKR_KEY_HANDLE_INVALID"; + case CKR_KEY_NOT_WRAPPABLE: + return "CKR_KEY_NOT_WRAPPABLE"; + case CKR_KEY_SIZE_RANGE: + return "CKR_KEY_SIZE_RANGE"; + case CKR_KEY_UNEXTRACTABLE: + return "CKR_KEY_UNEXTRACTABLE"; + case CKR_MECHANISM_INVALID: + return "CKR_MECHANISM_INVALID"; + case CKR_MECHANISM_PARAM_INVALID: + return "CKR_MECHANISM_PARAM_INVALID"; + case CKR_OK: + return "CKR_OK"; + case CKR_OPERATION_ACTIVE: + return "CKR_OPERATION_ACTIVE"; + case CKR_SESSION_CLOSED: + return "CKR_SESSION_CLOSED"; + case CKR_SESSION_HANDLE_INVALID: + return "CKR_SESSION_HANDLE_INVALID"; + case CKR_SESSION_READ_ONLY: + return "CKR_SESSION_READ_ONLY"; + case CKR_TEMPLATE_INCOMPLETE: + return "CKR_TEMPLATE_INCOMPLETE"; + case CKR_TEMPLATE_INCONSISTENT: + return "CKR_TEMPLATE_INCONSISTENT"; + case CKR_TOKEN_WRITE_PROTECTED: + return "CKR_TOKEN_WRITE_PROTECTED"; + case CKR_UNWRAPPING_KEY_HANDLE_INVALID: + return "CKR_UNWRAPPING_KEY_HANDLE_INVALID"; + case CKR_UNWRAPPING_KEY_SIZE_RANGE: + return "CKR_UNWRAPPING_KEY_SIZE_RANGE"; + case CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT: + return "CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT"; + case CKR_USER_NOT_LOGGED_IN: + return "CKR_USER_NOT_LOGGED_IN"; + case CKR_WRAPPED_KEY_INVALID: + return "CKR_WRAPPED_KEY_INVALID"; + case CKR_WRAPPED_KEY_LEN_RANGE: + return "CKR_WRAPPED_KEY_LEN_RANGE"; + case CKR_WRAPPING_KEY_HANDLE_INVALID: + return "CKR_WRAPPING_KEY_HANDLE_INVALID"; + case CKR_WRAPPING_KEY_SIZE_RANGE: + return "CKR_WRAPPING_KEY_SIZE_RANGE"; + case CKR_WRAPPING_KEY_TYPE_INCONSISTENT: + return "CKR_WRAPPING_KEY_TYPE_INCONSISTENT"; + default: + return "PKCS #11 error"; + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11KeyWrapper.java b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11KeyWrapper.java new file mode 100644 index 00000000000..e4d8625efe5 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11KeyWrapper.java @@ -0,0 +1,533 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs11; + +import com.netscape.jss.crypto.*; +import java.security.spec.AlgorithmParameterSpec; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import com.netscape.jss.util.Assert; +import java.security.PublicKey; +import java.security.interfaces.RSAPublicKey; +import java.security.interfaces.DSAPublicKey; + +final class PK11KeyWrapper implements KeyWrapper { + + private PK11Token token; + private KeyWrapAlgorithm algorithm; + private int state=UNINITIALIZED; + private AlgorithmParameterSpec parameters=null; + private SymmetricKey symKey=null; + private PrivateKey privKey=null; + private PublicKey pubKey=null; + private byte[] IV=null; + + // states + private static final int UNINITIALIZED=0; + private static final int WRAP=1; + private static final int UNWRAP=2; + + private PK11KeyWrapper() { } + + PK11KeyWrapper(PK11Token token, KeyWrapAlgorithm algorithm) { + this.token = token; + this.algorithm = algorithm; + } + + public void initWrap(SymmetricKey wrappingKey, + AlgorithmParameterSpec parameters) + throws InvalidKeyException, InvalidAlgorithmParameterException + { + initWrap(parameters); + checkWrapper(wrappingKey); + this.symKey = wrappingKey; + } + + public void initWrap(PublicKey wrappingKey, + AlgorithmParameterSpec parameters) + throws InvalidKeyException, InvalidAlgorithmParameterException + { + initWrap(parameters); + checkWrapper(wrappingKey); + this.pubKey = wrappingKey; + } + + /** + * Does everything that is key-independent for initializing a wrap. + */ + private void initWrap(AlgorithmParameterSpec parameters) + throws InvalidAlgorithmParameterException + { + reset(); + + checkParams(parameters); + + this.parameters = parameters; + state = WRAP; + } + + public void initUnwrap(PrivateKey unwrappingKey, + AlgorithmParameterSpec parameters) + throws InvalidKeyException, InvalidAlgorithmParameterException + { + initUnwrap(parameters); + checkWrapper(unwrappingKey); + this.privKey = unwrappingKey; + } + + public void initUnwrap(SymmetricKey unwrappingKey, + AlgorithmParameterSpec parameters) + throws InvalidKeyException, InvalidAlgorithmParameterException + { + initUnwrap(parameters); + checkWrapper(unwrappingKey); + this.symKey = unwrappingKey; + } + + /** + * Does the key-independent parts of initializing an unwrap. + */ + private void initUnwrap(AlgorithmParameterSpec parameters) + throws InvalidAlgorithmParameterException + { + reset(); + + checkParams(parameters); + + this.parameters = parameters; + state = UNWRAP; + } + + /** + * Makes sure the key is right for the algorithm. + */ + private void checkWrapper(PublicKey key) throws InvalidKeyException { + if( key==null ) { + throw new InvalidKeyException("Key is null"); + } + if( ! (key instanceof PK11PubKey) ) { + throw new InvalidKeyException("Key is not a PKCS #11 key"); + } + try { + KeyType type = KeyType.getKeyTypeFromAlgorithm(algorithm); + if( (type == KeyType.RSA && !(key instanceof RSAPublicKey)) || + (type == KeyType.DSA && !(key instanceof DSAPublicKey)) ) { + throw new InvalidKeyException("Key is not the right type for "+ + "this algorithm"); + } + } catch( NoSuchAlgorithmException e ) { + Assert.notReached("unable to find algorithm from key type"); + } + } + + /** + * Makes sure the key lives on the token and is right for the algorithm. + */ + private void checkWrapper(SymmetricKey key) + throws InvalidKeyException + { + if( key==null ) { + throw new InvalidKeyException("Key is null"); + } + if( ! key.getOwningToken().equals(token) ) { + throw new InvalidKeyException("Key does not reside on the "+ + "current token"); + } + if( ! (key instanceof PK11SymKey) ) { + throw new InvalidKeyException("Key is not a PKCS #11 key"); + } + try { + if( ((PK11SymKey)key).getKeyType() != + KeyType.getKeyTypeFromAlgorithm(algorithm) ) { + throw new InvalidKeyException("Key is not the right type for"+ + " this algorithm"); + } + } catch( NoSuchAlgorithmException e ) { + Assert.notReached("Unknown algorithm"); + } + } + + /** + * Makes sure the key is on the token and is right for the algorithm. + */ + private void checkWrapper(PrivateKey key) + throws InvalidKeyException + { + if( key==null ) { + throw new InvalidKeyException("Key is null"); + } + if( ! key.getOwningToken().equals(token) ) { + throw new InvalidKeyException("Key does not reside on the "+ + "current token"); + } + if( ! (key instanceof PK11PrivKey) ) { + throw new InvalidKeyException("Key is not a PKCS #11 key"); + } + try { + if( ((PK11PrivKey)key).getKeyType() != + KeyType.getKeyTypeFromAlgorithm(algorithm) ) { + throw new InvalidKeyException("Key is not the right type for"+ + " this algorithm"); + } + } catch( NoSuchAlgorithmException e ) { + Assert.notReached("Unknown algorithm"); + } + } + + private void checkParams(AlgorithmParameterSpec params) + throws InvalidAlgorithmParameterException + { + Class paramClass = algorithm.getParameterClass(); + if(params==null) { + if(paramClass != null) { + // this algorithm takes a parameter, but none was given + throw new InvalidAlgorithmParameterException(algorithm+ + " requires an algorithm parameter"); + } + } else { + if( paramClass == null ) { + //this algorithm doesn't take a param, but one was given + throw new InvalidAlgorithmParameterException(algorithm+ + " does not take a parameter"); + } else if( ! ( paramClass.isInstance(params) ) ) { + throw new InvalidAlgorithmParameterException(algorithm+ + " expects a parameter of type "+paramClass); + } + + if( params instanceof IVParameterSpec ) { + IV = ((IVParameterSpec)params).getIV(); + } + } + } + + public byte[] + wrap(PrivateKey toBeWrapped) + throws InvalidKeyException, IllegalStateException, TokenException + { + if( state != WRAP ) { + throw new IllegalStateException(); + } + + checkWrappee(toBeWrapped); + + if( symKey != null ) { + Assert.assert( privKey==null && pubKey==null ); + return nativeWrapPrivWithSym(token, toBeWrapped, symKey, algorithm, + IV); + } else { + throw new InvalidKeyException( + "Wrapping a private key with a public key is not supported"); + /* + Assert.assert( pubKey!=null && privKey==null && symKey==null ); + return nativeWrapPrivWithPub(token, toBeWrapped, pubKey, algorithm, + IV); + */ + } + } + + public byte[] + wrap(SymmetricKey toBeWrapped) + throws InvalidKeyException, IllegalStateException, TokenException + { + if( state != WRAP ) { + throw new IllegalStateException(); + } + + checkWrappee(toBeWrapped); + + if( symKey != null ) { + Assert.assert( privKey==null && pubKey==null ); + return nativeWrapSymWithSym(token, toBeWrapped, symKey, algorithm, + IV); + } else { + Assert.assert( pubKey!=null && privKey==null && symKey==null ); + return nativeWrapSymWithPub(token, toBeWrapped, pubKey, algorithm, + IV); + } + } + + /** + * Makes sure the key lives on the right token. + */ + private void + checkWrappee(SymmetricKey symKey) throws InvalidKeyException { + if( symKey == null ) { + throw new InvalidKeyException("key to be wrapped is null"); + } + if( ! (symKey instanceof PK11SymKey) ) { + throw new InvalidKeyException("key to be wrapped is not a "+ + "PKCS #11 key"); + } + if( ! symKey.getOwningToken().equals(token) ) { + throw new InvalidKeyException("key to be wrapped does not live"+ + " on the same token as the wrapping key"); + } + } + + /** + * Makes sure the key lives on the right token. + */ + private void + checkWrappee(PrivateKey privKey) throws InvalidKeyException { + if( privKey == null ) { + throw new InvalidKeyException("key to be wrapped is null"); + } + if( ! (privKey instanceof PK11PrivKey) ) { + throw new InvalidKeyException("key to be wrapped is not a "+ + "PKCS #11 key"); + } + if( ! privKey.getOwningToken().equals(token) ) { + throw new InvalidKeyException("key to be wrapped does not live"+ + " on the same token as the wrapping key"); + } + } + + /** + * Wrap a symmetric with a symmetric + */ + private static native byte[] + nativeWrapSymWithSym(PK11Token token, SymmetricKey toBeWrapped, + SymmetricKey wrappingKey, KeyWrapAlgorithm alg, byte[] IV) + throws TokenException; + + /** + * Wrap a symmetric with a public + */ + private static native byte[] + nativeWrapSymWithPub(PK11Token token, SymmetricKey toBeWrapped, + PublicKey wrappingKey, KeyWrapAlgorithm alg, byte[] IV) + throws TokenException; + + /** + * Wrap a private with a symmetric + */ + private static native byte[] + nativeWrapPrivWithSym(PK11Token token, PrivateKey toBeWrapped, + SymmetricKey wrappingKey, KeyWrapAlgorithm alg, byte[] IV) + throws TokenException; + + /** + * Wrap a private with a public. + * NOTE: This operation is not supported by the security library. + private static native byte[] + nativeWrapPrivWithPub(PK11Token token, PrivateKey toBeWrapped, + PublicKey wrappingKey, + KeyWrapAlgorithm alg, byte[] IV) + throws TokenException; + */ + + /** + * Unwraps a private key, creating a permanent private key object. + * A permanent private key object resides on a token until it is + * explicitly deleted from the token. + */ + public PrivateKey + unwrapPrivate(byte[] wrapped, PrivateKey.Type type, PublicKey publicKey) + throws TokenException, InvalidKeyException, IllegalStateException + { + return baseUnwrapPrivate(wrapped, type, publicKey, false); + } + + /** + * Unwraps a private key, creating a temporary private key object. + * A temporary + * private key is one that does not permanently reside on a token. + * As soon as it is garbage-collected, it is gone forever. + */ + public PrivateKey + unwrapTemporaryPrivate(byte[] wrapped, PrivateKey.Type type, + PublicKey publicKey) + throws TokenException, InvalidKeyException, IllegalStateException + { + return baseUnwrapPrivate(wrapped, type, publicKey, true); + } + + private PrivateKey + baseUnwrapPrivate(byte[] wrapped, PrivateKey.Type type, + PublicKey publicKey, boolean temporary) + throws TokenException, InvalidKeyException, IllegalStateException + { + if( state != UNWRAP ) { + throw new IllegalStateException(); + } + + byte[] publicValue = extractPublicValue(publicKey, type); + + if( symKey != null ) { + Assert.assert(pubKey==null && privKey==null); + return nativeUnwrapPrivWithSym(token, symKey, wrapped, algorithm, + algFromType(type), publicValue, IV, temporary ); + } else { + throw new InvalidKeyException("Unwrapping a private key with" + + " a private key is not supported"); + /* + Assert.assert(privKey!=null && pubKey==null && symKey==null); + return nativeUnwrapPrivWithPriv(token, privKey, wrapped, algorithm, + algFromType(type), publicValue, IV, temporary ); + */ + } + } + + /** + * Extracts the "public value" from a public key. The public value is + * used to construct the key identifier (CKA_ID). Also, the internal token + * stores the DSA public value along with the private key. + */ + private static byte[] + extractPublicValue(PublicKey publicKey, PrivateKey.Type type) + throws InvalidKeyException + { + if( publicKey == null ) { + throw new InvalidKeyException("publicKey is null"); + } + if( type == PrivateKey.RSA ) { + if( !(publicKey instanceof RSAPublicKey)) { + throw new InvalidKeyException("Type of public key does not "+ + "match type of private key"); + } + return ((RSAPublicKey)publicKey).getModulus().toByteArray(); + } else if(type == PrivateKey.DSA) { + if( !(publicKey instanceof DSAPublicKey) ) { + throw new InvalidKeyException("Type of public key does not "+ + "match type of private key"); + } + return ((DSAPublicKey)publicKey).getY().toByteArray(); + } else { + Assert.notReached("Unknown private key type"); + return new byte[] { }; + } + } + + + public SymmetricKey + unwrapSymmetric(byte[] wrapped, SymmetricKey.Type type, int keyLen) + throws TokenException, IllegalStateException, + InvalidAlgorithmParameterException + { + if( state != UNWRAP ) { + throw new IllegalStateException(); + } + + if( (! algorithm.isPadded()) && (type == SymmetricKey.RC4) ) { + if( keyLen <= 0 ) { + throw new InvalidAlgorithmParameterException( + "RC4 keys wrapped in unpadded algorithms need key length"+ + " specified when unwrapping"); + } + } else { + // Don't use the key length + keyLen = 0; + } + + if( symKey != null ) { + Assert.assert(pubKey==null && privKey==null); + return nativeUnwrapSymWithSym(token, symKey, wrapped, algorithm, + algFromType(type), keyLen, IV ); + } else { + Assert.assert(privKey!=null && pubKey==null && symKey==null); + return nativeUnwrapSymWithPriv(token, privKey, wrapped, algorithm, + algFromType(type), keyLen, IV ); + } + } + + private static Algorithm + algFromType(PrivateKey.Type type) { + if(type == PrivateKey.RSA) { + return KeyPairAlgorithm.RSAFamily; + } else { + Assert.assert(type == PrivateKey.DSA); + return KeyPairAlgorithm.DSAFamily; + } + } + + private static Algorithm + algFromType(SymmetricKey.Type type) { + if( type == SymmetricKey.DES ) { + return EncryptionAlgorithm.DES_ECB; + } else if( type == SymmetricKey.DES3 ) { + return EncryptionAlgorithm.DES3_ECB; + } else { + Assert.assert( type == SymmetricKey.RC4 ); + return EncryptionAlgorithm.RC4; + } + } + + /** + * Unwrap a private with a symmetric. + */ + private static native PrivateKey + nativeUnwrapPrivWithSym(PK11Token token, SymmetricKey unwrappingKey, + byte[] wrappedKey, KeyWrapAlgorithm alg, Algorithm type, + byte[] publicValue, byte[] IV, boolean temporary) + throws TokenException; + + /** + * Unwrap a private with a private. + * NOTE: this is not supported by the security library. + private static native PrivateKey + nativeUnwrapPrivWithPriv(PK11Token token, PrivateKey unwrappingKey, + byte[] wrappedKey, KeyWrapAlgorithm alg, Algorithm type, + byte[] publicValue, byte[] IV, boolean temporary) + throws TokenException; + */ + + /** + * Unwrap a symmetric with a symmetric. + */ + private static native SymmetricKey + nativeUnwrapSymWithSym(PK11Token token, SymmetricKey unwrappingKey, + byte[] wrappedKey, + KeyWrapAlgorithm alg, Algorithm type, int keyLen, byte[] IV) + throws TokenException; + + /** + * Unwrap a symmetric with a private. + */ + private static native SymmetricKey + nativeUnwrapSymWithPriv(PK11Token token, PrivateKey unwrappingKey, + byte[] wrappedKey, KeyWrapAlgorithm alg, Algorithm type, int keyLen, + byte[] IV) + throws TokenException; + + + private void reset() { + state = UNINITIALIZED; + symKey = null; + privKey = null; + pubKey = null; + parameters = null; + IV = null; + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11MessageDigest.c b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11MessageDigest.c new file mode 100644 index 00000000000..0a51294c7c3 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11MessageDigest.c @@ -0,0 +1,210 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +#include "_jni/com_netscape_jss_pkcs11_PK11MessageDigest.h" + +#include +#include +#include +#include +#include + +/* JSS includes */ +#include +#include +#include +#include +#include + + +/*********************************************************************** + * + * PK11MessageDigest.initDigest + * + */ +JNIEXPORT jobject JNICALL +Java_com_netscape_jss_pkcs11_PK11MessageDigest_initDigest + (JNIEnv *env, jclass clazz, jobject algObj) +{ + SECOidTag alg; + PK11Context *context=NULL; + + alg = JSS_getOidTagFromAlg(env, algObj); + PR_ASSERT( alg != SEC_OID_UNKNOWN ); /* we checked already in Java */ + + context = PK11_CreateDigestContext(alg); + if( context == NULL ) { + JSS_throwMsg(env, DIGEST_EXCEPTION, "Unable to create digest context"); + return NULL; + } + + return JSS_PK11_wrapCipherContextProxy(env, &context); +} + +/*********************************************************************** + * + * PK11MessageDigest.initHMAC + * + */ +JNIEXPORT jobject JNICALL +Java_com_netscape_jss_pkcs11_PK11MessageDigest_initHMAC + (JNIEnv *env, jclass clazz, jobject tokenObj, jobject algObj, + jobject keyObj) +{ + PK11SymKey *origKey = NULL, *newKey=NULL; + PK11Context *context = NULL; + CK_MECHANISM_TYPE mech; + SECItem param; + PK11SlotInfo *slot=NULL; + jobject contextObj=NULL; + + mech = JSS_getPK11MechFromAlg(env, algObj); + PR_ASSERT( mech != CKM_INVALID_MECHANISM ); /* we checked already in Java */ + + if( JSS_PK11_getSymKeyPtr(env, keyObj, &origKey) != PR_SUCCESS ) { + /* exception was thrown */ + goto finish; + } + + /* copy the key, setting the CKA_SIGN attribute */ + newKey = pk11_CopyToSlot(PK11_GetSlotFromKey(origKey), mech, CKA_SIGN, + origKey); + if( newKey == NULL ) { + JSS_throwMsg(env, DIGEST_EXCEPTION, + "Unable to set CKA_SIGN attribute on symmetric key"); + goto finish; + } + + param.data = NULL; + param.len = 0; + + context = PK11_CreateContextBySymKey(mech, CKA_SIGN, newKey, ¶m); + if( context == NULL ) { + JSS_throwMsg(env, DIGEST_EXCEPTION, + "Unable to initialize digest context"); + goto finish; + } + + contextObj = JSS_PK11_wrapCipherContextProxy(env, &context); +finish: + if(newKey) { + /* SymKeys are ref counted, and the context will free it's ref + * when it is destroyed */ + PK11_FreeSymKey(newKey); + } + + return contextObj; +} + + +/*********************************************************************** + * + * PK11MessageDigest.update + * + */ +JNIEXPORT void JNICALL +Java_com_netscape_jss_pkcs11_PK11MessageDigest_update + (JNIEnv *env, jclass clazz, jobject proxyObj, jbyteArray inbufBA, + jint offset, jint len) +{ + + PK11Context *context = NULL; + jbyte* bytes = NULL; + + if( JSS_PK11_getCipherContext(env, proxyObj, &context) != PR_SUCCESS ) { + /* exception was thrown */ + goto finish; + } + + PR_ASSERT( (*env)->GetArrayLength(env, inbufBA) >= offset+len ); + bytes = (*env)->GetByteArrayElements(env, inbufBA, NULL); + if( bytes == NULL ) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + if( PK11_DigestOp(context, (unsigned char*)(bytes+offset), len) + != SECSuccess ) + { + JSS_throwMsg(env, DIGEST_EXCEPTION, "Digest operation failed"); + goto finish; + } + +finish: + if(bytes) { + (*env)->ReleaseByteArrayElements(env, inbufBA, bytes, JNI_ABORT); + } +} + + +/*********************************************************************** + * + * PK11MessageDigest.digest + * + */ +JNIEXPORT jint JNICALL +Java_com_netscape_jss_pkcs11_PK11MessageDigest_digest + (JNIEnv *env, jclass clazz, jobject proxyObj, jbyteArray outbuf, + jint offset, jint len) +{ + PK11Context *context=NULL; + jbyte *bytes=NULL; + SECStatus status; + unsigned int outLen; + + if( JSS_PK11_getCipherContext(env, proxyObj, &context) != PR_SUCCESS) { + /* exception was thrown */ + goto finish; + } + + PR_ASSERT( (*env)->GetArrayLength(env, outbuf) >= offset+len ); + bytes = (*env)->GetByteArrayElements(env, outbuf, NULL); + if( bytes == NULL ) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + status = PK11_DigestFinal(context, (unsigned char*)(bytes+offset), + &outLen, len); + if( status != SECSuccess ) { + JSS_throwMsg(env, DIGEST_EXCEPTION, "Error occurred while performing" + " digest operation"); + goto finish; + } + +finish: + if(bytes) { + (*env)->ReleaseByteArrayElements(env, outbuf, bytes, 0); + } + return outLen; +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11MessageDigest.java b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11MessageDigest.java new file mode 100644 index 00000000000..1775fe13cec --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11MessageDigest.java @@ -0,0 +1,154 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs11; + +import com.netscape.jss.crypto.*; +import java.security.DigestException; +import java.security.NoSuchAlgorithmException; +import java.security.InvalidKeyException; + +/** + * Message Digesting with PKCS #11. + */ +public final class PK11MessageDigest extends JSSMessageDigest { + + private PK11Token token; + private CipherContextProxy digestProxy; + private PK11SymKey hmacKey; + private DigestAlgorithm alg; + + PK11MessageDigest(PK11Token token, DigestAlgorithm alg) + throws NoSuchAlgorithmException, DigestException + { + this.token = token; + this.alg = alg; + + if( ! token.doesAlgorithm(alg) ) { + throw new NoSuchAlgorithmException(); + } + + reset(); + } + + public void initHMAC(SymmetricKey key) + throws DigestException, InvalidKeyException + { + + if( ! (alg instanceof HMACAlgorithm) ) { + throw new DigestException("Digest is not an HMAC digest"); + } + + reset(); + + if( ! (key instanceof PK11SymKey) ) { + throw new InvalidKeyException("HMAC key is not a PKCS #11 key"); + } + + hmacKey = (PK11SymKey) key; + + if( ! key.getOwningToken().equals(token) ) { + hmacKey = null; + throw new InvalidKeyException( + "HMAC key does not live on the same token as this digest"); + } + + this.digestProxy = initHMAC(token, alg, hmacKey); + } + + public void update(byte[] input, int offset, int len) + throws DigestException + { + if( digestProxy == null ) { + throw new DigestException("Digest not correctly initialized"); + } + if( input.length < offset+len ) { + throw new IllegalArgumentException( + "Input buffer is not large enough for offset and length"); + } + + update(digestProxy, input, offset, len); + } + + public int digest(byte[] outbuf, int offset, int len) + throws DigestException + { + if( digestProxy == null ) { + throw new DigestException("Digest not correctly initialized"); + } + if( outbuf.length < offset+len ) { + throw new IllegalArgumentException( + "Output buffer is not large enough for offset and length"); + } + + int retval = digest(digestProxy, outbuf, offset, len); + + reset(); + + return retval; + } + + public void reset() throws DigestException { + if( ! (alg instanceof HMACAlgorithm) ) { + // This is a regular digest, so we have enough information + // to inialize the context + this.digestProxy = initDigest(alg); + } else if( hmacKey != null ) { + // This is an HMAC digest, and we have a key + this.digestProxy = initHMAC(token, alg, hmacKey); + } else { + // this is an HMAC digest for which we don't have the key yet, + // we have to wait to construct the context + this.digestProxy = null; + } + } + + public DigestAlgorithm getAlgorithm() { + return alg; + } + + private static native CipherContextProxy + initDigest(DigestAlgorithm alg) + throws DigestException; + + private static native CipherContextProxy + initHMAC(PK11Token token, DigestAlgorithm alg, PK11SymKey key) + throws DigestException; + + private static native void + update(CipherContextProxy proxy, byte[] inbuf, int offset, int len); + + private static native int + digest(CipherContextProxy proxy, byte[] outbuf, int offset, int len); + +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Module.c b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Module.c new file mode 100644 index 00000000000..ad941e78bd8 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Module.c @@ -0,0 +1,265 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +#include "_jni/com_netscape_jss_pkcs11_PK11Module.h" + +#include +#include +#include +#include +#include + +#include "pk11util.h" +#include +#include +#include "jss_exceptions.h" + +/*********************************************************************** + * Class: com_netscape_jss_pkcs11_PK11Module + * Method: getName + * Signature: ()Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_com_netscape_jss_pkcs11_PK11Module_getName + (JNIEnv *env, jobject this) +{ + SECMODModule *module; + jstring nameString=NULL; + + PR_ASSERT(env!=NULL && this!=NULL); + + if( JSS_PK11_getModulePtr(env, this, &module) != PR_SUCCESS) { + goto finish; + } + + PR_ASSERT(module->commonName != NULL); + nameString = (*env)->NewStringUTF(env, module->commonName); + +finish: + PR_ASSERT( nameString || (*env)->ExceptionOccurred(env) ); + return nameString; +} + +/*********************************************************************** + * Class: com_netscape_jss_pkcs11_PK11Module + * Method: getLibraryName + * Signature: ()Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_com_netscape_jss_pkcs11_PK11Module_getLibraryName + (JNIEnv *env, jobject this) +{ + SECMODModule *module; + jstring libName = NULL; + + PR_ASSERT(env!=NULL && this!=NULL); + + if( JSS_PK11_getModulePtr(env, this, &module) != PR_SUCCESS) { + goto finish; + } + + PR_ASSERT(module->dllName != NULL); + libName = (*env)->NewStringUTF(env, module->dllName); + +finish: + PR_ASSERT( libName || (*env)->ExceptionOccurred(env) ); + return libName; +} + +/*********************************************************************** + * Class: com_netscape_jss_pkcs11_PK11Module + * Method: putTokensInVector + * Signature: (Ljava/util/Vector;)V + */ +JNIEXPORT void JNICALL Java_com_netscape_jss_pkcs11_PK11Module_putTokensInVector + (JNIEnv *env, jobject this, jobject vector) +{ + SECMODModule *module; + jclass vectorClass; + jmethodID addElement; + jobject token; + PK11SlotInfo *slot; + int i; + + PR_ASSERT(env!=NULL && this!=NULL && vector!=NULL); + + /*************************** + * Get Vector JNI ids + ***************************/ + vectorClass = (*env)->GetObjectClass(env, vector); + if(vectorClass==NULL) goto finish; + + addElement = (*env)->GetMethodID(env, + vectorClass, + VECTOR_ADD_ELEMENT_NAME, + VECTOR_ADD_ELEMENT_SIG); + if(addElement==NULL) goto finish; + + /*************************** + * Get the PKCS #11 module + ***************************/ + if( JSS_PK11_getModulePtr(env, this, &module) != PR_SUCCESS) goto finish; + + /************************** + * Loop over slots + **************************/ + for(i=0; i < module->slotCount; i++) { + + char *slotname, *tokenname; + slotname = PK11_GetSlotName(module->slots[i]); + tokenname = PK11_GetTokenName(module->slots[i]); + + /* ignore if the slot or token has no name */ + if( slotname!=NULL && slotname[0]!='\0' && + tokenname!=NULL && tokenname[0]!='\0' ) { + + /* turn the slot into a PK11Token */ + slot = PK11_ReferenceSlot(module->slots[i]); + PR_ASSERT(slot!=NULL); + token = JSS_PK11_wrapPK11Token(env, &slot); + + /* stick the PK11Token in the Vector */ + (*env)->CallVoidMethod(env, vector, addElement, token); + } + + } + +finish: + return; +} + +/*********************************************************************** + * + * J S S _ P K 1 1 _ w r a p P K 1 1 M o d u l e + * + * Turns a SECMODModule* C structure into a PK11Module Java object. + * + * INPUTS + * ptr + * Address of a SECMODModule *. This pointer will be copied + * into the new Java object, then set to NULL. + * RETURNS + * A new Java PK11Module object, or NULL if an exception was thrown. + * In any case, the ptr parameter is eaten. + */ +PR_IMPLEMENT( jobject ) +JSS_PK11_wrapPK11Module(JNIEnv *env, SECMODModule **module) +{ + jclass moduleClass; + jmethodID constructor; + jobject newModule=NULL; + jbyteArray pointer; + + PR_ASSERT(env!=NULL && module!=NULL && *module!=NULL); + + pointer = JSS_ptrToByteArray(env, (void*)*module); + + /* + * Lookup the class and constructor + */ + moduleClass = (*env)->FindClass(env, PK11MODULE_CLASS_NAME); + if(moduleClass == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + constructor = (*env)->GetMethodID( + env, + moduleClass, + PLAIN_CONSTRUCTOR, + PK11MODULE_CONSTRUCTOR_SIG); + if(constructor == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + /* + * Call the constructor + */ + newModule = (*env)->NewObject(env, moduleClass, constructor, pointer); + +finish: + if(newModule==NULL) { + SECMOD_DestroyModule(*module); + } + *module = NULL; + return newModule; +} + + +/*********************************************************************** + * + * J S S _ P K 1 1 _ g e t M o d u l e P t r + * + * Retrieve the SECMODModule pointer of the given PK11Module. + * + * INPUTS + * module + * A reference to a Java PK11Module. + * ptr + * Address of a SECMODModule * that will be loaded with the + * SECMODModule pointer of the given PK11Module. + * RETURNS + * PR_FAILURE if an exception was thrown, or PR_SUCCESS if the + * peration succeeded. + */ +PR_IMPLEMENT( PRStatus ) +JSS_PK11_getModulePtr(JNIEnv *env, jobject module, SECMODModule **ptr) +{ + PR_ASSERT(env!=NULL && module!=NULL && ptr!=NULL); + + return JSS_getPtrFromProxyOwner(env, + module, + PK11MODULE_PROXY_FIELD, + PK11MODULE_PROXY_SIG, + (void**)ptr); +} + +/********************************************************************** + * ModuleProxy.releaseNativeResources + */ +JNIEXPORT void JNICALL +Java_com_netscape_jss_pkcs11_ModuleProxy_releaseNativeResources + (JNIEnv *env, jobject this) +{ + SECMODModule *module; + + if( JSS_PK11_getModulePtr(env, this, &module) != PR_SUCCESS) { + ASSERT_OUTOFMEM(env); + goto finish; + } + PR_ASSERT(module != NULL); + + SECMOD_DestroyModule(module); + +finish: + return; +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Module.java b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Module.java new file mode 100644 index 00000000000..0b7d9d5d1f5 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Module.java @@ -0,0 +1,86 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.pkcs11; + +import com.netscape.jss.util.Assert; +import java.util.Enumeration; +import java.util.Vector; + +public final class PK11Module { + + private PK11Module() { + Assert.notReached("PK11Module default constructor"); + } + + /** + * This constructor should only be called from native code. + */ + private PK11Module(byte[] pointer) { + Assert.assert(pointer!=null); + moduleProxy = new ModuleProxy(pointer); + reloadTokens(); + } + + /** + * Returns the common name of this module. + */ + public native String getName(); + + /** + * Returns the name of the shared library implementing this module. + */ + public native String getLibraryName(); + + /** + * Get the CryptoTokens provided by this module. + * + * @return An enumeration of CryptoTokens that come from this module. + */ + public synchronized Enumeration getTokens() { + return tokenVector.elements(); + } + + /** + * Re-load the list of this module's tokens. This function is private + * to JSS. + */ + public synchronized void reloadTokens() { + tokenVector = new Vector(); + putTokensInVector(tokenVector); + } + + private native void putTokensInVector(Vector tokens); + + private Vector tokenVector; + private ModuleProxy moduleProxy; +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11PrivKey.c b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11PrivKey.c new file mode 100644 index 00000000000..8a35251a386 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11PrivKey.c @@ -0,0 +1,473 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +#include "_jni/com_netscape_jss_pkcs11_PrivateKeyProxy.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "pk11util.h" +#include "java_ids.h" + +/*********************************************************************** + * + * J S S _ P K 1 1 _ w r a p P r i v K e y + * privk: will be stored in a Java wrapper. + * Returns: a new PK11PrivKey, or NULL if an exception occurred. + */ +PR_IMPLEMENT( jobject ) +JSS_PK11_wrapPrivKey(JNIEnv *env, SECKEYPrivateKey **privk) +{ + jclass keyClass; + jmethodID constructor; + jbyteArray ptrArray; + jobject Key=NULL; + + PR_ASSERT(env!=NULL && privk!=NULL && *privk!=NULL); + + /* Find the class */ + keyClass = (*env)->FindClass(env, PK11PRIVKEY_CLASS_NAME); + if(keyClass == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + /* find the constructor */ + constructor = (*env)->GetMethodID(env, keyClass, + PK11PRIVKEY_CONSTRUCTOR_NAME, + PK11PRIVKEY_CONSTRUCTOR_SIG); + if(constructor == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + /* convert the pointer to a byte array */ + ptrArray = JSS_ptrToByteArray(env, (void*)*privk); + if(ptrArray == NULL) { + goto finish; + } + /* call the constructor */ + Key = (*env)->NewObject(env, keyClass, constructor, ptrArray); + +finish: + if(Key == NULL) { + SECKEY_DestroyPrivateKey(*privk); + } + *privk = NULL; + return Key; +} + +/*********************************************************************** + * PK11PrivKey.verifyKeyIsOnToken + */ +JNIEXPORT void JNICALL +Java_com_netscape_jss_pkcs11_PK11PrivKey_verifyKeyIsOnToken + (JNIEnv *env, jobject this, jobject token) +{ + SECKEYPrivateKey *key = NULL; + PK11SlotInfo *slot = NULL; + PK11SlotInfo *keySlot = NULL; + + if( JSS_PK11_getPrivKeyPtr(env, this, &key) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + goto finish; + } + + if( JSS_PK11_getTokenSlotPtr(env, token, &slot) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + goto finish; + } + + keySlot = PK11_GetSlotFromPrivateKey(key); + if(keySlot == PK11_GetInternalKeySlot()) { + /* hack for internal module */ + if(slot != keySlot && slot != PK11_GetInternalSlot()) { + JSS_throwMsg(env, NO_SUCH_ITEM_ON_TOKEN_EXCEPTION, + "Key is not present on this token"); + goto finish; + } + } else if(keySlot != slot) { + JSS_throwMsg(env, NO_SUCH_ITEM_ON_TOKEN_EXCEPTION, + "Key is not present on this token"); + goto finish; + } + +finish: + if(keySlot != NULL) { + PK11_FreeSlot(keySlot); + } +} + +/* + * PK11PrivKey.getKeyType + * + * Returns: The KeyType of this key. + */ +JNIEXPORT jobject JNICALL +Java_com_netscape_jss_pkcs11_PK11PrivKey_getKeyType + (JNIEnv *env, jobject this) +{ + PRThread *pThread; + SECKEYPrivateKey *privk; + KeyType keyType; + char* keyTypeFieldName; + jclass keyTypeClass; + jfieldID keyTypeField; + jobject keyTypeObject = NULL; + + PR_ASSERT(env!=NULL && this!=NULL); + + pThread = PR_AttachThread(PR_SYSTEM_THREAD, 0, NULL); + PR_ASSERT(pThread != NULL); + + if(JSS_PK11_getPrivKeyPtr(env, this, &privk) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL ); + goto finish; + } + PR_ASSERT(privk!=NULL); + + keyType = SECKEY_GetPrivateKeyType(privk); + + switch(keyType) { + case nullKey: + keyTypeFieldName = NULL_KEYTYPE_FIELD; + break; + case rsaKey: + keyTypeFieldName = RSA_KEYTYPE_FIELD; + break; + case dsaKey: + keyTypeFieldName = DSA_KEYTYPE_FIELD; + break; + case fortezzaKey: + keyTypeFieldName = FORTEZZA_KEYTYPE_FIELD; + break; + case dhKey: + keyTypeFieldName = DH_KEYTYPE_FIELD; + break; + case keaKey: + keyTypeFieldName = KEA_KEYTYPE_FIELD; + default: + PR_ASSERT(PR_FALSE); + keyTypeFieldName = NULL_KEYTYPE_FIELD; + break; + } + + keyTypeClass = (*env)->FindClass(env, KEYTYPE_CLASS_NAME); + if(keyTypeClass == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + keyTypeField = (*env)->GetStaticFieldID(env, keyTypeClass, + keyTypeFieldName, KEYTYPE_FIELD_SIG); + if(keyTypeField==NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + keyTypeObject = (*env)->GetStaticObjectField( + env, + keyTypeClass, + keyTypeField); + if(keyTypeObject == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + +finish: + PR_DetachThread(); + return keyTypeObject; +} + + +/* + * PrivateKeyProxy.releaseNativeResources + */ +JNIEXPORT void JNICALL +Java_com_netscape_jss_pkcs11_PrivateKeyProxy_releaseNativeResources + (JNIEnv *env, jobject this) +{ + SECKEYPrivateKey *privk; + PRThread *pThread; + + PR_ASSERT(env!=NULL && this!=NULL); + + pThread = PR_AttachThread(PR_SYSTEM_THREAD, 0, NULL); + PR_ASSERT(pThread != NULL); + + /* Get the SECKEYPrivateKey structure */ + if(JSS_getPtrFromProxy(env, this, (void**) &privk) != PR_SUCCESS) { + PR_ASSERT( PR_FALSE ); + goto finish; + } + PR_ASSERT(privk != NULL); + + SECKEY_DestroyPrivateKey(privk); + +finish: + PR_DetachThread(); + return; +} + + +/* + * Given a PrivateKey object, extracts the SECKEYPrivateKey* and stores it + * at the given address. + * + * privkObject: A JNI reference to a PrivateKey object. + * ptr: Address of a SECKEYPrivateKey* that will receive the pointer. + * Returns: PR_SUCCESS for success, PR_FAILURE if an exception was thrown. + */ +PR_IMPLEMENT( PRStatus ) +JSS_PK11_getPrivKeyPtr(JNIEnv *env, jobject privkObject, + SECKEYPrivateKey** ptr) +{ + PR_ASSERT(env!=NULL && privkObject!=NULL); + + /* Get the pointer from the key proxy */ + PR_ASSERT(sizeof(SECKEYPrivateKey*) == sizeof(void*)); + return JSS_getPtrFromProxyOwner(env, privkObject, KEY_PROXY_FIELD, + KEY_PROXY_SIG, (void**)ptr); +} + +/*********************************************************************** + * + * PK11PrivKey.getPK11Token + * + * Figures out which slot this key lives on and wraps it in a PK11Token, + * + * RETURNS + * NULL if an exception occurred, otherwise a new PK11Token object. + */ +JNIEXPORT jobject JNICALL +Java_com_netscape_jss_pkcs11_PK11PrivKey_getOwningToken + (JNIEnv *env, jobject this) +{ + SECKEYPrivateKey *key = NULL; + PK11SlotInfo *keySlot = NULL; + jobject token = NULL; + + PR_ASSERT(env!=NULL && this!=NULL); + + /* Get the C key structure */ + if( JSS_PK11_getPrivKeyPtr(env, this, &key) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + goto finish; + } + + /* Get the slot that this key lives on */ + keySlot = PK11_GetSlotFromPrivateKey(key); + PR_ASSERT(keySlot != NULL); + + /* Turn the slot into a Java PK11Token */ + token = JSS_PK11_wrapPK11Token(env, &keySlot); + if(token == NULL) { + PR_ASSERT( (*env)->ExceptionOccurred(env) ); + goto finish; + } + +finish: + if(keySlot != NULL) { + PK11_FreeSlot(keySlot); + } + return token; +} + +/********************************************************************** + * PK11PrivKey.getUniqueID + */ +JNIEXPORT jbyteArray JNICALL +Java_com_netscape_jss_pkcs11_PK11PrivKey_getUniqueID + (JNIEnv *env, jobject this) +{ + SECKEYPrivateKey *key = NULL; + PK11SlotInfo *slot = NULL; + SECItem keyItem = {0, 0, 0}; + jbyteArray byteArray = NULL; + + PR_ASSERT(env!=NULL && this!=NULL); + + /*************************************************** + * Get the private key and slot C structures + ***************************************************/ + if( JSS_PK11_getPrivKeyPtr(env, this, &key) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + goto finish; + } + slot = PK11_GetSlotFromPrivateKey(key); + PR_ASSERT(slot!=NULL); + + /*************************************************** + * Try to login to the token if necessary + ***************************************************/ + PK11_Authenticate(slot, PR_TRUE /*readCerts*/, NULL /*wincx*/); + + /*************************************************** + * Get the key id attribute + ***************************************************/ + if( PK11_ReadAttribute( slot, + key->pkcs11ID, + CKA_ID, + NULL/*arena*/, + &keyItem) != SECSuccess) + { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Unable to read ID attribute"); + goto finish; + } + + /*************************************************** + * Write the key id to a new byte array + ***************************************************/ + byteArray = (*env)->NewByteArray(env, keyItem.len); + if(byteArray == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + (*env)->SetByteArrayRegion(env, byteArray, 0, keyItem.len, + (jbyte*)keyItem.data); + if( (*env)->ExceptionOccurred(env) != NULL) { + PR_ASSERT(PR_FALSE); + goto finish; + } + +finish: + SECITEM_FreeItem(&keyItem, PR_FALSE /*freeit*/); + + return byteArray; +} + +/********************************************************************** + * PK11PrivKey.getStrength + */ +JNIEXPORT jint JNICALL +Java_com_netscape_jss_pkcs11_PK11PrivKey_getStrength + (JNIEnv *env, jobject this) +{ + SECKEYPrivateKey *key = NULL; + PK11SlotInfo *slot = NULL; + int strength; + + PR_ASSERT(env!=NULL && this!=NULL); + + /*************************************************** + * Get the private key and slot C structures + ***************************************************/ + if( JSS_PK11_getPrivKeyPtr(env, this, &key) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + return -1; + } + slot = PK11_GetSlotFromPrivateKey(key); + PR_ASSERT(slot!=NULL); + + /*************************************************** + * Try to login to the token if necessary + ***************************************************/ + PK11_Authenticate(slot, PR_TRUE /*readCerts*/, NULL /*wincx*/); + + /*************************************************** + * Get the strength ( in bytes ) + ***************************************************/ + strength = PK11_GetPrivateModulusLen(key); + if( strength > 0 ) { + /* convert to bits */ + return strength * 8; + } else { + return strength; + } +} + + +/*********************************************************************** + * JSS_PK11_getKeyType + * + * Converts a PrivateKey.KeyType object to a PKCS #11 key type. + * + * INPUTS + * keyTypeObj + * A com.netscape.jss.crypto.PrivateKey.KeyType object. + * RETURNS + * The key type, or nullKey if an exception occurred. + */ +PR_IMPLEMENT( KeyType ) +JSS_PK11_getKeyType(JNIEnv *env, jobject keyTypeObj) +{ + jclass keyTypeClass; + jfieldID fieldID; + char *fieldNames[] = { + RSA_PRIVKEYTYPE_FIELD, + DSA_PRIVKEYTYPE_FIELD }; + int numTypes = 2; + KeyType keyTypes[] = { + rsaKey, + dsaKey }; + jobject field; + int i; + + PR_ASSERT(env!=NULL && keyTypeObj!=NULL); + + keyTypeClass = (*env)->FindClass(env, PRIVKEYTYPE_CLASS_NAME); + if( keyTypeClass == NULL ) { + PR_ASSERT( (*env)->ExceptionOccurred(env) ); + goto finish; + } + + for(i=0; i < numTypes; i++) { + fieldID = (*env)->GetStaticFieldID(env, keyTypeClass, fieldNames[i], + PRIVKEYTYPE_SIG); + if( fieldID == NULL ) { + PR_ASSERT( (*env)->ExceptionOccurred(env) ); + goto finish; + } + field = (*env)->GetStaticObjectField(env, keyTypeClass, fieldID); + if( field == NULL ) { + PR_ASSERT( (*env)->ExceptionOccurred(env) ); + goto finish; + } + if( (*env)->IsSameObject(env, keyTypeObj, field) ) { + return keyTypes[i]; + } + } + + /* unrecognized type? */ + PR_ASSERT( PR_FALSE ); + +finish: + return nullKey; +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11PrivKey.java b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11PrivKey.java new file mode 100644 index 00000000000..e53d28e8037 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11PrivKey.java @@ -0,0 +1,97 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs11; + +import com.netscape.jss.crypto.Algorithm; +import com.netscape.jss.crypto.PrivateKey; +import com.netscape.jss.crypto.CryptoToken; +import com.netscape.jss.crypto.TokenException; +import com.netscape.jss.util.*; + +final class PK11PrivKey extends com.netscape.jss.pkcs11.PK11Key + implements PrivateKey { + + protected PK11PrivKey(byte[] pointer) { + Assert.assert(pointer!=null); + keyProxy = new PrivateKeyProxy(pointer); + } + + /** + * Make sure this key lives on the given token. + */ + public native void verifyKeyIsOnToken(PK11Token token) + throws com.netscape.jss.crypto.NoSuchItemOnTokenException; + + /** + * Returns a new CryptoToken where this key resides. + * + * @return The PK11Token that owns this key. + */ + public native CryptoToken getOwningToken(); + + public native byte[] getUniqueID() throws TokenException; + + public native KeyType getKeyType(); + + public PrivateKey.Type getType() { + KeyType kt = getKeyType(); + + if( kt == KeyType.RSA ) { + return PrivateKey.Type.RSA; + } else { + Assert.assert(kt == KeyType.DSA); + return PrivateKey.Type.DSA; + } + } + + /** + * Returns the size in bits of the modulus of an RSA Private key. + * Returns -1 for other types of keys. + */ + public native int getStrength(); +} + +class PrivateKeyProxy extends KeyProxy { + + public PrivateKeyProxy(byte[] pointer) { + super(pointer); + } + + protected native void releaseNativeResources(); + + protected void finalize() throws Throwable { + super.finalize(); + Debug.trace(Debug.OBNOXIOUS, "Finalizing a PrivateKeyProxy"); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11PubKey.c b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11PubKey.c new file mode 100644 index 00000000000..91917a3dece --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11PubKey.c @@ -0,0 +1,613 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +#include "_jni/com_netscape_jss_pkcs11_PublicKeyProxy.h" +#include "_jni/com_netscape_jss_pkcs11_PK11RSAPublicKey.h" +#include "_jni/com_netscape_jss_pkcs11_PK11DSAPublicKey.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "pk11util.h" + +#include + +#include "java_ids.h" +#include +#include + +/*********************************************************************** + * PublicKeyProxy.releaseNativeResources + */ +JNIEXPORT void JNICALL Java_com_netscape_jss_pkcs11_PublicKeyProxy_releaseNativeResources + (JNIEnv *env, jobject this) +{ + SECKEYPublicKey *pubk; + PRThread *pThread; + + PR_ASSERT(env!=NULL && this!=NULL); + + pThread = PR_AttachThread(PR_SYSTEM_THREAD, 0, NULL); + PR_ASSERT(pThread != NULL); + + /* Get the SECKEYPublicKey structure */ + if(JSS_getPtrFromProxy(env, this, (void**) &pubk) != PR_SUCCESS) { + PR_ASSERT( PR_FALSE ); + goto finish; + } + PR_ASSERT(pubk != NULL); + + SECKEY_DestroyPublicKey(pubk); + +finish: + PR_DetachThread(); + return; +} + +/*********************************************************************** +** JSS_PK11_wrapPubKey +*/ +PR_IMPLEMENT( jobject ) +JSS_PK11_wrapPubKey(JNIEnv *env, SECKEYPublicKey **pKey) +{ + jobject pubKey=NULL; + jclass keyClass; + KeyType keyType; + jmethodID constructor; + jbyteArray ptr; + char *keyClassName; + + PR_ASSERT(env!=NULL && pKey!=NULL); + + /* What kind of public key? */ + keyType = (*pKey)->keyType; + switch(keyType) { + case rsaKey: + keyClassName = PK11_RSA_PUBKEY_CLASS_NAME; + break; + case dsaKey: + keyClassName = PK11_DSA_PUBKEY_CLASS_NAME; + break; + default: + keyClassName = PK11PUBKEY_CLASS_NAME; + break; + } + + keyClass = (*env)->FindClass(env, keyClassName); + if(keyClass==NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + constructor = (*env)->GetMethodID( env, + keyClass, + PK11PUBKEY_CONSTRUCTOR_NAME, + PK11PUBKEY_CONSTRUCTOR_SIG); + if(constructor == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + ptr = JSS_ptrToByteArray(env, (void*)*pKey); + if(ptr == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + pubKey = (*env)->NewObject(env, keyClass, constructor, ptr); + if(pubKey == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + *pKey = NULL; + +finish: + if(pubKey==NULL && *pKey!=NULL) { + SECKEY_DestroyPublicKey(*pKey); + *pKey = NULL; + } + PR_DetachThread(); + return pubKey; +} + +/*********************************************************************** + * Given a PublicKey object, extracts the SECKEYPublicKey* and stores it + * at the given address. + * + * pubkObject: A JNI reference to a PublicKey object. + * ptr: Address of a SECKEYPublicKey* that will receive the pointer. + * Returns: PR_SUCCESS for success, PR_FAILURE if an exception was thrown. + */ +PRStatus +JSS_PK11_getPubKeyPtr(JNIEnv *env, jobject pubkObject, + SECKEYPublicKey** ptr) +{ + PR_ASSERT(env!=NULL && pubkObject!=NULL); + + /* Get the pointer from the key proxy */ + PR_ASSERT(sizeof(SECKEYPublicKey*) == sizeof(void*)); + return JSS_getPtrFromProxyOwner(env, pubkObject, KEY_PROXY_FIELD, + KEY_PROXY_SIG, (void**)ptr); +} + +/*********************************************************************** + * PK11PubKey.verifyKeyIsOnToken + */ +JNIEXPORT void JNICALL +Java_com_netscape_jss_pkcs11_PK11PubKey_verifyKeyIsOnToken + (JNIEnv *env, jobject this, jobject token) +{ + PRThread *pThread; + SECKEYPublicKey *key = NULL; + PK11SlotInfo *slot = NULL; + PK11SlotInfo *keySlot = NULL; + + pThread = PR_AttachThread(PR_SYSTEM_THREAD, 0, NULL); + PR_ASSERT(pThread != NULL); + + if( JSS_PK11_getPubKeyPtr(env, this, &key) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + goto finish; + } + + if( JSS_PK11_getTokenSlotPtr(env, token, &slot) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + goto finish; + } + +#if 0 + keySlot = PK11_GetSlotFromPublicKey(key); +#else + keySlot = PK11_ReferenceSlot(key->pkcs11Slot); +#endif + if(keySlot == PK11_GetInternalKeySlot()) { + /* hack for internal module */ + if(slot != keySlot && slot != PK11_GetInternalSlot()) { + JSS_throwMsg(env, NO_SUCH_ITEM_ON_TOKEN_EXCEPTION, + "Key is not present on this token"); + goto finish; + } + } else if(keySlot != slot) { + JSS_throwMsg(env, NO_SUCH_ITEM_ON_TOKEN_EXCEPTION, + "Key is not present on this token"); + goto finish; + } + +finish: + if(keySlot != NULL) { + PK11_FreeSlot(keySlot); + } + PR_DetachThread(); +} + +/*********************************************************************** + * PK11PubKey.getKeyType + * + * Returns: The KeyType of this key. + */ +JNIEXPORT jobject JNICALL +Java_com_netscape_jss_pkcs11_PK11PubKey_getKeyType + (JNIEnv *env, jobject this) +{ + PRThread *pThread; + SECKEYPublicKey *pubk; + KeyType keyType; + char* keyTypeFieldName; + jclass keyTypeClass; + jfieldID keyTypeField; + jobject keyTypeObject = NULL; + + PR_ASSERT(env!=NULL && this!=NULL); + + pThread = PR_AttachThread(PR_SYSTEM_THREAD, 0, NULL); + PR_ASSERT(pThread != NULL); + + if(JSS_PK11_getPubKeyPtr(env, this, &pubk) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL ); + goto finish; + } + PR_ASSERT(pubk!=NULL); + + keyType = pubk->keyType; + + switch(keyType) { + case nullKey: + keyTypeFieldName = NULL_KEYTYPE_FIELD; + break; + case rsaKey: + keyTypeFieldName = RSA_KEYTYPE_FIELD; + break; + case dsaKey: + keyTypeFieldName = DSA_KEYTYPE_FIELD; + break; + case fortezzaKey: + keyTypeFieldName = FORTEZZA_KEYTYPE_FIELD; + break; + case dhKey: + keyTypeFieldName = DH_KEYTYPE_FIELD; + break; + case keaKey: + keyTypeFieldName = KEA_KEYTYPE_FIELD; + default: + PR_ASSERT(PR_FALSE); + keyTypeFieldName = NULL_KEYTYPE_FIELD; + break; + } + + keyTypeClass = (*env)->FindClass(env, KEYTYPE_CLASS_NAME); + if(keyTypeClass == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + keyTypeField = (*env)->GetStaticFieldID(env, keyTypeClass, + keyTypeFieldName, KEYTYPE_FIELD_SIG); + if(keyTypeField==NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + keyTypeObject = (*env)->GetStaticObjectField( + env, + keyTypeClass, + keyTypeField); + if(keyTypeObject == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + +finish: + PR_DetachThread(); + return keyTypeObject; +} + +typedef enum { + DSA_P, + DSA_Q, + DSA_G, + DSA_PUBLIC, + RSA_MODULUS, + RSA_PUBLIC_EXPONENT +} PublicKeyField; + +static jbyteArray +get_public_key_info(JNIEnv *env, jobject this, PublicKeyField field); + +/********************************************************************** + * + * PK11RSAPublicKey.getModulusByteArray + * + * Returns the modulus of this RSA Public Key. The format is a big-endian + * octet string in a byte array, suitable for importing into a BigInteger. + * + */ +JNIEXPORT jbyteArray JNICALL +Java_com_netscape_jss_pkcs11_PK11RSAPublicKey_getModulusByteArray + (JNIEnv *env, jobject this) +{ + return get_public_key_info(env, this, RSA_MODULUS); +} + +/********************************************************************** + * + * PK11RSAPublicKey.getPublicExponentByteArray + * + * Returns the modulus of this RSA Public Key. The format is a big-endian + * octet string in a byte array, suitable for importing into a BigInteger. + * + */ +JNIEXPORT jbyteArray JNICALL +Java_com_netscape_jss_pkcs11_PK11RSAPublicKey_getPublicExponentByteArray + (JNIEnv *env, jobject this) +{ + return get_public_key_info(env, this, RSA_PUBLIC_EXPONENT); +} + +/********************************************************************** + * + * PK11DSAPublicKey.getPByteArray + * + * Returns the prime of this DSA Public Key. The format is a big-endian + * octet string in a byte array, suitable for importing into a BigInteger. + * + */ +JNIEXPORT jbyteArray JNICALL +Java_com_netscape_jss_pkcs11_PK11DSAPublicKey_getPByteArray + (JNIEnv *env, jobject this) +{ + return get_public_key_info(env, this, DSA_P); +} + +/********************************************************************** + * + * PK11DSAPublicKey.getQByteArray + * + * Returns the subprime of this DSA Public Key. The format is a big-endian + * octet string in a byte array, suitable for importing into a BigInteger. + * + */ +JNIEXPORT jbyteArray JNICALL +Java_com_netscape_jss_pkcs11_PK11DSAPublicKey_getQByteArray + (JNIEnv *env, jobject this) +{ + return get_public_key_info(env, this, DSA_Q); +} + +/********************************************************************** + * + * PK11DSAPublicKey.getGByteArray + * + * Returns the base of this DSA Public Key. The format is a big-endian + * octet string in a byte array, suitable for importing into a BigInteger. + * + */ +JNIEXPORT jbyteArray JNICALL +Java_com_netscape_jss_pkcs11_PK11DSAPublicKey_getGByteArray + (JNIEnv *env, jobject this) +{ + return get_public_key_info(env, this, DSA_G); +} + +/********************************************************************** + * + * PK11DSAPublicKey.getYByteArray + * + * Returns the public value (Y) of this DSA Public Key. The format is a + * big-endian octet string in a byte array, suitable for importing into + * a BigInteger. + * + */ +JNIEXPORT jbyteArray JNICALL +Java_com_netscape_jss_pkcs11_PK11DSAPublicKey_getYByteArray + (JNIEnv *env, jobject this) +{ + return get_public_key_info(env, this, DSA_PUBLIC); +} + +/********************************************************************** + * g e t _ p u b l i c _ k e y _ i n f o + * + * Looks up a field in a PK11PubKey and converts it to a Java byte array. + * The field is assumed to be a SECItem big-endian octet string. The byte + * array is suitable for feeding to a BigInteger constructor. + */ +static jbyteArray +get_public_key_info + (JNIEnv *env, jobject this, PublicKeyField field) +{ + SECKEYPublicKey *pubk; + jbyteArray byteArray=NULL; + SECItem *item; + + PR_ASSERT(env!=NULL && this!=NULL); + + if( JSS_PK11_getPubKeyPtr(env, this, &pubk) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) ); + goto finish; + } + + switch( field ) { + case DSA_P: + PR_ASSERT(pubk->keyType == dsaKey); + item = &pubk->u.dsa.params.prime; + break; + case DSA_Q: + PR_ASSERT(pubk->keyType == dsaKey); + item = &pubk->u.dsa.params.subPrime; + break; + case DSA_G: + PR_ASSERT(pubk->keyType == dsaKey); + item = &pubk->u.dsa.params.base; + break; + case DSA_PUBLIC: + PR_ASSERT(pubk->keyType == dsaKey); + item = &pubk->u.dsa.publicValue; + break; + case RSA_MODULUS: + PR_ASSERT(pubk->keyType == rsaKey); + item = &pubk->u.rsa.modulus; + break; + case RSA_PUBLIC_EXPONENT: + PR_ASSERT(pubk->keyType == rsaKey); + item = &pubk->u.rsa.publicExponent; + break; + default: + PR_ASSERT(PR_FALSE); + break; + } + PR_ASSERT(item != NULL); + + byteArray = JSS_OctetStringToByteArray(env, item); + if(byteArray == NULL) { + PR_ASSERT( (*env)->ExceptionOccurred(env) ); + goto finish; + } + +finish: + return byteArray; +} + + +/*********************************************************************** + * + * p u b k F r o m R a w + * + * Creates a PK11PubKey from its raw form. The raw form is a DER encoding + * of the public key. For example, this is what is stored in a + * SubjectPublicKeyInfo. + */ +static jobject +pubkFromRaw(JNIEnv *env, KeyType type, jbyteArray rawBA) +{ + jobject pubkObj=NULL; + SECKEYPublicKey *pubk=NULL; + SECStatus rv; + SECItem *pubkDER=NULL; + + /* validate args */ + PR_ASSERT(env!=NULL && (type == rsaKey || type == dsaKey)); + if( rawBA == NULL ) { + JSS_throw(env, NULL_POINTER_EXCEPTION); + goto finish; + } + + pubkDER = JSS_ByteArrayToSECItem(env, rawBA); + if( pubkDER == NULL ) { + /* exception was thrown */ + goto finish; + } + + pubk = PR_NEW(SECKEYPublicKey); + if(pubk == NULL) { + JSS_throw(env, OUT_OF_MEMORY_ERROR); + goto finish; + } + pubk->arena = NULL; + pubk->pkcs11Slot = NULL; + pubk->pkcs11ID = CK_INVALID_HANDLE; + pubk->keyType = type; + + if( type == rsaKey ) { + rv = SEC_ASN1DecodeItem(NULL, pubk, SECKEY_RSAPublicKeyTemplate, + pubkDER); + } else { + rv = SEC_ASN1DecodeItem(NULL, pubk, SECKEY_DSAPublicKeyTemplate, + pubkDER); + } + if( rv != SECSuccess ) { + JSS_throw(env, INVALID_KEY_FORMAT_EXCEPTION); + goto finish; + } + + /* this clears pubk */ + pubkObj = JSS_PK11_wrapPubKey(env, &pubk); + if( pubkObj == NULL ) { + /* exception was thrown */ + goto finish; + } + +finish: + if(pubk!=NULL) { + /* this will only happen if we failed the ASN1 decoding, meaning + * there's no data stored in the internal SECItems */ + PR_Free(pubk); + } + if(pubkDER!=NULL) { + SECITEM_FreeItem(pubkDER, PR_TRUE /*freeit*/); + } + return pubkObj; +} + +/*********************************************************************** + * + * PK11PubKey.RSAfromRaw + */ +JNIEXPORT jobject JNICALL +Java_com_netscape_jss_pkcs11_PK11PubKey_RSAFromRaw + (JNIEnv *env, jclass clazz, jbyteArray rawBA) +{ + return pubkFromRaw(env, rsaKey, rawBA); +} + +/*********************************************************************** + * + * PK11PubKey.RSAfromRaw + */ +JNIEXPORT jobject JNICALL +Java_com_netscape_jss_pkcs11_PK11PubKey_DSAFromRaw + (JNIEnv *env, jclass clazz, jbyteArray rawBA) +{ + return pubkFromRaw(env, dsaKey, rawBA); +} + +/*********************************************************************** + * + * PK11PubKey.getEncoded + * + * Converts the public key to a SubjectPublicKeyInfo, and returns its + * DER-encoding. + */ +JNIEXPORT jbyteArray JNICALL +Java_com_netscape_jss_pkcs11_PK11PubKey_getEncoded + (JNIEnv *env, jobject this) +{ + SECKEYPublicKey *pubk; + CERTSubjectPublicKeyInfo *spki=NULL; + jbyteArray encodedBA=NULL; + SECItem *spkiDER=NULL; + + /* get the public key */ + if( JSS_PK11_getPubKeyPtr(env, this, &pubk) != PR_SUCCESS ) { + /* exception was thrown */ + goto finish; + } + + /* get the subjectpublickeyinfo */ + spki = SECKEY_CreateSubjectPublicKeyInfo(pubk); + if( spki == NULL ) { + /* out of memory? */ + JSS_trace(env, JSS_TRACE_ERROR, "unable to convert public key to" + " SubjectPublicKeyInfo"); + JSS_throw(env, OUT_OF_MEMORY_ERROR); + goto finish; + } + + /* DER-encode the subjectpublickeyinfo */ + spkiDER = SEC_ASN1EncodeItem(NULL /*arena*/, NULL/*dest*/, spki, + CERT_SubjectPublicKeyInfoTemplate); + if( spkiDER == NULL ) { + JSS_trace(env, JSS_TRACE_ERROR, "unable to DER-encode" + " SubjectPublicKeyInfo"); + JSS_throw(env, OUT_OF_MEMORY_ERROR); + goto finish; + } + + /* convert the der-encoding to a Java byte array */ + encodedBA = JSS_SECItemToByteArray(env, spkiDER); + +finish: + if(spki!=NULL) { + SECKEY_DestroySubjectPublicKeyInfo(spki); + } + if(spkiDER!=NULL) { + SECITEM_FreeItem(spkiDER, PR_TRUE /*freeit*/); + } + return encodedBA; +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11PubKey.java b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11PubKey.java new file mode 100644 index 00000000000..3eb94246dda --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11PubKey.java @@ -0,0 +1,108 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs11; + +import com.netscape.jss.crypto.Algorithm; +import com.netscape.jss.util.*; +import com.netscape.jss.crypto.PrivateKey; +import com.netscape.jss.crypto.InvalidKeyFormatException; + +public class PK11PubKey extends com.netscape.jss.pkcs11.PK11Key + implements java.security.PublicKey { + + protected PK11PubKey(byte[] pointer) { + Assert.assert(pointer!=null); + keyProxy = new PublicKeyProxy(pointer); + } + + /** + * Make sure this key lives on the given token. + */ + public native void verifyKeyIsOnToken(PK11Token token) + throws com.netscape.jss.crypto.NoSuchItemOnTokenException; + + public native KeyType getKeyType(); + + /** + * Creates a PK11PubKey from its raw form. The raw form is a DER encoding + * of the public key. For example, this is what is stored in a + * SubjectPublicKeyInfo. + * + * @param type The type of private key to be decoded. + * @param rawKey The bytes of the raw key. + * @exception InvalidKeyFormatException If the raw key could not be + * decoded. + */ + public static PK11PubKey fromRaw(PrivateKey.Type type, byte[] rawKey) + throws InvalidKeyFormatException + { + if( type == PrivateKey.RSA ) { + return RSAFromRaw(rawKey); + } else { + Assert.assert( type == PrivateKey.DSA ); + return DSAFromRaw(rawKey); + } + } + + private static native PK11PubKey RSAFromRaw(byte[] rawKey); + private static native PK11PubKey DSAFromRaw(byte[] rawKey); + + /** + * Returns a DER-encoded SubjectPublicKeyInfo representing this key. + */ + public native byte[] getEncoded(); + + /** + * The name of the primary encoding format of this key. The primary + * encoding format is X.509 SubjectPublicKeyInfo, and the name + * is "X.509". + */ + public String getFormat() { + return "X.509"; + } +} + +class PublicKeyProxy extends KeyProxy { + + public PublicKeyProxy(byte[] pointer) { + super(pointer); + } + + protected native void releaseNativeResources(); + + protected void finalize() throws Throwable { + super.finalize(); + Debug.trace(Debug.OBNOXIOUS, "Releasing a PublicKeyProxy"); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11RSAPublicKey.java b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11RSAPublicKey.java new file mode 100644 index 00000000000..6d15ba899d0 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11RSAPublicKey.java @@ -0,0 +1,63 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs11; + +import com.netscape.jss.util.Assert; +import java.security.interfaces.RSAPublicKey; +import java.math.BigInteger; + +public class PK11RSAPublicKey extends PK11PubKey implements RSAPublicKey { + + public PK11RSAPublicKey(byte[] pointer) { + super(pointer); + } + + public BigInteger getModulus() { + try { + return new BigInteger(getModulusByteArray()); + } catch( NumberFormatException e) { + return null; + } + } + private native byte[] getModulusByteArray(); + + public BigInteger getPublicExponent() { + try { + return new BigInteger(getPublicExponentByteArray()); + } catch( NumberFormatException e) { + return null; + } + } + private native byte[] getPublicExponentByteArray(); +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11SecureRandom.c b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11SecureRandom.c new file mode 100644 index 00000000000..265563495ab --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11SecureRandom.c @@ -0,0 +1,328 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +/* + * HCL header files + */ + +#include +#include + +/* + * JNI header files + */ + +#include "_jni/com_netscape_jss_pkcs11_PK11SecureRandom.h" + +/* + * JSS header files + */ + +#include + +/* + * JNI FUNCTION: PK11SecureRandom.setSeed + * + * JNI FUNCTION TYPE: protected + * + * JNI INPUTS: + * + * env + * The JNI object through which all JNI functions are referenced + * + * this + * A JNI reference to the class which defines this native method + * + * INPUTS: + * + * N/A + * + * OUTPUTS: + * + * jseed + * A JNI array for storage of the random byte seed sequence + * + * ERRORS: + * + * N/A + * + * RETURN: + * + * Upon success, this method returns a byte array + * containing a random byte sequence + * + * NOTES: + * + * This routine is called to seed the pseudo-random number generator. + * + * JNI NOTES: + * + * Class: com_netscape_jss_pkcs11_PK11SecureRandom + * Method: setSeed + * Signature: ([B)V + */ + +JNIEXPORT void JNICALL +Java_com_netscape_jss_pkcs11_PK11SecureRandom_setSeed + ( JNIEnv* env, jobject this, jbyteArray jseed ) +{ + /* + * "JNI" data members + */ + + jbyte* jdata = NULL; + jboolean jIsCopy = JNI_FALSE; + jsize jlen = 0; + + + /* + * "C" data members + */ + + PRThread* pThread = NULL; + SECStatus status = PR_FALSE; + PK11SlotInfo* slot = NULL; + + + /* + * Perform initial assertions + */ + + PR_ASSERT( env != NULL && this != NULL ); + + + /* + * Attach to the external java thread + */ + + pThread = PR_AttachThread( PR_SYSTEM_THREAD, 0, NULL ); + PR_ASSERT( pThread != NULL ); + + + /* + * Obtain the appropriate "slot" + */ + + slot = PK11_GetBestSlot( CKM_FAKE_RANDOM, NULL ); + if( slot == NULL ) { + PR_ASSERT( PR_FALSE ); + goto loser; + } + + + /* + * Convert "JNI jbyteArray" into "JNI jbyte*" so + * that it can be cast into a "C unsigned char*" + */ + + jdata = ( *env )->GetByteArrayElements( env, jseed, &jIsCopy ); + + + /* + * Retrieve the length of the "JNI jbyteArray" + * so that it can be cast into a "C int" + */ + + jlen = ( *env )->GetArrayLength( env, jseed ); + + + /* + * Seed the pseudo-random number generator; + * currently, failures from this routine are ignored + */ + + status = PK11_SeedRandom( slot, ( unsigned char* ) jdata, ( int ) jlen ); + if( status != SECSuccess ) { + PR_ASSERT( PR_FALSE ); + goto loser; + } + + +loser: + + /* + * Copy back the contents of the "JNI jbyte*" and + * free any resources associated with it + */ + + if( jIsCopy == JNI_TRUE ) { + ( *env )->ReleaseByteArrayElements( env, jseed, jdata, 0 ); + } + + + /* + * Free any "C" resources + */ + + if( slot != NULL ) { + PK11_FreeSlot( slot ); + } + slot = NULL; + + + /* + * Detach from the external java thread and return + */ + + PR_DetachThread(); + + return; +} + + +/* + * JNI FUNCTION: PK11SecureRandom.nextBytes + * + * JNI FUNCTION TYPE: protected + * + * JNI INPUTS: + * + * env + * The JNI object through which all JNI functions are referenced + * + * this + * A JNI reference to the class which defines this native method + * + * INPUTS: + * + * N/A + * + * OUTPUTS: + * + * jbytes + * A JNI array for storage of the random byte sequence + * + * ERRORS: + * + * N/A + * + * RETURN: + * + * Upon success, this method returns a byte array + * containing a random byte sequence + * + * NOTES: + * + * This routine is called to generate a pseudo-random number. + * + * JNI NOTES: + * + * Class: com_netscape_jss_pkcs11_PK11SecureRandom + * Method: nextBytes + * Signature: ([B)V + */ + +JNIEXPORT void JNICALL +Java_com_netscape_jss_pkcs11_PK11SecureRandom_nextBytes + ( JNIEnv* env, jobject this, jbyteArray jbytes ) +{ + /* + * "JNI" data members + */ + + jbyte* jdata = NULL; + jboolean jIsCopy = JNI_FALSE; + jsize jlen = 0; + + + /* + * "C" data members + */ + + PRThread* pThread = NULL; + SECStatus status = PR_FALSE; + + + /* + * Perform initial assertions + */ + + PR_ASSERT( env != NULL && this != NULL ); + + + /* + * Attach to the external java thread + */ + + pThread = PR_AttachThread( PR_SYSTEM_THREAD, 0, NULL ); + PR_ASSERT( pThread != NULL ); + + + /* + * Convert "JNI jbyteArray" into "JNI jbyte*" so + * that it can be cast into a "C unsigned char*" + */ + + jdata = ( *env )->GetByteArrayElements( env, jbytes, &jIsCopy ); + + + /* + * Retrieve the length of the "JNI jbyteArray" + * so that it can be cast into a "C int" + */ + + jlen = ( *env )->GetArrayLength( env, jbytes ); + + + /* + * Generate a pseudo-random number; currently, + * failures from this routine are ignored + */ + + status = PK11_GenerateRandom( ( unsigned char* ) jdata, ( int ) jlen ); + if( status != SECSuccess ) { + goto loser; + } + + +loser: + + /* + * Copy back the contents of the "JNI jbyte*" and + * free any resources associated with it + */ + + if( jIsCopy == JNI_TRUE ) { + ( *env )->ReleaseByteArrayElements( env, jbytes, jdata, 0 ); + } + + + /* + * Detach from the external java thread and return + */ + + PR_DetachThread(); + + return; +} + diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11SecureRandom.java b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11SecureRandom.java new file mode 100644 index 00000000000..5843dcf9048 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11SecureRandom.java @@ -0,0 +1,92 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs11; + +import java.util.*; +import com.netscape.jss.util.*; +import com.netscape.jss.crypto.*; + +/** + * A random number generator for PKCS #11. + * + * @see com.netscape.jss.CryptoManager + */ +public final +class PK11SecureRandom implements com.netscape.jss.crypto.JSSSecureRandom +{ + //////////////////////////////////////////////////// + // construction and finalization + //////////////////////////////////////////////////// + + /** + * While it would be "nice" to add the following code + * snippet to check initialization of the random + * number generator prior to using any of the functions, + * a circular link dependency prevents this: + * + * try { + * CryptoManager.getInstance(); + * } + * catch ( CryptoManager.NotInitializedException e ) { + * Assert.notReached("Pseudorandom number generator " + + * "has not been initialized!" ); + * } + */ + public + PK11SecureRandom() {} + + //////////////////////////////////////////////////// + // public routines + //////////////////////////////////////////////////// + + public synchronized native void + setSeed( byte[] seed ); + + public void + setSeed( long seed ) + { + byte[] data = new byte[8]; + + // convert long into 8-byte byte array + for( int i = 0; i < 8; i++ ) { + data[i] = ( byte ) ( seed >> ( 8 * i ) ); + } + + setSeed( data ); + } + + public synchronized native void + nextBytes( byte bytes[] ); +} + diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Signature.c b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Signature.c new file mode 100644 index 00000000000..930432102d5 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Signature.c @@ -0,0 +1,775 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +#include +#include +#include +#include +#include +#include "_jni/com_netscape_jss_pkcs11_PK11Signature.h" +#include "_jni/com_netscape_jss_pkcs11_SigContextProxy.h" +#include +#include +#include + +#include +#include +#include +#include "pk11util.h" + +/*** temporary? ***/ +#include + +static PRStatus +getPrivateKey(JNIEnv *env, jobject sig, SECKEYPrivateKey**key); + +static PRStatus +getPublicKey(JNIEnv *env, jobject sig, SECKEYPublicKey**key); + +static PRStatus +getSomeKey(JNIEnv *env, jobject sig, void **key, short type); + +static SECOidTag +getAlgorithm(JNIEnv *env, jobject sig); + +static void +setSigContext(JNIEnv *env, jobject sig, jobject context); + +static PRStatus +getSigContext(JNIEnv *env, jobject sig, void**pContext, SigContextType* pType); + +/*********************************************************************** + * + * PK11Signature.initSigContext + */ +JNIEXPORT void JNICALL +Java_com_netscape_jss_pkcs11_PK11Signature_initSigContext + (JNIEnv *env, jobject this) +{ + SGNContext *ctxt=NULL; + jobject contextProxy=NULL; + SECKEYPrivateKey *privk; + + /* Extract the private key from the PK11Signature */ + if( getPrivateKey(env, this, &privk) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + goto finish; + } + + /* Start the signing operation */ + ctxt = SGN_NewContext(getAlgorithm(env, this), privk); + if(ctxt == NULL) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Unable to create signing context"); + goto finish; + } + if( SGN_Begin(ctxt) != SECSuccess ) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Unable to begin signing context"); + goto finish; + } + + /* Create a contextProxy and stick it in the PK11Signature object */ + contextProxy = JSS_PK11_wrapSigContextProxy(env, + (void**)&ctxt, + SGN_CONTEXT); + if(contextProxy == NULL) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + goto finish; + } + setSigContext(env, this, contextProxy); + +finish: + if(contextProxy==NULL && ctxt!=NULL) { + /* we created a context but not the Java wrapper, so we need to + * delete the context here. */ + SGN_DestroyContext(ctxt, PR_TRUE /*freeit*/); + } +} + +JNIEXPORT void JNICALL +Java_com_netscape_jss_pkcs11_PK11Signature_initVfyContext + (JNIEnv *env, jobject this) +{ + VFYContext2 *ctxt=NULL; + jobject contextProxy=NULL; + SECKEYPublicKey *pubk; + + if( getPublicKey(env, this, &pubk) != PR_SUCCESS ) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + goto finish; + } + + ctxt = VFY_CreateContext2(pubk, getAlgorithm(env, this)); + if( ctxt == NULL) { + JSS_throwMsg(env, TOKEN_EXCEPTION, + "Unable to create verification context"); + goto finish; + } + if( VFY_Begin2(ctxt) != SECSuccess) { + JSS_throwMsg(env, TOKEN_EXCEPTION, + "Unable to begin verification context"); + goto finish; + } + + /* create a ContextProxy and stick it in the PK11Signature object */ + contextProxy = JSS_PK11_wrapSigContextProxy(env, + (void**)&ctxt, + VFY_CONTEXT); + if(contextProxy == NULL) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + goto finish; + } + setSigContext(env, this, contextProxy); + +finish: + if(contextProxy==NULL && ctxt!=NULL) { + /* we created a context but not the Java wrapper, so we need to + * delete the context here */ + VFY_DestroyContext2(ctxt, PR_TRUE /*freeit*/); + } +} + +/********************************************************************** + * + * PK11Signature.engineUpdateNative + * + */ +JNIEXPORT void JNICALL +Java_com_netscape_jss_pkcs11_PK11Signature_engineUpdateNative + (JNIEnv *env, jobject this, jbyteArray bArray, jint offset, jint length) +{ + SigContextType type; + void *ctxt; + jbyte *bytes=NULL; + jint numBytes; + + /* Extract the signature context */ + if( getSigContext(env, this, &ctxt, &type) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + goto finish; + } + PR_ASSERT(ctxt != NULL); + + /* Get the bytes to be updated */ + bytes = (*env)->GetByteArrayElements(env, bArray, NULL); + if(bytes==NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + numBytes = (*env)->GetArrayLength(env, bArray); + PR_ASSERT(numBytes > 0); + + + /* Update the context */ + if(type == SGN_CONTEXT) { + if( SGN_Update( (SGNContext*)ctxt, + (unsigned char*)bytes, + (unsigned)numBytes ) != SECSuccess) + { + JSS_throwMsg(env, SIGNATURE_EXCEPTION, "update failed"); + goto finish; + } + } else { + PR_ASSERT( type == VFY_CONTEXT ); + if( VFY_Update2( (VFYContext2*)ctxt, + (unsigned char*)bytes, + (unsigned) numBytes ) != SECSuccess) + { + JSS_throwMsg(env, SIGNATURE_EXCEPTION, "update failed"); + goto finish; + } + } + +finish: + if(bytes!=NULL) { + (*env)->ReleaseByteArrayElements(env, bArray, bytes, JNI_ABORT); + } +} + + +/********************************************************************** + * + * PK11Signature.engineSignNative + * + */ +JNIEXPORT jbyteArray JNICALL +Java_com_netscape_jss_pkcs11_PK11Signature_engineSignNative + (JNIEnv *env, jobject this) +{ + SGNContext *ctxt; + SigContextType type; + SECItem signature; + jbyteArray sigArray=NULL; + jbyte *sigBytes=NULL; + + PR_ASSERT(env!=NULL && this!=NULL); + + /* + * Extract the signature context from the Java wrapper + */ + if( getSigContext(env, this, (void**)&ctxt, &type) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + goto finish; + } + PR_ASSERT(ctxt!=NULL && type==SGN_CONTEXT); + + /* + * Finish the signing operation. + */ + if( SGN_End(ctxt, &signature) != SECSuccess) { + JSS_throw(env, SIGNATURE_EXCEPTION); + goto finish; + } + + /* + * Convert SECItem signature to Java byte array + */ + sigArray = (*env)->NewByteArray(env, signature.len); + if(sigArray == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + sigBytes = (*env)->GetByteArrayElements(env, sigArray, NULL); + if(sigBytes == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + memcpy(sigBytes, signature.data, signature.len); + (*env)->ReleaseByteArrayElements(env, sigArray, sigBytes, 0); + sigBytes=NULL; + +finish: + if(sigBytes != NULL) { + (*env)->ReleaseByteArrayElements(env, sigArray, sigBytes, 0); + } + return sigArray; +} + +JNIEXPORT jboolean JNICALL +Java_com_netscape_jss_pkcs11_PK11Signature_engineVerifyNative + (JNIEnv *env, jobject this, jbyteArray sigArray) +{ + jboolean verified = JNI_FALSE; + VFYContext2 *ctxt; + SigContextType type; + SECItem sigItem = {siBuffer, NULL, 0}; + + PR_ASSERT( env!=NULL && this!=NULL && sigArray!=NULL); + + /* + * Lookup the context + */ + if( getSigContext(env, this, (void**)&ctxt, &type) != PR_SUCCESS) { + PR_ASSERT(PR_FALSE); + JSS_throwMsg(env, SIGNATURE_EXCEPTION, + "Unable to retrieve verification context"); + goto finish; + } + if(type != VFY_CONTEXT) { + PR_ASSERT(PR_FALSE); + JSS_throwMsg(env, SIGNATURE_EXCEPTION, + "Verification engine has signature context"); + goto finish; + } + + /* + * Convert signature to SECItem + */ + sigItem.data = (unsigned char*) + (*env)->GetByteArrayElements(env, sigArray, 0); + if(sigItem.data == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + sigItem.len = (*env)->GetArrayLength(env, sigArray); + + /* + * Finish the verification operation + */ + if( VFY_End2(ctxt, &sigItem, NULL) == SECSuccess) { + verified = JNI_TRUE; + } else if( PR_GetError() != SEC_ERROR_BAD_SIGNATURE) { + PR_ASSERT(PR_FALSE); + JSS_throwMsg(env, SIGNATURE_EXCEPTION, + "Failed to complete verification operation"); + goto finish; + } + +finish: + if(sigItem.data!=NULL) { + (*env)->ReleaseByteArrayElements( env, + sigArray, + (jbyte*)sigItem.data, + JNI_ABORT); + } + return verified; +} + +/* + * Extract the algorithm from a PK11Signature. + * + * sig: a PK11Signature. + * Returns: the algorithm of this signature, or SEC_OID_UNKNOWN if an + * error occurs. + */ +static SECOidTag +getAlgorithm(JNIEnv *env, jobject sig) +{ + jclass sigClass; + jfieldID algField; + jobject alg; + SECOidTag retval=SEC_OID_UNKNOWN; + + PR_ASSERT(env!=NULL && sig!=NULL); + + sigClass = (*env)->GetObjectClass(env, sig); + PR_ASSERT(sigClass != NULL); + + algField = (*env)->GetFieldID( env, + sigClass, + SIG_ALGORITHM_FIELD, + SIG_ALGORITHM_SIG); + if(algField == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + alg = (*env)->GetObjectField(env, sig, algField); + if(alg == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + retval = JSS_getOidTagFromAlg(env, alg); + +finish: + return retval; +} + +/* + * Set the contextProxy member of a PK11Signature. + * + * sig: the PK11Signature whose contextProxy we are setting. + * context: the ContextProxy we are setting in the signature. It may be NULL. +**/ +static void +setSigContext(JNIEnv *env, jobject sig, jobject context) +{ + jclass sigClass; + jfieldID contextField; + + PR_ASSERT(env!=NULL && sig!=NULL); + + sigClass = (*env)->GetObjectClass(env, sig); + PR_ASSERT(sigClass!=NULL); + + contextField = (*env)->GetFieldID( + env, + sigClass, + SIG_CONTEXT_PROXY_FIELD, + SIG_CONTEXT_PROXY_SIG); + if(contextField == NULL) { + ASSERT_OUTOFMEM(env); + /* This function doesn't advertise that it can throw exceptions, + * so we shouldn't throw one */ + (*env)->ExceptionClear(env); + return; + } + + (*env)->SetObjectField(env, sig, contextField, context); +} + +/* + * Don't call this if there is no context. + */ +static PRStatus +getSigContext(JNIEnv *env, jobject sig, void**pContext, SigContextType* pType) +{ + jfieldID contextField; + jclass sigClass; + jobject proxy; + + PR_ASSERT(env!=NULL && sig!=NULL && pContext!=NULL && pType!=NULL); + + sigClass = (*env)->GetObjectClass(env, sig); +#ifdef DEBUG + { + jclass realSigClass = (*env)->FindClass(env, PK11SIGNATURE_CLASS_NAME); + PR_ASSERT( (*env)->IsInstanceOf(env, sig, realSigClass) ); + } +#endif + + contextField = (*env)->GetFieldID(env, sigClass, SIG_CONTEXT_PROXY_FIELD, + SIG_CONTEXT_PROXY_SIG); + if(contextField == NULL) { + ASSERT_OUTOFMEM(env); + return PR_FAILURE; + } + + proxy = (*env)->GetObjectField(env, sig, contextField); + if(proxy == NULL) { + PR_ASSERT(PR_FALSE); + JSS_throw(env, TOKEN_EXCEPTION); + return PR_FAILURE; + } + + if( JSS_PK11_getSigContext(env, proxy, pContext, pType) != PR_SUCCESS ) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + return PR_FAILURE; + } + PR_ASSERT(*pContext != NULL); + + return PR_SUCCESS; +} + +#define PUBLICKEYTYPE 0 +#define PRIVATEKEYTYPE 1 +/********************************************************************** + * + * g e t P r i v a t e K e y + */ +static PRStatus +getPrivateKey(JNIEnv *env, jobject sig, SECKEYPrivateKey**key) +{ + return getSomeKey(env, sig, (void**)key, PRIVATEKEYTYPE); +} + +/********************************************************************** + * + * g e t P u b l i c K e y + */ +static PRStatus +getPublicKey(JNIEnv *env, jobject sig, SECKEYPublicKey**key) +{ + return getSomeKey(env, sig, (void**)key, PUBLICKEYTYPE); +} + +static PRStatus +getSomeKey(JNIEnv *env, jobject sig, void **key, short type) +{ + jfieldID keyField; + jclass sigClass; + jobject keyProxy; + + PR_ASSERT(env!=NULL && sig!=NULL && key!=NULL); + + sigClass = (*env)->GetObjectClass(env, sig); +#ifdef DEBUG + { + jclass realSigClass = (*env)->FindClass(env, PK11SIGNATURE_CLASS_NAME); + PR_ASSERT( (*env)->IsInstanceOf(env, sig, realSigClass) ); + } +#endif + + keyField = (*env)->GetFieldID(env, sigClass, SIG_KEY_FIELD, SIG_KEY_SIG); + if(keyField == NULL) { + ASSERT_OUTOFMEM(env); + return PR_FAILURE; + } + + keyProxy = (*env)->GetObjectField(env, sig, keyField); + if(keyProxy == NULL) { + PR_ASSERT(PR_FALSE); + JSS_throw(env, TOKEN_EXCEPTION); + return PR_FAILURE; + } + + if(type == PRIVATEKEYTYPE) { + if( JSS_PK11_getPrivKeyPtr(env, keyProxy, (SECKEYPrivateKey**)key) + != PR_SUCCESS) + { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + return PR_FAILURE; + } + } else { + if( JSS_PK11_getPubKeyPtr(env, keyProxy, (SECKEYPublicKey**)key) + != PR_SUCCESS) + { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + return PR_FAILURE; + } + } + PR_ASSERT(*key != NULL); + + return PR_SUCCESS; +} + +struct SigContextProxyStr { + void *ctxt; + SigContextType type; +}; + +/*********************************************************************** + * J S S _ P K 1 1 _ g e t S i g C o n t e x t + * + * Extracts the context pointer from a SigContextProxy. + * proxy: a non-NULL SigContextProxy object. + * pContext: address of a SGNContext* or VFYContext* where the pointer will be + * stored. + * pType: address of a SigContextType where will be stored the type + * of the context either SGN_CONTEXT or VFY_CONTEXT. + * Returns: PR_SUCCESS, unless an exception was thrown. + */ +PR_IMPLEMENT( PRStatus ) +JSS_PK11_getSigContext(JNIEnv *env, jobject proxy, void**pContext, + SigContextType *pType) +{ + SigContextProxy *ctxtProxy; + + PR_ASSERT(env!=NULL && proxy!=NULL && pContext!=NULL && pType!=NULL); + + if( JSS_getPtrFromProxy(env, proxy, (void**)&ctxtProxy) != PR_SUCCESS) + { + ASSERT_OUTOFMEM(env); + return PR_FAILURE; + } + + /* Make sure the pointers are OK */ + if(ctxtProxy==NULL || ctxtProxy->ctxt==NULL) { + PR_ASSERT(PR_FALSE); + JSS_throw(env, SIGNATURE_EXCEPTION); + return PR_FAILURE; + } + + /* Everything looks good, return the pointer */ + *pContext = ctxtProxy->ctxt; + *pType = ctxtProxy->type; + return PR_SUCCESS; +} + +/********************************************************************** + * + * J S S _ P K 1 1 _ w r a p S i g C o n t e x t P r o x y + * + * Wraps a SGNContext in a SigContextProxy. + * + * ctxt: address of ptr to a SGNContext or VfyContext, which must not be NULL. + * It will be eaten by the wrapper and set to NULL. + * + * type: type of context, either SGN_CONTEXT or VFY_CONTEXT + * Returns: a new SigContextProxy object wrapping the given SGNContext, or + * NULL if an exception was thrown. + */ +PR_IMPLEMENT( jobject ) +JSS_PK11_wrapSigContextProxy(JNIEnv *env, void **ctxt, SigContextType type) +{ + jclass proxyClass; + jmethodID constructor; + jbyteArray byteArray; + SigContextProxy *proxy=NULL; + jobject Context=NULL; + + PR_ASSERT(env!=NULL && ctxt!=NULL && *ctxt!=NULL); + + /* Create the proxy structure */ + proxy = (SigContextProxy*) PR_Malloc(sizeof(SigContextProxy)); + if(proxy == NULL) { + JSS_throw(env, OUT_OF_MEMORY_ERROR); + goto finish; + } + proxy->ctxt = *ctxt; + proxy->type = type; + + byteArray = JSS_ptrToByteArray(env, (void*)proxy); + + /* + * Lookup the class and constructor + */ + proxyClass = (*env)->FindClass(env, SIG_CONTEXT_PROXY_CLASS_NAME); + if( proxyClass == NULL ) { + ASSERT_OUTOFMEM(env); + goto finish; + } + constructor = (*env)->GetMethodID( + env, + proxyClass, + SIG_CONTEXT_PROXY_CONSTRUCTOR_NAME, + SIG_CONTEXT_PROXY_CONSTRUCTOR_SIG); + if(constructor == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + /* call the constructor */ + Context = (*env)->NewObject(env, proxyClass, constructor, byteArray); + +finish: + if(Context==NULL) { + /* didn't work, so free resources */ + if(proxy!=NULL) { + PR_Free(proxy); + } + if(type==SGN_CONTEXT) { + SGN_DestroyContext( (SGNContext*)*ctxt, PR_TRUE /*freeit*/); + } else { + PR_ASSERT(type == VFY_CONTEXT); + VFY_DestroyContext( (VFYContext*)*ctxt, PR_TRUE /*freeit*/); + } + } + *ctxt = NULL; + return Context; +} + +/*********************************************************************** + * + * SigContextProxy.releaseNativeResources + * + * Deletes the SGNContext wrapped by this SigContextProxy object. + */ +JNIEXPORT void JNICALL +Java_com_netscape_jss_pkcs11_SigContextProxy_releaseNativeResources + (JNIEnv *env, jobject this) +{ + SigContextProxy *proxy; + + /* Retrieve the proxy pointer */ + if( JSS_getPtrFromProxy(env, this, (void**)&proxy) != PR_SUCCESS) { +#ifdef DEBUG + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + PR_fprintf(PR_STDERR, + "ERROR: native signature context was not released\n"); +#endif + goto finish; + } + PR_ASSERT(proxy!=NULL); + + /* Free the context and the proxy */ + if(proxy->type == SGN_CONTEXT) { + SGN_DestroyContext( (SGNContext*)proxy->ctxt, PR_TRUE /*freeit*/); + } else { + PR_ASSERT(proxy->type == VFY_CONTEXT); + VFY_DestroyContext2( (VFYContext2*)proxy->ctxt, PR_TRUE /*freeit*/); + } + PR_Free(proxy); + +finish: + ; +} + +/*********************************************************************** + * PK11Signature.engineRawSignNative + */ +JNIEXPORT jbyteArray JNICALL +Java_com_netscape_jss_pkcs11_PK11Signature_engineRawSignNative + (JNIEnv *env, jclass clazz, jobject tokenObj, jobject keyObj, + jbyteArray hashBA) +{ + SECKEYPrivateKey *key = NULL; + SECItem *sig = NULL; + SECItem *hash = NULL; + jbyteArray sigBA = NULL; + + PR_ASSERT(env!=NULL && tokenObj!=NULL && keyObj!=NULL && hashBA!=NULL); + + /* Get the private key */ + if( JSS_PK11_getPrivKeyPtr(env, keyObj, &key) != PR_SUCCESS ) { + /* exception was thrown */ + goto finish; + } + + /* get the hash */ + hash = JSS_ByteArrayToSECItem(env, hashBA); + + /* prepare space for the sig */ + sig = PR_NEW(SECItem); + sig->len = PK11_SignatureLen(key); + sig->data = PR_Malloc(sig->len); + + /* perform the signature operation */ + if( PK11_Sign(key, sig, hash) != SECSuccess ) { + JSS_throwMsg(env, SIGNATURE_EXCEPTION, "Signature operation failed" + " on token"); + goto finish; + } + + /* convert signature to byte array */ + sigBA = JSS_SECItemToByteArray(env, sig); + +finish: + if(sig) { + SECITEM_FreeItem(sig, PR_TRUE /*freeit*/); + } + if(hash) { + SECITEM_FreeItem(hash, PR_TRUE /*freeit*/); + } + return sigBA; +} + +/*********************************************************************** + * PK11Signature.engineRawVerifyNative + */ +JNIEXPORT jboolean JNICALL +Java_com_netscape_jss_pkcs11_PK11Signature_engineRawVerifyNative + (JNIEnv *env, jclass clazz, jobject tokenObj, jobject keyObj, + jbyteArray hashBA, jbyteArray sigBA) +{ + SECItem *sig=NULL; + SECItem *hash=NULL; + SECKEYPublicKey *key=NULL; + jboolean verified=JNI_FALSE; + SECStatus status; + + PR_ASSERT(env!=NULL && tokenObj!=NULL && keyObj!=NULL && hashBA!=NULL + && sigBA!=NULL); + + sig = JSS_ByteArrayToSECItem(env, sigBA); + if(sig==NULL) { + goto finish; + } + hash = JSS_ByteArrayToSECItem(env, hashBA); + if(hash==NULL) { + goto finish; + } + + if( JSS_PK11_getPubKeyPtr(env, keyObj, &key) != PR_SUCCESS ) { + goto finish; + } + + /* perform the operation */ + status = PK11_Verify(key, sig, hash, NULL /*wincx*/); + if( status == SECSuccess ) { + verified = JNI_TRUE; + } else if( PR_GetError() != SEC_ERROR_BAD_SIGNATURE ) { + JSS_throwMsg(env, SIGNATURE_EXCEPTION, "Verification operation" + " failed on token"); + goto finish; + } + +finish: + if(sig) { + SECITEM_FreeItem(sig, PR_TRUE /*freeit*/); + } + if(hash) { + SECITEM_FreeItem(hash, PR_TRUE /*freeit*/); + } + return verified; +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Signature.java b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Signature.java new file mode 100644 index 00000000000..7f9291bc9d1 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Signature.java @@ -0,0 +1,419 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs11; + +import com.netscape.jss.crypto.*; +import com.netscape.jss.util.*; +import java.security.spec.AlgorithmParameterSpec; +import java.security.*; +import java.security.SecureRandom; +import java.io.ByteArrayOutputStream; +import com.netscape.jss.crypto.PrivateKey; + +final class PK11Signature extends com.netscape.jss.crypto.SignatureSpi { + + /************************************************************* + ** PK11Signature + */ + public PK11Signature(PK11Token token, SignatureAlgorithm algorithm) + throws NoSuchAlgorithmException, TokenException + { + Assert.assert(token!=null && algorithm!=null); + + // Make sure this token supports this algorithm. It's OK if + // it only supports the signing part; the hashing can be done + // on the internal module. + if( ! token.doesAlgorithm(algorithm) && + ! token.doesAlgorithm(algorithm.getSigningAlg()) ) + { + throw new NoSuchAlgorithmException(); + } + + this.tokenProxy = token.getProxy(); + this.token = token; + this.algorithm = algorithm; + if( algorithm.getRawAlg() == algorithm ) { + raw = true; + rawInput = new ByteArrayOutputStream(); + } + this.state = UNINITIALIZED; + } + + /************************************************************* + ** engineInitSign + */ + public void engineInitSign(com.netscape.jss.crypto.PrivateKey privateKey) + throws InvalidKeyException, TokenException + { + PK11PrivKey privKey; + + Assert.assert(privateKey!=null); + + // + // Scrutinize the key. Make sure it: + // -is a PKCS #11 key + // -lives on this token + // -is the right type for the algorithm + // + if( privateKey == null ) { + throw new InvalidKeyException("private key is null"); + } + if( ! (privateKey instanceof PK11PrivKey) ) { + throw new InvalidKeyException("privateKey is not a PKCS #11 "+ + "private key"); + } + + privKey = (PK11PrivKey) privateKey; + + try { + privKey.verifyKeyIsOnToken(token); + } catch(NoSuchItemOnTokenException e) { + throw new InvalidKeyException(e.toString()); + } + + try { + if( KeyType.getKeyTypeFromAlgorithm(algorithm) + != privKey.getKeyType()) + { + throw new InvalidKeyException( + "Key type is inconsistent with algorithm"); + } + } catch( NoSuchAlgorithmException e ) { + Assert.notReached("unknown algorithm: "+algorithm); + throw new InvalidKeyException(); + } + + // Finally, the key is OK + key = privKey; + + // Now initialize the signature context + if( ! raw ) { + sigContext = null; + initSigContext(); + } + + // Don't set state until we know everything worked + state = SIGN; + } + + /************************************************************* + ** engineInitSign + ** + ** This just here for JCA compliance(?), we don't take randoms this way. + */ + public void + engineInitSign(com.netscape.jss.crypto.PrivateKey privateKey, + SecureRandom random) + throws InvalidKeyException, TokenException + { + Assert.notReached("This function is not supported"); + + engineInitSign(privateKey); + } + + /************************************************************* + ** initSigContext + ** + ** This function creates a signing context, initializes it, + ** and sets the sigContext field. + */ + protected native void initSigContext() + throws TokenException; + + + /************************************************************* + ** engineInitVerify + */ + public void engineInitVerify(PublicKey publicKey) + throws InvalidKeyException, TokenException + { + PK11PubKey pubKey; + + Assert.assert(publicKey!=null); + + // + // Scrutinize the key. Make sure it: + // -is a PKCS #11 key + // -lives on this token + // -is the right type for the algorithm + // + if( ! (publicKey instanceof PK11PubKey) ) { + throw new InvalidKeyException("publicKey is not a PKCS #11 "+ + "public key"); + } + pubKey = (PK11PubKey) publicKey; + + //try { + // pubKey.verifyKeyIsOnToken(token); + //} catch( NoSuchItemOnTokenException e) { + // throw new InvalidKeyException(e.toString()); + //} + + try { + if( KeyType.getKeyTypeFromAlgorithm(algorithm) + != pubKey.getKeyType()) + { + throw new InvalidKeyException( + "Key type is inconsistent with algorithm"); + } + } catch( NoSuchAlgorithmException e ) { + Assert.notReached("unknown algorithm: "+algorithm); + throw new InvalidKeyException(); + } + + key = pubKey; + + if( ! raw ) { + sigContext = null; + initVfyContext(); + } + + // Don't set state until we know everything worked. + state = VERIFY; + } + + /************************************************************* + ** initVfyContext + */ + protected native void initVfyContext() throws TokenException; + + /************************************************************* + ** engineUpdate + */ + public void engineUpdate(byte b) + throws SignatureException, TokenException + { + engineUpdate(new byte[] {b}, 0, 1); + } + + /************************************************************* + ** engineUpdate + */ + public void engineUpdate(byte[] b, int off, int len) + throws SignatureException, TokenException + { + Assert.assert(b != null); + if( (state==SIGN || state==VERIFY) ) { + if(!raw && sigContext==null) { + Assert.notReached("signature has no context"); + throw new SignatureException("Signature has no context"); + } else if( raw && rawInput==null) { + Assert.notReached("raw signature has no input stream"); + throw new SignatureException("raw signature has no input "+ + "stream"); + } + } else { + Assert.assert(state == UNINITIALIZED); + throw new SignatureException("Signature is not initialized"); + } + Assert.assert(token!=null); + Assert.assert(tokenProxy!=null); + Assert.assert(algorithm!=null); + Assert.assert(key!=null); + + if( raw ) { + rawInput.write(b, off, len); + } else { + engineUpdateNative( b, off, len); + } + } + + /************************************************************* + ** engineUpdateNative + */ + protected native void engineUpdateNative(byte[] b, int off, int len) + throws TokenException; + + + /************************************************************* + ** engineSign + */ + public byte[] engineSign() + throws SignatureException, TokenException + { + if(state != SIGN) { + throw new SignatureException("Signature is not initialized"); + } + if(!raw && sigContext==null) { + throw new SignatureException("Signature has no context"); + } else if(raw && rawInput==null) { + throw new SignatureException("Signature has no input"); + } + Assert.assert(token!=null); + Assert.assert(tokenProxy!=null); + Assert.assert(algorithm!=null); + Assert.assert(key!=null); + + byte[] result; + if( raw ) { + result = engineRawSignNative(token, (PK11PrivKey)key, + rawInput.toByteArray()); + rawInput.reset(); + } else { + result = engineSignNative(); + } + state = UNINITIALIZED; + sigContext = null; + + return result; + } + + /************************************************************* + ** engineSign + */ + public int engineSign(byte[] outbuf, int offset, int len) + throws SignatureException, TokenException + { + Assert.assert(outbuf!=null); + byte[] sig; + if( raw ) { + sig = engineRawSignNative(token, (PK11PrivKey)key, + rawInput.toByteArray()); + rawInput.reset(); + } else { + sig = engineSign(); + } + if( (outbuf==null) || (outbuf.length <= offset) || + (len < sig.length) || (offset+len > outbuf.length)) + { + throw new SignatureException( + "outbuf is not sufficient to hold signature"); + } + System.arraycopy( (Object)sig, 0, (Object)outbuf, offset, sig.length); + return sig.length; + } + + /** + * Performs raw signing of the given hash with the given private key. + */ + private static native byte[] engineRawSignNative(PK11Token token, + PrivateKey key, byte[] hash) + throws SignatureException, TokenException; + + /************************************************************* + ** engineSignNative + */ + private native byte[] engineSignNative() + throws SignatureException, TokenException; + + /************************************************************* + ** engineVerify + */ + public boolean engineVerify(byte[] sigBytes) + throws SignatureException, TokenException + { + Assert.assert(sigBytes!=null); + if(state != VERIFY) { + throw new SignatureException( + "Signature is not initialized properly"); + } + if(!raw && sigContext==null) { + Assert.notReached("Signature has no context"); + throw new SignatureException("Signature has no context"); + } + if(raw && rawInput==null) { + Assert.notReached("Signature has no input"); + throw new SignatureException("Signature has no input"); + } + Assert.assert(token!=null); + Assert.assert(tokenProxy!=null); + Assert.assert(algorithm!=null); + Assert.assert(key!=null); + + if(sigBytes==null) { + return false; + } + + boolean result; + if( raw ) { + result = engineRawVerifyNative(token, (PK11PubKey)key, + rawInput.toByteArray(), sigBytes); + rawInput.reset(); + } else { + result = engineVerifyNative(sigBytes); + } + state = UNINITIALIZED; + sigContext = null; + + return result; + } + + /** + * Performs raw verification of the signature of a hash using the + * given public key, on the given token. + */ + protected static native boolean engineRawVerifyNative(PK11Token token, + PublicKey key, byte[] hash, byte[] signature) + throws SignatureException, TokenException; + + /********************************************************************** + ** engineVerifyNative + */ + native protected boolean engineVerifyNative(byte[] sigBytes) + throws SignatureException, TokenException; + + /************************************************************* + ** engineSetParameter + */ + public void engineSetParameter(AlgorithmParameterSpec params) + throws InvalidAlgorithmParameterException, TokenException + { + Assert.notYetImplemented("PK11Signature.engineSetParameter"); + } + + protected PK11Token token; + protected TokenProxy tokenProxy; + protected Algorithm algorithm; + protected PK11Key key; + protected int state; + protected SigContextProxy sigContext; + protected boolean raw=false; // raw signing only, no hashing + protected ByteArrayOutputStream rawInput; + + // states + static public final int UNINITIALIZED = 0; + static public final int SIGN = 1; + static public final int VERIFY = 2; +} + +class SigContextProxy extends NativeProxy { + public SigContextProxy(byte[] pointer) { + super(pointer); + } + protected native void releaseNativeResources(); + protected void finalize() throws Throwable { + Debug.trace(Debug.OBNOXIOUS, "Finalizing a SigContextProxy"); + super.finalize(); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Store.c b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Store.c new file mode 100644 index 00000000000..6f354624586 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Store.c @@ -0,0 +1,1231 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +#include "_jni/com_netscape_jss_pkcs11_PK11Store.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "pk11util.h" +#include +#include + +/*********************************************************************** + * HACKS which belong in pk11cert.c + ***********************************************************************/ +typedef struct pk11KeyCallbackStr { + SECStatus (* callback)(SECKEYPrivateKey *,void *); + void *callbackArg; + void *wincx; +} pk11KeyCallback; + +/* Traverse slots callback */ +typedef struct pk11TraverseSlotStr { + SECStatus (*callback)(PK11SlotInfo *,CK_OBJECT_HANDLE, void *); + void *callbackArg; + CK_ATTRIBUTE *findTemplate; + int templateCount; +} pk11TraverseSlot; + +SECStatus pk11_DoKeys(PK11SlotInfo*, CK_OBJECT_HANDLE, void*); +SECStatus PK11_TraverseSlot(PK11SlotInfo *, void*); + +/*********************************************************************** + * PK11_TraversePrivateKeysInSlot + * + * This is an HCL hack that traverses all the private keys on a slot. + * + * INPUTS + * slot + * The PKCS #11 slot whose private keys you want to traverse. + * callback + * A callback function that will be called for each key. + * arg + * An argument that will be passed to the callback function. + */ +static SECStatus +PK11_TraversePrivateKeysInSlot( PK11SlotInfo *slot, + SECStatus(* callback)(SECKEYPrivateKey*, void*), void *arg) +{ + pk11KeyCallback perKeyCB; + pk11TraverseSlot perObjectCB; + CK_OBJECT_CLASS privkClass = CKO_PRIVATE_KEY; + CK_ATTRIBUTE theTemplate[1]; + int templateSize = 1; + + theTemplate[0].type = CKA_CLASS; + theTemplate[0].pValue = &privkClass; + theTemplate[0].ulValueLen = sizeof(privkClass); + + if(slot==NULL) { +#ifdef DEBUG + PR_fprintf(PR_STDERR, + "Null slot passed to PK11_TraversePrivateKeysInSlot\n"); + PR_ASSERT(PR_FALSE); +#endif + return SECSuccess; + } + + perObjectCB.callback = pk11_DoKeys; + perObjectCB.callbackArg = &perKeyCB; + perObjectCB.findTemplate = theTemplate; + perObjectCB.templateCount = templateSize; + perKeyCB.callback = callback; + perKeyCB.callbackArg = arg; + perKeyCB.wincx = NULL; + + return PK11_TraverseSlot(slot, &perObjectCB); +} + +/********************************************************************** + * Callback information for keyTraversalCallback + */ +typedef enum { + CERT_OBJECT, + KEY_OBJECT +} ObjectType; +typedef struct { + JNIEnv *env; + jobject vector; + ObjectType type; +} TraversalCallbackInfo; + +/********************************************************************** + * traversalCallback + * + * Generic callback that does the job for both private keys + * and certificates. + * + */ +static SECStatus +traversalCallback(void *keyCert, void *arg) +{ + TraversalCallbackInfo *info; + jclass vectorClass; + jmethodID addElement; + jobject object=NULL; + jobject vector; + JNIEnv *env; + SECKEYPrivateKey *key=NULL; + SECKEYPrivateKey *keyCopy=NULL; + CERTCertificate *cert=NULL; + CERTCertificate *certCopy=NULL; + SECStatus status = SECFailure; + + /************************************************** + * Get the callback data + **************************************************/ + if(arg == NULL) { + JSS_trace(env, JSS_TRACE_ERROR, + "traversalCallback called with NULL argument"); + PR_ASSERT(PR_FALSE); + goto finish; + } + info = (TraversalCallbackInfo*)arg; + env = info->env; + vector = info->vector; + if(info->type == KEY_OBJECT) { + key = (SECKEYPrivateKey*)keyCert; + } else { + PR_ASSERT(info->type == CERT_OBJECT); + cert = (CERTCertificate*)keyCert; + } + if(env==NULL || vector==NULL) { + PR_ASSERT(PR_FALSE); + goto finish; + } + + /************************************************** + * Get JNI ids + **************************************************/ + vectorClass = (*env)->GetObjectClass(env, vector); + if(vectorClass == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + addElement = (*env)->GetMethodID(env, + vectorClass, + VECTOR_ADD_ELEMENT_NAME, + VECTOR_ADD_ELEMENT_SIG); + if(addElement == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + /*************************************************** + * Wrap the object + ***************************************************/ + if(info->type == KEY_OBJECT) { + + /** Private keys may be temporary now... + if(key->pkcs11IsTemp) { + JSS_trace(env, JSS_TRACE_ERROR, + "Private Key passed to keyTraversalCallback is a" + " temporary object"); + PR_ASSERT(PR_FALSE); + goto finish; + } + */ + + keyCopy = SECKEY_CopyPrivateKey(key); + object = JSS_PK11_wrapPrivKey(env, &keyCopy); + } else { + PR_ASSERT( info->type == CERT_OBJECT ); + + certCopy = CERT_DupCertificate(cert); + object = JSS_PK11_wrapCert(env, &certCopy); + } + if(object == NULL) { + PR_ASSERT( (*env)->ExceptionOccurred(env) ); + goto finish; + } + + + /*************************************************** + * Insert the key into the vector + ***************************************************/ + (*env)->CallVoidMethod(env, vector, addElement, object); + + status = SECSuccess; + +finish: + if(object==NULL) { + if(keyCopy!=NULL) { + SECKEY_DestroyPrivateKey(keyCopy); + } + if(certCopy!=NULL) { + CERT_DestroyCertificate(certCopy); + } + } + return status; +} + +/********************************************************************** + * keyTraversalCallback + * + * Given a private key and vector, inserts the private key into the vector. + * + */ +static SECStatus +keyTraversalCallback(SECKEYPrivateKey *key, void *arg) +{ + PR_ASSERT( ((TraversalCallbackInfo*)arg)->type == KEY_OBJECT); + return traversalCallback( (void*)key, arg); +} + +/********************************************************************** + * certTraversalCallback + * + * Given a certificate and vector, inserts the certificate into the vector. + * + */ +static SECStatus +certTraversalCallback(CERTCertificate *cert, void *arg) +{ + PR_ASSERT( ((TraversalCallbackInfo*)arg)->type == CERT_OBJECT); + return traversalCallback( (void*)cert, arg); +} + + +/********************************************************************** + * PK11Store.putKeysInVector + */ +JNIEXPORT void JNICALL +Java_com_netscape_jss_pkcs11_PK11Store_putKeysInVector + (JNIEnv *env, jobject this, jobject keyVector) +{ + PK11SlotInfo *slot; + TraversalCallbackInfo info; + + PR_ASSERT(env!=NULL && this!=NULL && keyVector!=NULL); + + if( JSS_PK11_getStoreSlotPtr(env, this, &slot) != PR_SUCCESS) { + ASSERT_OUTOFMEM(env); + goto finish; + } + PR_ASSERT(slot!=NULL); + + info.env = env; + info.vector = keyVector; + info.type = KEY_OBJECT; + + /* + * Most, if not all, tokens have to be logged in before they allow + * access to their private keys, so try to login here. If we're already + * logged in, this is a no-op. + * If the login fails, go ahead and try to get the keys anyway, in case + * this is an exceptionally promiscuous token. + */ + PK11_Authenticate(slot, PR_TRUE /*load certs*/, NULL /*wincx*/); + + if( PK11_TraversePrivateKeysInSlot(slot, + keyTraversalCallback, + (void*)&info) != SECSuccess) + { + if( ! (*env)->ExceptionOccurred(env) ) { + JSS_throwMsg(env, TOKEN_EXCEPTION, + "PK11_TraverseSlot returned an error"); + } + goto finish; + } + +finish: + return; +} + +/********************************************************************** + * PK11Store.putCertsInVector + */ +JNIEXPORT void JNICALL +Java_com_netscape_jss_pkcs11_PK11Store_putCertsInVector + (JNIEnv *env, jobject this, jobject certVector) +{ + PK11SlotInfo *slot; + TraversalCallbackInfo info; + + PR_ASSERT(env!=NULL && this!=NULL && certVector!=NULL); + + if( JSS_PK11_getStoreSlotPtr(env, this, &slot) != PR_SUCCESS) { + ASSERT_OUTOFMEM(env); + goto finish; + } + PR_ASSERT(slot!=NULL); + + /* + * log in if the slot does not have publicly readable certs + */ + if( !PK11_IsFriendly(slot) ) { + PK11_Authenticate(slot, PR_TRUE /*load certs*/, NULL /*wincx*/); + } + + info.env = env; + info.vector = certVector; + info.type = CERT_OBJECT; + + if( PK11_TraverseCertsInSlot(slot, + certTraversalCallback, + (void*)&info) != SECSuccess) + { + if( ! (*env)->ExceptionOccurred(env) ) { + JSS_throwMsg(env, TOKEN_EXCEPTION, + "PK11_TraverseSlot returned an error"); + } + goto finish; + } + +finish: + return; +} + +/************************************************************************ + * + * J S S _ g e t S t o r e S l o t P t r + * + * Retrieve the PK11SlotInfo pointer of the given PK11Store. + * + * INPUTS + * store + * A reference to a Java PK11Store + * slot + * address of a PK11SlotInfo* that will be loaded with + * the PK11SlotInfo pointer of the given token. + * RETURNS + * PR_SUCCESS if the operation was successful, PR_FAILURE if an + * exception was thrown. + */ +PR_IMPLEMENT( PRStatus ) +JSS_PK11_getStoreSlotPtr(JNIEnv *env, jobject store, PK11SlotInfo **slot) +{ + PR_ASSERT(env!=NULL && store!=NULL && slot!=NULL); + + return JSS_getPtrFromProxyOwner(env, store, PK11STORE_PROXY_FIELD, + PK11STORE_PROXY_SIG, (void**)slot); +} + +/********************************************************************** + * PK11Store.deletePrivateKey + */ +JNIEXPORT void JNICALL +Java_com_netscape_jss_pkcs11_PK11Store_deletePrivateKey + (JNIEnv *env, jobject this, jobject key) +{ + PK11SlotInfo *slot; + SECKEYPrivateKey *privk; + + PR_ASSERT(env!=NULL && this!=NULL); + if(key == NULL) { + JSS_throw(env, NO_SUCH_ITEM_ON_TOKEN_EXCEPTION); + goto finish; + } + + /************************************************** + * Get the C structures + **************************************************/ + if( JSS_PK11_getStoreSlotPtr(env, this, &slot) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + goto finish; + } + + if( JSS_PK11_getPrivKeyPtr(env, key, &privk) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + goto finish; + } + + /*************************************************** + * Validate structures + ***************************************************/ + + /* A private key may be temporary, but you can't use this function + * to delete it. Instead, just let it be garbage collected */ + if( privk->pkcs11IsTemp ) { + PR_ASSERT(PR_FALSE); + JSS_throwMsg(env, TOKEN_EXCEPTION, + "Private Key is not a permanent PKCS #11 object"); + goto finish; + } + + if( slot != privk->pkcs11Slot) { + JSS_throw(env, NO_SUCH_ITEM_ON_TOKEN_EXCEPTION); + goto finish; + } + + /*************************************************** + * Perform the destruction + ***************************************************/ + if( PK11_DestroyTokenObject(privk->pkcs11Slot, privk->pkcs11ID) + != SECSuccess) + { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Unable to actually destroy object"); + goto finish; + } + +finish: + return; +} + +/********************************************************************** + * PK11Store.deleteCert + */ +JNIEXPORT void JNICALL +Java_com_netscape_jss_pkcs11_PK11Store_deleteCert + (JNIEnv *env, jobject this, jobject certObject) +{ + PK11SlotInfo *slot, *certSlot=NULL; + CK_OBJECT_HANDLE certID; + CERTCertificate *cert; + + PR_ASSERT(env!=NULL && this!=NULL); + if(certObject == NULL) { + JSS_throw(env, NO_SUCH_ITEM_ON_TOKEN_EXCEPTION); + goto finish; + } + + /************************************************** + * Get the C structures + **************************************************/ + if( JSS_PK11_getStoreSlotPtr(env, this, &slot) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + goto finish; + } + + if( JSS_PK11_getCertPtr(env, certObject, &cert) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + goto finish; + } + + certID = PK11_FindObjectForCert(cert, NULL, &certSlot); + + /*************************************************** + * Validate structures + ***************************************************/ + if( slot != certSlot) { + if( certSlot == NULL ) { + /* try deleting from internal cert database */ + if( SEC_DeletePermCertificate(cert) != SECSuccess) { + JSS_throwMsg(env, TOKEN_EXCEPTION, + "Unable to delete certificate from internal database"); + } + } else { + JSS_throw(env, NO_SUCH_ITEM_ON_TOKEN_EXCEPTION); + } + goto finish; /* in any case we're done */ + } + + /*************************************************** + * Perform the destruction + ***************************************************/ + if( PK11_Authenticate(certSlot, PR_TRUE /*loadCerts*/, NULL /*wincx*/) + != SECSuccess) + { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Unable to login to token"); + goto finish; + } + if( PK11_DestroyTokenObject(certSlot, certID) != SECSuccess) + { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Unable to actually destroy object"); + goto finish; + } + + if ((cert->istemp != PR_TRUE) && (cert->istemp != PR_FALSE)) { + /* the cloning feature somehow doesn't have istemp initialized */ + cert->istemp = PR_FALSE; + } + + /* This call returns SECSuccess if cert istemp is PR_FALSE */ + if (cert->istemp == PR_TRUE) { + if( CERT_DeleteTempCertificate(cert) != SECSuccess ) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Unable to delete temporary cert"); + goto finish; + } + } + +finish: + if(certSlot != NULL) { + PK11_FreeSlot(certSlot); + } + return; +} + +#define DER_DEFAULT_CHUNKSIZE (2048) + +/*********************************************************************** + * passwordToSecitem + * + * Converts a Java Password object to a SECItem, first hashing with + * global salt. The Java Password object will be cleared. + * Returns NULL iff an exception was thrown. + */ +static SECItem* +passwordToSecitem(JNIEnv *env, jobject pwObject, jbyteArray globalSaltArray) +{ + jclass passwordClass; + jmethodID getByteCopyMethod; + jmethodID clearMethod; + jbyteArray pwArray; + SECItem *ret=NULL; + jbyte *pwChars; + jthrowable excep; + SECItem *salt = NULL; + + PR_ASSERT(env!=NULL && pwObject!=NULL); + + ret = (SECItem*) PR_NEW(SECItem); + if(ret == NULL) { + JSS_throw(env, OUT_OF_MEMORY_ERROR); + goto finish; + } + + /***************************************** + * Get Password class and methods + *****************************************/ + passwordClass = (*env)->GetObjectClass(env, pwObject); + if(passwordClass == NULL) { + goto finish; + } + getByteCopyMethod = (*env)->GetMethodID( + env, + passwordClass, + PW_GET_BYTE_COPY_NAME, + PW_GET_BYTE_COPY_SIG); + clearMethod = (*env)->GetMethodID( env, + passwordClass, + PW_CLEAR_NAME, + PW_CLEAR_SIG); + if(getByteCopyMethod==NULL || clearMethod==NULL) { + goto finish; + } + + /*************************************************** + * Get the salt + ***************************************************/ + salt = PR_NEW(SECItem); + if( salt == NULL ) { + JSS_throw(env, OUT_OF_MEMORY_ERROR); + goto finish; + } + salt->len = (*env)->GetArrayLength(env, globalSaltArray); + PR_ASSERT(salt->len > 0); + salt->data = (unsigned char*) + (*env)->GetByteArrayElements(env, globalSaltArray, NULL); + if( salt->data == NULL ) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + /************************************************ + * Get the bytes from the password, then clear it + ***********************************************/ + pwArray = (*env)->CallObjectMethod( env, pwObject, getByteCopyMethod); + (*env)->CallVoidMethod(env, pwObject, clearMethod); + if(pwArray == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + /************************************************************* + * Copy the characters out of the byte array, + *************************************************************/ + pwChars = (*env)->GetByteArrayElements(env, pwArray, NULL); + if(pwChars == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + /* hash the password into a SECItem */ + ret = SECKEY_HashPassword( (char*) pwChars, salt); + + /*************************************************** + * Clear the array. + ***************************************************/ + memset(pwChars, 0, ret->len); + (*env)->ReleaseByteArrayElements(env, pwArray, pwChars, 0); + +finish: + if( (excep=(*env)->ExceptionOccurred(env)) ) { + (*env)->ExceptionClear(env); + } + if(salt) { + if(salt->data) { + (*env)->ReleaseByteArrayElements(env, globalSaltArray, + (jbyte*) salt->data, JNI_ABORT); + } + PR_Free(salt); + } + if( excep ) { + (*env)->Throw(env, excep); + } + return ret; +} + +typedef enum { + SUCCESS=0, + TOKEN_FAILURE, + DECODE_FAILURE, + LOGIN_FAILURE, + OUT_OF_MEM, + KEYID_FAILURE, + KEY_EXISTS +} ImportResult; + + + +SECKEYLowPrivateKey * +seckey_decrypt_private_key(SECKEYEncryptedPrivateKeyInfo *epki, + SECItem *pwitem); + +SECKEYEncryptedPrivateKeyInfo * +seckey_encrypt_private_key( + SECKEYLowPrivateKey *pk, SECItem *pwitem, SECKEYKeyDBHandle *keydb, + SECOidTag algorithm); + +int PK11_NumberObjectsFor(PK11SlotInfo*, CK_ATTRIBUTE*, int); + + +/*********************************************************************** + * decoding part copied from keydb.c seckey_decode_encrypted_private_key + + */ +static ImportResult +decodeAndImportEncryptedKey(SECKEYDBKey *dbkey, SECItem *pwitem, + PK11SlotInfo *slot, KeyType keyType, PRBool temporary) +{ + SECKEYLowPrivateKey *pk = NULL; + SECKEYEncryptedPrivateKeyInfo *epki=NULL; + SECKEYEncryptedPrivateKeyInfo *newepki=NULL; + PRArenaPool *temparena = NULL; + SECStatus rv = SECFailure; + SECOidTag algorithm; + SECItem *publicValue = NULL; + SECItem nickname; + ImportResult result=DECODE_FAILURE; + + PR_ASSERT(dbkey!=NULL && pwitem!=NULL); + + temparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if(temparena == NULL) { + return OUT_OF_MEM; + } + + epki = (SECKEYEncryptedPrivateKeyInfo *) + PORT_ArenaZAlloc(temparena, sizeof(SECKEYEncryptedPrivateKeyInfo)); + if(epki == NULL) { + goto loser; + } + + rv = SEC_ASN1DecodeItem(temparena, epki, + SECKEY_EncryptedPrivateKeyInfoTemplate, + &(dbkey->derPK)); + if(rv != SECSuccess) { + goto loser; + } + + algorithm = SECOID_GetAlgorithmTag(&(epki->algorithm)); + switch(algorithm) + { + case SEC_OID_RC4: + rv = SECITEM_CopyItem(temparena, &(epki->algorithm.parameters), + &(dbkey->salt)); + break; + default: + break; + } + + pk = seckey_decrypt_private_key(epki, pwitem); + if(pk == NULL) { + result = DECODE_FAILURE; + goto loser; + } + + if(pk->keyType == dsaKey) { + publicValue = &pk->u.dsa.publicValue; + } else { + PR_ASSERT( pk->keyType == rsaKey ); + publicValue = &pk->u.rsa.modulus; + } + + newepki = seckey_encrypt_private_key(pk, pwitem, NULL /*keydb*/, + SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4); + if(newepki == NULL) { + result = DECODE_FAILURE; + goto loser; + } + + /*************************************************** + * Login to the token if necessary + ***************************************************/ + if( PK11_Authenticate(slot, PR_TRUE /*loadcerts*/, NULL /*wincx*/) + != SECSuccess) + { + result = LOGIN_FAILURE; + goto loser; + } + + + /************************************************** + * HACK to workaround bug #323494 + * On internal token, must call C_FindObjectsInit before creating + * any token objects. + *************************************************/ + if( slot==PK11_GetInternalSlot() || slot==PK11_GetInternalKeySlot() ) { + CK_ATTRIBUTE attr; + CK_OBJECT_CLASS class = CKO_PRIVATE_KEY; + + attr.type = CKA_CLASS; + attr.pValue = &class; + attr.ulValueLen = sizeof(class); + + PK11_NumberObjectsFor(slot, &attr, 1); + } + + nickname.len = 0; + nickname.data = NULL; + rv = PK11_ImportEncryptedPrivateKeyInfo(slot, newepki, pwitem, &nickname, + publicValue, !temporary, PR_TRUE /*private*/, keyType, + 0 /*default key usage*/, NULL /*wincx*/); + if(rv == SECSuccess) { + result = SUCCESS; + } else { + result = TOKEN_FAILURE; + } + +loser: + if(pk) { + SECKEY_LowDestroyPrivateKey(pk); + } + if(newepki) { + SECKEY_DestroyEncryptedPrivateKeyInfo(newepki, PR_TRUE /* freeit */); + } + PORT_FreeArena(temparena, PR_TRUE); + return result; +} + +/*********************************************************************** + * decoding part copied from keydb.c seckey_decode_encrypted_private_key + + */ +static ImportResult +decodeAndImportKey(SECItem *dervalue, + PK11SlotInfo *slot, KeyType keyType, PRBool temporary) +{ + SECKEYLowPrivateKey *pk = NULL; + SECKEYPrivateKeyInfo *pki = NULL; + PRArenaPool *temparena = NULL; + PRArenaPool *pkarena = NULL; + SECStatus rv = SECFailure; + SECOidTag algorithm; + SECItem *publicValue = NULL; + SECItem *keyid = NULL; + SECKEYPrivateKey *existingpk = NULL; + SECItem nickname; + ImportResult result=DECODE_FAILURE; + + PR_ASSERT(dervalue!=NULL); + + temparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + pkarena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + + if(temparena == NULL) { + return OUT_OF_MEM; + } + if(pkarena == NULL) { + return OUT_OF_MEM; + } + + pki = (SECKEYPrivateKeyInfo *) + PORT_ArenaZAlloc(temparena, sizeof(SECKEYPrivateKeyInfo)); + if(pki == NULL) { + result = DECODE_FAILURE; + goto loser; + } + + pk = (SECKEYLowPrivateKey *) + PORT_ArenaZAlloc(temparena, sizeof(SECKEYLowPrivateKey)); + if(pk == NULL) { + result = DECODE_FAILURE; + goto loser; + } + + rv = SEC_ASN1DecodeItem(temparena, pki, + SECKEY_PrivateKeyInfoTemplate, + dervalue); + if(rv != SECSuccess) { + goto loser; + } + + + /* decode the PublicKey from inside the PublicKeyInfo structure */ + /* the format of this encoding is defined by the algorithm + in the publickeyinfo, so we have to use different ASN + templates depending on which key is which */ + + switch(SECOID_GetAlgorithmTag(&pki->algorithm)) { + case SEC_OID_X500_RSA_ENCRYPTION: + case SEC_OID_PKCS1_RSA_ENCRYPTION: + pk->keyType = rsaKey; + rv = SEC_ASN1DecodeItem(pkarena, pk, + SECKEY_RSAPrivateKeyTemplate, + &pki->privateKey); + break; + case SEC_OID_ANSIX9_DSA_SIGNATURE: + pk->keyType = dsaKey; + rv = SEC_ASN1DecodeItem(pkarena, pk, + SECKEY_DSAPrivateKeyTemplate, + &pki->privateKey); + if (rv != SECSuccess) + goto loser; + rv = SEC_ASN1DecodeItem(pkarena, &pk->u.dsa.params, + SECKEY_PQGParamsTemplate, + &pki->algorithm.parameters); + break; + default: + rv = SECFailure; + break; + } + + /* pull out public key */ + + if(pk->keyType == dsaKey) { + publicValue = &pk->u.dsa.publicValue; + } else { + PR_ASSERT( pk->keyType == rsaKey ); + publicValue = &pk->u.rsa.modulus; + } + + /*************************************************** + * Login to the token if necessary + ***************************************************/ + if( PK11_Authenticate(slot, PR_TRUE /*loadcerts*/, NULL /*wincx*/) + != SECSuccess) + { + result = LOGIN_FAILURE; + goto loser; + } + + /*************************************************** + * Throw a 'key exists' exception if the key is + * already in the token + ***************************************************/ + /* first make the key id - a 'nickname' for the key + derived from the public key + */ + keyid = PK11_MakeIDFromPubKey(publicValue); + if (keyid == NULL) { + result = KEYID_FAILURE; + goto loser; + } + existingpk = PK11_FindKeyByKeyID(slot,keyid,NULL); + if (existingpk != NULL) { + result = KEY_EXISTS; + goto loser; + } + + /************************************************** + * HACK to workaround bug #323494 + * On internal token, must call C_FindObjectsInit before creating + * any token objects. + *************************************************/ + if( slot==PK11_GetInternalSlot() || slot==PK11_GetInternalKeySlot() ) { + CK_ATTRIBUTE attr; + CK_OBJECT_CLASS class = CKO_PRIVATE_KEY; + + attr.type = CKA_CLASS; + attr.pValue = &class; + attr.ulValueLen = sizeof(class); + + PK11_NumberObjectsFor(slot, &attr, 1); + } + + nickname.len = 0; + nickname.data = NULL; + + rv = PK11_ImportPrivateKeyInfo(slot, pki, &nickname, + publicValue, PR_TRUE /*PERM*/, PR_TRUE /*PRIVATE*/, + 0 /*keyusage*/, NULL /*wincx*/ ); + + if(rv == SECSuccess) { + result = SUCCESS; + } else { + result = TOKEN_FAILURE; + /* if the public key import failed, we are responsible + freeing this memory - otherwise it's the + responsiblity of the owner of the key */ + PORT_FreeArena(pkarena, PR_TRUE); + } + +loser: + if(existingpk) { + SECKEY_DestroyPrivateKey(existingpk); + } + if(keyid) { + SECITEM_FreeItem(keyid,PR_TRUE); + } + if(pk) { + SECKEY_LowDestroyPrivateKey(pk); + } + if(pki) { + SECKEY_DestroyPrivateKeyInfo(pki, PR_TRUE /* freeit */); + } + PORT_FreeArena(temparena, PR_TRUE); + return result; +} + + +/*********************************************************************** + * importEncryptedPrivateKey + */ +static void +importEncryptedPrivateKey + ( JNIEnv *env, + jobject this, + jbyteArray encodedKeyArray, + jobject passwordObject, + jbyteArray saltArray, + jbyteArray globalSaltArray, + jobject keyTypeObj, + PRBool temporary ) +{ + SECKEYDBKey dbkey; + SECItem *pwitem=NULL; + ImportResult result; + PK11SlotInfo *slot; + jthrowable excep; + KeyType keyType; + + + keyType = JSS_PK11_getKeyType(env, keyTypeObj); + if( keyType == nullKey ) { + /* exception was thrown */ + goto finish; + } + + /* + * initialize so we can goto finish + */ + dbkey.arena = NULL; + dbkey.version = 0; + dbkey.nickname = NULL; + dbkey.salt.data = NULL; + dbkey.salt.len = 0; + dbkey.derPK.data = NULL; + dbkey.derPK.len = 0; + + + PR_ASSERT(env!=NULL && this!=NULL); + + if(encodedKeyArray == NULL || passwordObject==NULL || saltArray==NULL) { + JSS_throw(env, NULL_POINTER_EXCEPTION); + goto finish; + } + + /* + * Extract the encoded key into the DBKEY + */ + dbkey.derPK.len = (*env)->GetArrayLength(env, encodedKeyArray); + if(dbkey.derPK.len <= 0) { + JSS_throwMsg(env, INVALID_KEY_FORMAT_EXCEPTION, "Key array is empty"); + goto finish; + } + dbkey.derPK.data = (unsigned char*) + (*env)->GetByteArrayElements(env, encodedKeyArray, NULL); + if(dbkey.derPK.data == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + /* + * Extract the salt into the DBKEY + */ + dbkey.salt.len = (*env)->GetArrayLength(env, saltArray); + if(dbkey.salt.len <= 0) { + JSS_throwMsg(env, INVALID_KEY_FORMAT_EXCEPTION, "Salt array is empty"); + goto finish; + } + dbkey.salt.data = (unsigned char*) + (*env)->GetByteArrayElements(env, saltArray, NULL); + if(dbkey.salt.data == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + /* + * Extract the password into a SECItem, which has the side effect + * of clearing the password. + */ + pwitem = passwordToSecitem(env, passwordObject, globalSaltArray); + if(pwitem == NULL) { + PR_ASSERT( (*env)->ExceptionOccurred(env) ); + goto finish; + } + + /* + * Get the PKCS #11 slot + */ + if( JSS_PK11_getStoreSlotPtr(env, this, &slot) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + goto finish; + } + + /* + * Now decode and import + */ + result = decodeAndImportEncryptedKey(&dbkey, pwitem, slot, keyType, temporary); + if( result == TOKEN_FAILURE ) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Failed to import key to token"); + } else if( result == DECODE_FAILURE ) { + JSS_throwMsg(env, INVALID_KEY_FORMAT_EXCEPTION, + "Failed to decode key"); + } else if( result == LOGIN_FAILURE ) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Failed to login to token"); + } else { + PR_ASSERT( result == SUCCESS ); + } + +finish: + /* Save any exceptions */ + if( (excep=(*env)->ExceptionOccurred(env)) ) { + (*env)->ExceptionClear(env); + } + if(dbkey.derPK.data != NULL) { + (*env)->ReleaseByteArrayElements( env, + encodedKeyArray, + (jbyte*) dbkey.derPK.data, + JNI_ABORT ); + } + if(dbkey.salt.data != NULL) { + (*env)->ReleaseByteArrayElements( env, + saltArray, + (jbyte*) dbkey.salt.data, + JNI_ABORT ); + } + if(pwitem) { + SECITEM_ZfreeItem(pwitem, PR_TRUE); + } + /* now re-throw the exception */ + if( excep ) { + (*env)->Throw(env, excep); + } +} + + +/*********************************************************************** + * PK11Store.importEncryptedPrivateKey + */ +JNIEXPORT void JNICALL +Java_com_netscape_jss_pkcs11_PK11Store_importEncryptedPrivateKey + ( JNIEnv *env, + jobject this, + jbyteArray encodedKeyArray, + jobject passwordObject, + jbyteArray saltArray, + jbyteArray globalSaltArray, + jobject keyTypeObj ) +{ + importEncryptedPrivateKey(env, this, encodedKeyArray, passwordObject, + saltArray, globalSaltArray, keyTypeObj, PR_FALSE /* not temporary */); +} + +/*********************************************************************** + * importPrivateKey + */ +static void +importPrivateKey + ( JNIEnv *env, + jobject this, + jbyteArray keyArray, + jobject keyTypeObj, + PRBool temporary ) +{ + SECItem derPK; + ImportResult result; + PK11SlotInfo *slot; + jthrowable excep; + KeyType keyType; + + + keyType = JSS_PK11_getKeyType(env, keyTypeObj); + if( keyType == nullKey ) { + /* exception was thrown */ + goto finish; + } + + /* + * initialize so we can goto finish + */ + /* dbkey.arena = NULL; */ + derPK.data = NULL; + derPK.len = 0; + + + PR_ASSERT(env!=NULL && this!=NULL); + + if(keyArray == NULL) { + JSS_throw(env, NULL_POINTER_EXCEPTION); + goto finish; + } + + /* + * copy the java byte array into a local copy + */ + derPK.len = (*env)->GetArrayLength(env, keyArray); + if(derPK.len <= 0) { + JSS_throwMsg(env, INVALID_KEY_FORMAT_EXCEPTION, "Key array is empty"); + goto finish; + } + derPK.data = (unsigned char*) + (*env)->GetByteArrayElements(env, keyArray, NULL); + if(derPK.data == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + /* + * Get the PKCS #11 slot + */ + if( JSS_PK11_getStoreSlotPtr(env, this, &slot) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + goto finish; + } + + /* + * Now decode and import + */ + result = decodeAndImportKey(&derPK, slot, keyType, temporary); + if( result == TOKEN_FAILURE ) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Failed to import key to token"); + } else if( result == DECODE_FAILURE ) { + JSS_throwMsg(env, INVALID_KEY_FORMAT_EXCEPTION, + "Failed to decode key"); + } else if( result == KEY_EXISTS) { + JSS_throwMsg(env, KEY_EXISTS_EXCEPTION, "Key already in token"); + } else if( result == KEYID_FAILURE ) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Error creating Key ID"); + } else if( result == LOGIN_FAILURE ) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Failed to login to token"); + } else { + PR_ASSERT( result == SUCCESS ); + } + +finish: + /* Save any exceptions */ + if( (excep=(*env)->ExceptionOccurred(env)) ) { + (*env)->ExceptionClear(env); + } + if(derPK.data != NULL) { + (*env)->ReleaseByteArrayElements( env, + keyArray, + (jbyte*) derPK.data, + JNI_ABORT ); + } + /* now re-throw the exception */ + if( excep ) { + (*env)->Throw(env, excep); + } +} + + +/*********************************************************************** + * PK11Store.importdPrivateKey + */ +JNIEXPORT void JNICALL +Java_com_netscape_jss_pkcs11_PK11Store_importPrivateKey + ( JNIEnv *env, + jobject this, + jbyteArray keyArray, + jobject keyTypeObj ) +{ + importPrivateKey(env, this, keyArray, + keyTypeObj, PR_FALSE /* not temporary */); +} + +/*********************************************************************** + * PK11Store.importTemporaryEncryptedPrivateKey + */ +JNIEXPORT void JNICALL +Java_com_netscape_jss_pkcs11_PK11Store_importTemporaryEncryptedPrivateKey + ( JNIEnv *env, + jobject this, + jbyteArray encodedKeyArray, + jobject passwordObject, + jbyteArray saltArray, + jbyteArray globalSaltArray, + jobject keyTypeObj ) +{ + importEncryptedPrivateKey(env, this, encodedKeyArray, passwordObject, + saltArray, globalSaltArray, keyTypeObj, PR_FALSE /* temporary */); +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Store.java b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Store.java new file mode 100644 index 00000000000..18672fcbb6b --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Store.java @@ -0,0 +1,140 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs11; + +import com.netscape.jss.crypto.*; +import com.netscape.jss.util.*; +import java.security.cert.CertificateEncodingException; +import java.util.Vector; + +public final class PK11Store implements CryptoStore { + + //////////////////////////////////////////////////////////// + // Private Keys + //////////////////////////////////////////////////////////// + public native void + importEncryptedPrivateKey( byte[] encodedKey, + Password password, + byte[] salt, + byte[] globalSalt, + PrivateKey.Type type ) + throws InvalidKeyFormatException, TokenException; + + /** + * Imports a raw private key into this token. + * + * @param key The private key. + * @exception TokenException If the key cannot be imported to this token. + * @exception KeyAlreadyImportedException If the key already on this token. + */ + public native void + importPrivateKey( byte[] key, + PrivateKey.Type type ) + throws TokenException,KeyAlreadyImportedException; + + + + /** + * @deprecated + */ + public void + importEncryptedPrivateKey( byte[] encodedKey, + Password password, + byte[] salt, + byte[] globalSalt ) + throws InvalidKeyFormatException, TokenException { + + importEncryptedPrivateKey( encodedKey, password, salt, globalSalt, + PrivateKey.RSA ); + } + + + public native void + importTemporaryEncryptedPrivateKey( byte[] encodedKey, + Password password, + byte[] salt, + byte[] globalSalt, + PrivateKey.Type type ) + throws InvalidKeyFormatException, TokenException; + + public synchronized PrivateKey[] + getPrivateKeys() throws TokenException { + Vector keys = new Vector(); + putKeysInVector(keys); + PrivateKey[] array = new PrivateKey[keys.size()]; + keys.copyInto( (Object[]) array ); + return array; + } + protected native void putKeysInVector(Vector keys) throws TokenException; + + + public native void deletePrivateKey(PrivateKey key) + throws NoSuchItemOnTokenException, TokenException; + + //////////////////////////////////////////////////////////// + // Certs + //////////////////////////////////////////////////////////// + + public X509Certificate[] + getCertificates() throws TokenException + { + Vector certs = new Vector(); + putCertsInVector(certs); + X509Certificate[] array = new X509Certificate[certs.size()]; + certs.copyInto( (Object[]) array ); + return array; + } + protected native void putCertsInVector(Vector certs) throws TokenException; + + // Currently have to use PK11_DeleteTokenObject + PK11_FindObjectForCert + // or maybe SEC_DeletePermCertificate. + public native void deleteCert(X509Certificate cert) + throws NoSuchItemOnTokenException, TokenException; + + //////////////////////////////////////////////////////////// + // Construction + //////////////////////////////////////////////////////////// + protected boolean updated; + public PK11Store(TokenProxy proxy) { + Assert.assert(proxy!=null); + this.storeProxy = proxy; + } + + protected PK11Store() { } + + //////////////////////////////////////////////////////////// + // Private data + //////////////////////////////////////////////////////////// + protected TokenProxy storeProxy; +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11SymKey.c b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11SymKey.c new file mode 100644 index 00000000000..da9eec06f58 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11SymKey.c @@ -0,0 +1,321 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +#include "_jni/com_netscape_jss_pkcs11_SymKeyProxy.h" + +#include +#include +#include +#include + +#include +#include +#include +#include "pk11util.h" + +/*********************************************************************** + * + * J S S _ P K 1 1 _ w r a p S y m K e y + + * Puts a Symmetric Key into a Java object. + * (Does NOT perform a cryptographic "wrap" operation.) + * symKey: will be stored in a Java wrapper. + * Returns: a new PK11SymKey, or NULL if an exception occurred. + */ +PR_IMPLEMENT( jobject ) +JSS_PK11_wrapSymKey(JNIEnv *env, PK11SymKey **symKey) +{ + jclass keyClass; + jmethodID constructor; + jbyteArray ptrArray; + jobject Key=NULL; + + PR_ASSERT(env!=NULL && symKey!=NULL && *symKey!=NULL); + + /* find the class */ + keyClass = (*env)->FindClass(env, PK11SYMKEY_CLASS_NAME); + if( keyClass == NULL ) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + /* find the constructor */ + constructor = (*env)->GetMethodID(env, keyClass, + PLAIN_CONSTRUCTOR, + PK11SYMKEY_CONSTRUCTOR_SIG); + if(constructor == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + /* convert the pointer to a byte array */ + ptrArray = JSS_ptrToByteArray(env, (void*)*symKey); + if( ptrArray == NULL ) { + goto finish; + } + /* call the constructor */ + Key = (*env)->NewObject(env, keyClass, constructor, ptrArray); + +finish: + if(Key == NULL) { + PK11_FreeSymKey(*symKey); + } + *symKey = NULL; + return Key; +} + +/*********************************************************************** + * + * PK11SymKey.getOwningToken + */ +JNIEXPORT jobject JNICALL +Java_com_netscape_jss_pkcs11_PK11SymKey_getOwningToken + (JNIEnv *env, jobject this) +{ + PK11SymKey *key = NULL; + PK11SlotInfo *slot = NULL; + jobject token = NULL; + + PR_ASSERT(env!=NULL && this!=NULL); + + /* Get the C key structure */ + if( JSS_PK11_getSymKeyPtr(env, this, &key) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + goto finish; + } + + /* Get the slot this key lives on */ + slot = PK11_GetSlotFromKey(key); + PR_ASSERT(slot != NULL); + + /* Turn the slot into a Java PK11Token */ + token = JSS_PK11_wrapPK11Token(env, &slot); + if(token == NULL) { + PR_ASSERT( (*env)->ExceptionOccurred(env) ); + goto finish; + } + +finish: + if(slot != NULL) { + PK11_FreeSlot(slot); + } + return token; +} + +/*********************************************************************** + * + * PK11SymKey.getSize + */ +JNIEXPORT jint JNICALL +Java_com_netscape_jss_pkcs11_PK11SymKey_getStrength + (JNIEnv *env, jobject this) +{ + PK11SymKey *key=NULL; + int strength = 0; + + /* get the key pointer */ + if( JSS_PK11_getSymKeyPtr(env, this, &key) != PR_SUCCESS) { + goto finish; + } + + strength = PK11_GetKeyStrength(key, NULL /*algid*/); + +finish: + return strength; +} + +/*********************************************************************** + * + * PK11SymKey.getKeyData + */ +JNIEXPORT jbyteArray JNICALL +Java_com_netscape_jss_pkcs11_PK11SymKey_getKeyData + (JNIEnv *env, jobject this) +{ + PK11SymKey *key=NULL; + SECItem *keyData; /* a reference to the key data */ + jbyteArray dataArray=NULL; + + /* get the key pointer */ + if( JSS_PK11_getSymKeyPtr(env, this, &key) != PR_SUCCESS) { + goto finish; + } + + /* Extract the key data */ + if( PK11_ExtractKeyValue(key) != SECSuccess ) { + /* key is not extractable */ + JSS_throwMsg(env, NOT_EXTRACTABLE_EXCEPTION, "Unable to extract " + "symmetric key data"); + goto finish; + } + keyData = PK11_GetKeyData(key); + /* PK11_ExtractKeyValue should have failed if keyData is NULL */ + PR_ASSERT(keyData != NULL); + + /* copy the key data into a Java byte array */ + dataArray = JSS_SECItemToByteArray(env, keyData); + +finish: + /* keyData is just a reference, nothing to free */ + if( dataArray == NULL) { + PR_ASSERT( (*env)->ExceptionOccurred(env) ); + } + return dataArray; +} + +/*********************************************************************** + * + * PK11SymKey.getKeyType + */ +JNIEXPORT jobject JNICALL +Java_com_netscape_jss_pkcs11_PK11SymKey_getKeyType + (JNIEnv *env, jobject this) +{ + PK11SymKey *key=NULL; + CK_MECHANISM_TYPE keyMech; + char *typeFieldName=NULL; + jclass typeClass=NULL; + jfieldID typeField=NULL; + jobject typeObject=NULL; + + if( JSS_PK11_getSymKeyPtr(env, this, &key) != SECSuccess ) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + /* Look up the key type from the key */ + keyMech = PK11_GetMechanism(key); + switch(keyMech) { + /* PBE mechanisms have to be handled by hand */ + case CKM_PBE_MD2_DES_CBC: + case CKM_PBE_MD5_DES_CBC: + case CKM_NETSCAPE_PBE_SHA1_DES_CBC: + typeFieldName = DES_KEYTYPE_FIELD; + break; + case CKM_PBE_SHA1_RC4_128: + case CKM_PBE_SHA1_RC4_40: + typeFieldName = RC4_KEYTYPE_FIELD; + break; + case CKM_PBE_SHA1_RC2_128_CBC: + case CKM_PBE_SHA1_RC2_40_CBC: + typeFieldName = RC2_KEYTYPE_FIELD; + break; + case CKM_PBE_SHA1_DES3_EDE_CBC: + typeFieldName = DES3_KEYTYPE_FIELD; + break; + case CKM_PBA_SHA1_WITH_SHA1_HMAC: + typeFieldName = SHA1_HMAC_KEYTYPE_FIELD; + break; + default: + keyMech = PK11_GetKeyType( keyMech, 0 ); + switch(keyMech) { + case CKK_DES: + typeFieldName = DES_KEYTYPE_FIELD; + break; + case CKK_DES3: + typeFieldName = DES3_KEYTYPE_FIELD; + break; + case CKK_RC4: + typeFieldName = RC4_KEYTYPE_FIELD; + break; + case CKK_RC2: + typeFieldName = RC2_KEYTYPE_FIELD; + break; + default: + PR_ASSERT(PR_FALSE); + typeFieldName = DES_KEYTYPE_FIELD; + break; + } + break; + } + + /* convert to a Java key type */ + typeClass = (*env)->FindClass(env, KEYTYPE_CLASS_NAME); + if(typeClass == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + typeField = (*env)->GetStaticFieldID(env, typeClass, typeFieldName, + KEYTYPE_FIELD_SIG); + if(typeField == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + typeObject = (*env)->GetStaticObjectField(env, typeClass, typeField); + if(typeObject == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + +finish: + return typeObject; +} + + +/*********************************************************************** + * + * J S S _ P K 1 1 _ g e t S y m K e y P t r + * + */ +PR_IMPLEMENT( PRStatus ) +JSS_PK11_getSymKeyPtr(JNIEnv *env, jobject symKeyObject, PK11SymKey **ptr) +{ + PR_ASSERT(env!=NULL && symKeyObject!=NULL); + + /* Get the pointer from the key proxy */ + return JSS_getPtrFromProxyOwner(env, symKeyObject, SYM_KEY_PROXY_FIELD, + SYM_KEY_PROXY_SIG, (void**)ptr); +} + + +/*********************************************************************** + * + * SymKeyProxy.releaseNativeResources + */ +JNIEXPORT void JNICALL +Java_com_netscape_jss_pkcs11_SymKeyProxy_releaseNativeResources + (JNIEnv *env, jobject this) +{ + PK11SymKey *key=NULL; + + PR_ASSERT(env!=NULL && this!=NULL); + + if( JSS_getPtrFromProxy(env, this, (void**)&key) == PR_SUCCESS) { + PK11_FreeSymKey(key); + } else { + /* can't really throw an exception from a destructor */ + PR_ASSERT(PR_FALSE); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11SymKey.java b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11SymKey.java new file mode 100644 index 00000000000..1c74eefd0b7 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11SymKey.java @@ -0,0 +1,94 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs11; + +import com.netscape.jss.crypto.*; +import com.netscape.jss.util.Assert; + +public final class PK11SymKey implements SymmetricKey { + + protected PK11SymKey(byte[] pointer) { + Assert.assert(pointer!=null); + keyProxy = new SymKeyProxy(pointer); + } + + private SymKeyProxy keyProxy; + + public SymmetricKey.Type getType() { + KeyType kt = getKeyType(); + if(kt == KeyType.DES) { + return DES; + } else if(kt == KeyType.DES3) { + return DES3; + } else if(kt == KeyType.RC4) { + return RC4; + } else if(kt == KeyType.RC2) { + return RC2; + } else { + Assert.notReached("Unrecognized key type"); + return DES; + } + } + + public native CryptoToken getOwningToken(); + + /** + * Returns key strength, measured as the number of bits of secret material. + * NOTE: Due to a bug in the security library (333440), this + * may return a wrong answer for PBE keys that have embedded parity + * (like DES). A DES key is 56 bits of information plus + * 8 bits of parity, so it takes up 64 bits. For a normal DES key, + * this method will correctly return 56, but for a PBE-generated DES key, + * the security library bug causes it to return 64. + */ + public native int getStrength(); + + public native byte[] getKeyData() + throws SymmetricKey.NotExtractableException; + + public native KeyType getKeyType(); +} + +class SymKeyProxy extends KeyProxy { + + public SymKeyProxy(byte[] pointer) { + super(pointer); + } + + protected native void releaseNativeResources(); + + protected void finalize() throws Throwable { + super.finalize(); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Token.c b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Token.c new file mode 100644 index 00000000000..66351d028db --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Token.c @@ -0,0 +1,1268 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +#include "_jni/com_netscape_jss_pkcs11_PK11Token.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include "java_ids.h" + +#include "pk11util.h" +#include + +#define ERRX 1 +#define KEYTYPE_DSA_STRING "dsa" +#define KEYTYPE_RSA_STRING "rsa" +#define KEYTYPE_DSA 1 +#define KEYTYPE_RSA 2 + +static CERTCertificateRequest* make_cert_request(JNIEnv *env, + const char *subject, SECKEYPublicKey *pubk); +void GenerateCertRequest(JNIEnv *env, unsigned int ktype, const char *subject, + int keysize, PK11SlotInfo *slot, + unsigned char **b64request, PQGParams *dsaParams); +static SECStatus GenerateKeyPair(JNIEnv *env, unsigned int ktype, + PK11SlotInfo *slot, + SECKEYPublicKey **pubk, + SECKEYPrivateKey **privk, int keysize, PQGParams *dsaParams); + +/* these values are taken from PK11KeyPairGenerator.java */ +#define DEFAULT_RSA_KEY_SIZE 2048 +#define DEFAULT_RSA_PUBLIC_EXPONENT 0x10001 + +/*********************************************************************** + * + * J S S _ P K 1 1 _ w r a p P K 1 1 T o k e n + * + * Create a PK11Token object from a PKCS #11 slot. + * + * slot is a pointer to a PKCS #11 slot, which must not be NULL. It will + * be eaten by the wrapper, so you can't use it after you call this. + * + * Returns a new PK11Token object, or NULL if an exception was thrown. + */ +PR_IMPLEMENT( jobject ) +JSS_PK11_wrapPK11Token(JNIEnv *env, PK11SlotInfo **slot) +{ + jclass tokenClass; + jmethodID constructor; + jbyteArray byteArray; + jobject Token=NULL; + jboolean internal; + jboolean keyStorage; + + PR_ASSERT(env!=NULL && slot!=NULL && *slot!=NULL); + + internal = (*slot == PK11_GetInternalSlot()); + keyStorage = (*slot == PK11_GetInternalKeySlot()); + + byteArray = JSS_ptrToByteArray(env, (void*)*slot); + + /* + * Lookup the class and constructor + */ + tokenClass = (*env)->FindClass(env, PK11TOKEN_CLASS_NAME); + if(tokenClass == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + constructor = (*env)->GetMethodID( + env, + tokenClass, + PK11TOKEN_CONSTRUCTOR_NAME, + PK11TOKEN_CONSTRUCTOR_SIG); + if(constructor == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + /* Call the constructor */ + Token = (*env)->NewObject(env, + tokenClass, + constructor, + byteArray, + internal, + keyStorage); + +finish: + if(Token==NULL) { + PK11_FreeSlot(*slot); + } + *slot = NULL; + return Token; +} + +#if 0 +/* + * PK11Token.needsLogin + * Returns true if this token needs to be logged in before it can be used. + */ +JNIEXPORT jboolean JNICALL Java_com_netscape_jss_pkcs11_PK11Token_needsLogin + (JNIEnv *env, jobject this) +{ + PK11SlotInfo *slot; + jboolean retval; + + PR_ASSERT(env!=NULL && this!=NULL); + + if(JSS_PK11_getTokenSlotPtr(env, this, &slot) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + /* an exception was thrown */ + retval = JNI_FALSE; + goto finish; + } + PR_ASSERT(slot != NULL); + + if(PK11_NeedLogin(slot) == PR_TRUE) { + retval = JNI_TRUE; + } else { + retval = JNI_FALSE; + } + +finish: + return retval; +} +#endif + +/************************************************************************ + * + * P K 1 1 T o k e n . i s L o g g e d I n + * + * Returns true if this token is logged in. + */ +JNIEXPORT jboolean JNICALL Java_com_netscape_jss_pkcs11_PK11Token_isLoggedIn + (JNIEnv *env, jobject this) +{ + PK11SlotInfo *slot; + jboolean retval; + + PR_ASSERT(env!=NULL && this!=NULL); + + if(JSS_PK11_getTokenSlotPtr(env, this, &slot) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + /* an exception was thrown */ + retval = JNI_FALSE; + goto finish; + } + PR_ASSERT(slot != NULL); + + if(PK11_IsLoggedIn(slot, NULL) == PR_TRUE) { + retval = JNI_TRUE; + } else { + retval = JNI_FALSE; + } + +finish: + return retval; +} + +/************************************************************************ + * + * P K 1 1 T o k e n . n a t i v e L o g i n + * + * Attempts to login to the token with the given password callback. + * Throws NotInitializedException if the token is not initialized. + * Throws IncorrectPINException if the supplied PIN is incorrect. + */ +JNIEXPORT void JNICALL Java_com_netscape_jss_pkcs11_PK11Token_nativeLogin + (JNIEnv *env, jobject this, jobject callback) +{ + PK11SlotInfo *slot; + + PR_ASSERT(env!=NULL && this!=NULL && callback!=NULL); + + if(JSS_PK11_getTokenSlotPtr(env, this, &slot) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + /* an exception was thrown */ + goto finish; + } + PR_ASSERT(slot != NULL); + + /* Is the token initialized? */ + if(PK11_NeedUserInit(slot)) { + JSS_nativeThrow( + env, + TOKEN_NOT_INITIALIZED_EXCEPTION + ); + goto finish; + } + + if(PK11_Authenticate(slot, PR_TRUE /*loadCerts*/, (void*)callback) + != SECSuccess) + { + JSS_nativeThrow(env, INCORRECT_PASSWORD_EXCEPTION); + goto finish; + } + + /* Success! */ +finish: + return; +} + +/************************************************************************ + * + * P K 1 1 T o k e n . l o g o u t + */ +JNIEXPORT void JNICALL Java_com_netscape_jss_pkcs11_PK11Token_logout + (JNIEnv *env, jobject this) +{ + PK11SlotInfo *slot; + + PR_ASSERT(env!=NULL && this!=NULL); + + + if( JSS_PK11_getTokenSlotPtr(env, this, &slot) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + /* an exception occurred */ + goto finish; + } + PR_ASSERT(slot != NULL); + + if( PK11_Logout(slot) != SECSuccess) { + JSS_nativeThrowMsg( env, + TOKEN_EXCEPTION, + "Unable to logout token" + ); + goto finish; + } + +finish: + return; +} + +/************************************************************************ + * + * P K 1 1 T o k e n . g e t L o g i n M o d e + * + * Returns the login mode (ONE_TIME, TIMEOUT, EVERY_TIME) for this token. + * These constants must sync with the ones defined in CryptoToken. + */ +#define ONE_TIME 0 +#define TIMEOUT 1 +#define EVERY_TIME 2 + +/************************************************************************ + * + * P K 1 1 T o k e n . g e t L o g i n M o d e + * + */ +JNIEXPORT jint JNICALL +Java_com_netscape_jss_pkcs11_PK11Token_getLoginMode + (JNIEnv *env, jobject this) +{ + PK11SlotInfo *slot; + jint mode=ONE_TIME; + int askpw; + int timeout; + + PR_ASSERT(env!=NULL && this!=NULL); + + if( JSS_PK11_getTokenSlotPtr(env, this, &slot) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + goto finish; + } + PR_ASSERT(slot!=NULL); + + PK11_GetSlotPWValues(slot, &askpw, &timeout); + + if(askpw == -1) { + mode = EVERY_TIME; + } else if(askpw == 0) { + mode = ONE_TIME; + } else if(askpw == 1) { + mode = TIMEOUT; + } else { + JSS_throw(env, TOKEN_EXCEPTION); + goto finish; + } + +finish: + return mode; +} + +/************************************************************************ + * + * P K 1 1 T o k e n . g e t L o g i n T i m e o u t M i n u t e s + */ +JNIEXPORT jint JNICALL +Java_com_netscape_jss_pkcs11_PK11Token_getLoginTimeoutMinutes + (JNIEnv *env, jobject this) +{ + PK11SlotInfo *slot; + int askpw; + int timeout=0; + + PR_ASSERT(env!=NULL && this!=NULL); + + if( JSS_PK11_getTokenSlotPtr(env, this, &slot) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + goto finish; + } + PR_ASSERT(slot!=NULL); + + PK11_GetSlotPWValues(slot, &askpw, &timeout); + +finish: + return timeout; +} + + +/************************************************************************ + * + * P K 1 1 T o k e n . s e t L o g i n M o d e + * + */ +JNIEXPORT void JNICALL +Java_com_netscape_jss_pkcs11_PK11Token_setLoginMode + (JNIEnv *env, jobject this, jint mode) +{ + PK11SlotInfo *slot; + int askpw, timeout; + + PR_ASSERT(env!=NULL && this!=NULL); + + if( JSS_PK11_getTokenSlotPtr(env, this, &slot) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + goto finish; + } + PR_ASSERT(slot!=NULL); + + PK11_GetSlotPWValues(slot, &askpw, &timeout); + + if(mode == EVERY_TIME) { + askpw = -1; + } else if(mode == ONE_TIME) { + askpw = 0; + } else if(mode == TIMEOUT) { + askpw = 1; + } else { + JSS_throw(env, TOKEN_EXCEPTION); + goto finish; + } + + PK11_SetSlotPWValues(slot, askpw, timeout); + +finish: + ; +} + +/************************************************************************ + * + * P K 1 1 T o k e n . s e t L o g i n T i m e o u t M i n u t e s + * + */ +JNIEXPORT void JNICALL +Java_com_netscape_jss_pkcs11_PK11Token_setLoginTimeoutMinutes + (JNIEnv *env, jobject this, jint newTimeout) +{ + PK11SlotInfo *slot; + int askpw, timeout; + + PR_ASSERT(env!=NULL && this!=NULL); + + if( JSS_PK11_getTokenSlotPtr(env, this, &slot) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + return; + } + PR_ASSERT(slot!=NULL); + + PK11_GetSlotPWValues(slot, &askpw, &timeout); + PK11_SetSlotPWValues(slot, askpw, newTimeout); + +} + +/************************************************************************ + * + * P K 1 1 T o k e n . i s P r e s e n t + * + * Returns true if this token is present in the slot + */ +JNIEXPORT jboolean JNICALL Java_com_netscape_jss_pkcs11_PK11Token_isPresent + (JNIEnv *env, jobject this) +{ + PK11SlotInfo *slot; + jboolean retval; + + PR_ASSERT(env!=NULL && this!=NULL); + + if(JSS_PK11_getTokenSlotPtr(env, this, &slot) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + /* an exception was thrown */ + retval = JNI_FALSE; + goto finish; + } + PR_ASSERT(slot != NULL); + + if(PK11_IsPresent(slot) == PR_TRUE) { + retval = JNI_TRUE; + } else { + retval = JNI_FALSE; + } + +finish: + return retval; +} + +/************************************************************************ + * + * P K 1 1 T o k e n . P W I n i t a b l e + * + * Make sure this token can be initialized. Currently we only check the + * internal module, since it can't be initialized more than once. + * Presumably most tokens can have their PINs initialized arbitrarily + * many times. + */ +JNIEXPORT jboolean JNICALL Java_com_netscape_jss_pkcs11_PK11Token_PWInitable + (JNIEnv *env, jobject this) +{ + PK11SlotInfo *slot=NULL; + jboolean initable=JNI_FALSE; + + PR_ASSERT(env!=NULL && this!=NULL); + + /* + * Convert Java objects to native objects + */ + if(JSS_PK11_getTokenSlotPtr(env, this, &slot) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + /* an exception was thrown */ + goto finish; + } + PR_ASSERT(slot!=NULL); + + if(slot != PK11_GetInternalKeySlot()) { + /* We don't know about other tokens */ + initable = JNI_TRUE; + } else { + if(PK11_NeedUserInit(slot)) { + initable = JNI_TRUE; + } else { + /* Internal module only allows one init, after this you + * need to do a changePIN */ + initable = JNI_FALSE; + } + } + +finish: + return initable; +} + +/************************************************************************ + * + * P K 1 1 T o k e n . i n i t P a s s w o r d + * + */ +JNIEXPORT void JNICALL Java_com_netscape_jss_pkcs11_PK11Token_initPassword + (JNIEnv *env, jobject this, jbyteArray ssopw, jbyteArray userpw) +{ + PK11SlotInfo *slot=NULL; + char *szSsopw=NULL, *szUserpw=NULL; + jboolean ssoIsCopy, userIsCopy; + SECStatus initResult; + PRErrorCode error; + + PR_ASSERT(env!=NULL && this!=NULL && ssopw!=NULL && userpw!=NULL); + + /* + * Convert Java objects to native objects + */ + if(JSS_PK11_getTokenSlotPtr(env, this, &slot) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + /* an exception was thrown */ + goto finish; + } + szSsopw = (char*) (*env)->GetByteArrayElements(env, ssopw, &ssoIsCopy); + szUserpw = (char*) (*env)->GetByteArrayElements(env, userpw, &userIsCopy); + PR_ASSERT(slot!=NULL && szSsopw!=NULL && szUserpw!=NULL); + + /* + * If we're on the internal module, make sure we can still be + * initialized. + */ + if(slot == PK11_GetInternalKeySlot() && !PK11_NeedUserInit(slot)) { + JSS_nativeThrowMsg(env, ALREADY_INITIALIZED_EXCEPTION, + "Netscape Internal Key Token is already initialized"); + goto finish; + } + + /* + * Initialize the PIN + */ + initResult = PK11_InitPin(slot, szSsopw, szUserpw); + if(initResult != SECSuccess) { + error = PR_GetError(); + } + + /* + * Throw exception if an error occurred + */ + if(initResult != SECSuccess) { + if(error == SEC_ERROR_BAD_PASSWORD) { + JSS_nativeThrowMsg( + env, + INCORRECT_PASSWORD_EXCEPTION, + "Incorrect security officer PIN" + ); + } else { + JSS_nativeThrowMsg( + env, + TOKEN_EXCEPTION, + "Unable to initialize PIN" + ); + } + } + +finish: + /* + * Free native objects + */ + if(szSsopw) { + if(ssoIsCopy) { + JSS_wipeCharArray(szSsopw); + } + /* JNI_ABORT means don't copy back changes */ + (*env)->ReleaseByteArrayElements(env, ssopw, (jbyte*)szSsopw, + JNI_ABORT); + } + if(szUserpw) { + if(userIsCopy) { + JSS_wipeCharArray(szUserpw); + } + (*env)->ReleaseByteArrayElements(env, userpw, (jbyte*)szUserpw, + JNI_ABORT); + } + + return; +} + +/************************************************************************ + * + * P K 1 1 T o k e n . p a s s w o r d I s I n i t i a l i z e d + * + */ +JNIEXPORT jboolean JNICALL +Java_com_netscape_jss_pkcs11_PK11Token_passwordIsInitialized + (JNIEnv *env, jobject this) +{ + PK11SlotInfo *slot=NULL; + jboolean isInitialized = JNI_FALSE; + + PR_ASSERT(env!=NULL && this!=NULL); + + /* + * Convert Java arguments to C + */ + if( JSS_PK11_getTokenSlotPtr(env, this, &slot) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + goto finish; + } + PR_ASSERT(slot != NULL); + + if(slot == PK11_GetInternalKeySlot()) { + /* special case for our Key slot */ + isInitialized = ! PK11_NeedPWInit(); + } else { + isInitialized = ! PK11_NeedUserInit(slot); + } + +finish: + return isInitialized; +} + + +/************************************************************************ + * + * P K 1 1 T o k e n . c h a n g e P a s s w o r d + * + */ +JNIEXPORT void JNICALL Java_com_netscape_jss_pkcs11_PK11Token_changePassword + (JNIEnv *env, jobject this, jbyteArray oldPIN, jbyteArray newPIN) +{ + PK11SlotInfo *slot=NULL; + char *szOldPIN=NULL, *szNewPIN=NULL; + jboolean oldIsCopy, newIsCopy; + SECStatus changeResult; + PRErrorCode error; + + PR_ASSERT(env!=NULL && this!=NULL && oldPIN!=NULL && newPIN!=NULL); + + /* + * Convert Java objects to native objects + */ + if(JSS_PK11_getTokenSlotPtr(env, this, &slot) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + /* an exception was thrown */ + goto finish; + } + szOldPIN= (char*) (*env)->GetByteArrayElements(env, oldPIN, &oldIsCopy); + szNewPIN= (char*) (*env)->GetByteArrayElements(env, newPIN, &newIsCopy); + PR_ASSERT(slot!=NULL && szOldPIN!=NULL && szNewPIN!=NULL); + + /* + * Change the PIN + */ + changeResult = PK11_ChangePW(slot, szOldPIN, szNewPIN); + if(changeResult != SECSuccess) { + error = PR_GetError(); + } + + /* + * Throw exception if an error occurred + */ + if(changeResult != SECSuccess) { + if(error == SEC_ERROR_BAD_PASSWORD) { + JSS_nativeThrowMsg( + env, + INCORRECT_PASSWORD_EXCEPTION, + "Incorrect PIN" + ); + } else { + JSS_nativeThrowMsg( + env, + TOKEN_EXCEPTION, + "Unable to change PIN" + ); + } + } + +finish: + /* Free native objects */ + if(szOldPIN) { + if(oldIsCopy) { + JSS_wipeCharArray(szOldPIN); + } + /* JNI_ABORT means don't copy back changes */ + (*env)->ReleaseByteArrayElements(env, oldPIN, (jbyte*)szOldPIN, + JNI_ABORT); + } + if(szNewPIN) { + if(newIsCopy) { + JSS_wipeCharArray(szNewPIN); + } + (*env)->ReleaseByteArrayElements(env, newPIN, (jbyte*)szNewPIN, + JNI_ABORT); + } + + return; +} + +typedef enum { SSOPW, USERPW } pwType; + +/************************************************************************ + * + * p a s s w o r d I s C o r r e c t + * + * Checks the given password, which could be an SSO or a user password. + * Returns JNI_TRUE if the password is correct, JNI_FALSE if it isn't, + * and may throw an exception if something goes wrong on the token. + */ +static jboolean +passwordIsCorrect + (JNIEnv *env, jobject this, jbyteArray password, pwType type) +{ + PK11SlotInfo *slot = NULL; + char *pwBytes=NULL; + jboolean isCopy; + jboolean pwIsCorrect = JNI_FALSE; + SECStatus status; + int error; + + PR_ASSERT(env!=NULL && this!=NULL && password!=NULL); + + /* + * Convert Java args to C + */ + if( JSS_PK11_getTokenSlotPtr(env, this, &slot) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + goto finish; + } + pwBytes = (char*) (*env)->GetByteArrayElements(env, password, &isCopy); + PR_ASSERT(slot!=NULL && pwBytes != NULL); + + /* + * Do the check + */ + if(type == SSOPW) { + status = PK11_CheckSSOPassword(slot, pwBytes); + } else { + status = PK11_CheckUserPassword(slot, pwBytes); + } + if(status == SECSuccess) { + pwIsCorrect = JNI_TRUE; + } else { + error = PR_GetError(); + if(error == SEC_ERROR_BAD_PASSWORD) { + /* just wrong password */ + pwIsCorrect = JNI_FALSE; + } else { + /* some token problem */ + JSS_nativeThrowMsg(env, TOKEN_EXCEPTION, + "Unable to check password"); + goto finish; + } + } + +finish: + /* Free native objects */ + if(pwBytes != NULL) { + if(isCopy) { + JSS_wipeCharArray(pwBytes); + } + /* JNI_ABORT means don't copy back changes */ + (*env)->ReleaseByteArrayElements(env, password, (jbyte*)pwBytes, + JNI_ABORT); + } + + return pwIsCorrect; +} + +/************************************************************************ + * + * P K 1 1 T o k e n . u s e r P a s s w o r d I s C o r r e c t + * + */ +JNIEXPORT jboolean JNICALL +Java_com_netscape_jss_pkcs11_PK11Token_userPasswordIsCorrect + (JNIEnv *env, jobject this, jbyteArray password) +{ + return passwordIsCorrect(env, this, password, USERPW); +} + +/************************************************************************ + * + * P K 1 1 T o k e n . S S O P a s s w o r d I s C o r r e c t + * + */ +JNIEXPORT jboolean JNICALL +Java_com_netscape_jss_pkcs11_PK11Token_SSOPasswordIsCorrect + (JNIEnv *env, jobject this, jbyteArray password) +{ + return passwordIsCorrect(env, this, password, SSOPW); +} + +/************************************************************************ + * + * P K 1 1 T o k e n . g e t N a m e + * + * Returns the name of this token. + */ +JNIEXPORT jstring JNICALL Java_com_netscape_jss_pkcs11_PK11Token_getName + (JNIEnv *env, jobject this) +{ + char *szName; + PK11SlotInfo *slot; + jstring name; + jstring retval; + + PR_ASSERT(env!=NULL && this!=NULL); + + if(JSS_PK11_getTokenSlotPtr(env, this, &slot) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL ); + /* an exception was thrown */ + retval = NULL; + goto finish; + } + PR_ASSERT(slot != NULL); + + szName = PK11_GetTokenName(slot); + /* NULL C string converts to empty Java string */ + if(szName == NULL) { + szName = ""; + } + + name = (*env)->NewStringUTF(env, szName); + + /* name could be NULL, if an OutOfMemoryError occurred. In that case, + * we just return NULL and let the exception be thrown in Java */ +#ifdef DEBUG + if(name == NULL) { + /* Make sure there is an exception before we return NULL */ + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + } +#endif + + retval = name; + +finish: + return retval; +} + +/************************************************************************ + * + * P K 1 1 T o k e n . r e l e a s e N a t i v e R e s o u r c e s + * + * Free the PK11SlotInfo structure that underlies my token. + */ +JNIEXPORT void JNICALL +Java_com_netscape_jss_pkcs11_PK11Token_releaseNativeResources + (JNIEnv *env, jobject this) +{ + PK11SlotInfo *slot; + + PR_ASSERT(env!=NULL && this!=NULL); + + if(JSS_PK11_getTokenSlotPtr(env, this, &slot) != PR_SUCCESS) { + PR_ASSERT( PR_FALSE ); + goto finish; + } + PR_ASSERT(slot != NULL); + + /* this actually only frees the data structure if we were the last + * reference to it */ + PK11_FreeSlot(slot); + +finish: + return; +} + +/************************************************************************ + * + * J S S _ g e t T o k e n S l o t P t r + * + * Retrieve the PK11SlotInfo pointer of the given token. + * + * tokenObject: A reference to a Java PK11Token + * ptr: address of a PK11SlotInfo* that will be loaded with the PK11SlotInfo + * pointer of the given token. + * returns: PR_SUCCESS if the operation was successful, PR_FAILURE if an + * exception was thrown. + */ +PR_IMPLEMENT( PRStatus ) +JSS_PK11_getTokenSlotPtr(JNIEnv *env, jobject tokenObject, PK11SlotInfo **ptr) +{ + PR_ASSERT(env != NULL && tokenObject != NULL && ptr != NULL); + + /* + * Get the pointer from the PK11Token, which has a Token Proxy member + */ + PR_ASSERT(sizeof(PK11SlotInfo*) == sizeof(void*)); + return JSS_getPtrFromProxyOwner(env, tokenObject, PK11TOKEN_PROXY_FIELD, + PK11TOKEN_PROXY_SIG, (void**)ptr); +} + +/********************************************************************** + * + * PK11Token.doesAlgorithm + * + */ +JNIEXPORT jboolean JNICALL +Java_com_netscape_jss_pkcs11_PK11Token_doesAlgorithm + (JNIEnv *env, jobject this, jobject alg) +{ + PK11SlotInfo *slot; + CK_MECHANISM_TYPE mech; + jboolean doesMech = JNI_FALSE; + + if( JSS_PK11_getTokenSlotPtr(env, this, &slot) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + goto finish; + } + + mech = JSS_getPK11MechFromAlg(env, alg); + PR_ASSERT( mech != CKM_INVALID_MECHANISM ); + + if( PK11_DoesMechanism(slot, mech) == PR_TRUE) { + doesMech = JNI_TRUE; + } + + /* HACK...exceptions */ + if( PK11_IsInternal(slot) && mech == CKM_PBA_SHA1_WITH_SHA1_HMAC ) { + /* Although the internal slot doesn't actually do this mechanism, + * we do it by hand in PK11KeyGenerator.c */ + doesMech = JNI_TRUE; + } + +finish: + return doesMech; +} + +/*********************************************************************** + * + * PK11Token.isWritable + * + */ +JNIEXPORT jboolean JNICALL +Java_com_netscape_jss_pkcs11_PK11Token_isWritable + (JNIEnv *env, jobject this) +{ + PK11SlotInfo *slot; + + if( JSS_PK11_getTokenSlotPtr(env, this, &slot) != PR_SUCCESS) { + return JNI_FALSE; /* an exception was thrown, so it doesn't matter */ + } + + return ! PK11_IsReadOnly(slot); +} + +#define ZERO_SECITEM(item) {(item).len=0; (item).data=NULL;} +int PK11_NumberObjectsFor(PK11SlotInfo*, CK_ATTRIBUTE*, int); + +/************************************************************************ + * + * P K 1 1 T o k e n . getCertRequest + */ +JNIEXPORT jstring JNICALL Java_com_netscape_jss_pkcs11_PK11Token_generatePK10 + (JNIEnv *env, jobject this, jstring subject, jint keysize, + jstring keyType, jbyteArray P, jbyteArray Q, jbyteArray G) +{ + PK11SlotInfo *slot; + const char* c_subject; + jboolean isCopy; + unsigned char *b64request; + SECItem p, q, g; + PQGParams *dsaParams=NULL; + jobject keyPair=NULL; + const char* c_keyType; + jboolean k_isCopy; + unsigned int ktype = 0; + + PR_ASSERT(env!=NULL && this!=NULL); + /* get keytype */ + c_keyType = (*env)->GetStringUTFChars(env, keyType, &k_isCopy); + + if (0 == PL_strcasecmp(c_keyType, KEYTYPE_DSA_STRING)) { + ktype = KEYTYPE_DSA; + } else if (0 == PL_strcasecmp(c_keyType, KEYTYPE_RSA_STRING)) { + ktype = KEYTYPE_RSA; + } else { + JSS_throw(env, INVALID_PARAMETER_EXCEPTION); + } + + if (ktype == KEYTYPE_DSA) { + if (P==NULL || Q==NULL || G ==NULL) { + /* shouldn't happen */ + JSS_throw(env, INVALID_PARAMETER_EXCEPTION); + } else { + /* caller supplies PQG */ + /* zero these so we can free them indiscriminately later */ + ZERO_SECITEM(p); + ZERO_SECITEM(q); + ZERO_SECITEM(g); + + if( JSS_ByteArrayToOctetString(env, P, &p) || + JSS_ByteArrayToOctetString(env, Q, &q) || + JSS_ByteArrayToOctetString(env, G, &g) ) + { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + goto finish; + } + dsaParams = PQG_NewParams(&p, &q, &g); + if(dsaParams == NULL) { + JSS_throw(env, OUT_OF_MEMORY_ERROR); + goto finish; + } + + } + } /* end ktype == KEYTYPE_DSA */ + + if( JSS_PK11_getTokenSlotPtr(env, this, &slot) != PR_SUCCESS) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + /* an exception occurred */ + goto finish; + } + + PR_ASSERT(slot != NULL); + if(PK11_IsLoggedIn(slot, NULL) != PR_TRUE) { + JSS_nativeThrowMsg(env, TOKEN_EXCEPTION, + "token not logged in"); + } + + /* get subject */ + c_subject = (*env)->GetStringUTFChars(env, subject, &isCopy); + + /* get keysize */ + + /* call GenerateCertRequest() */ + GenerateCertRequest(env, ktype, c_subject, (int) keysize, slot, &b64request, + dsaParams); + +finish: + if (isCopy == JNI_TRUE) { + /* release memory */ + (*env)->ReleaseStringUTFChars(env, subject, c_subject); + } + + if (k_isCopy == JNI_TRUE) { + /* release memory */ + (*env)->ReleaseStringUTFChars(env, keyType, c_keyType); + } + + if (ktype == KEYTYPE_DSA) { + SECITEM_FreeItem(&p, PR_FALSE); + SECITEM_FreeItem(&q, PR_FALSE); + SECITEM_FreeItem(&g, PR_FALSE); + PQG_DestroyParams(dsaParams); + } + + if (b64request == NULL) { + return NULL; + } else { + /* convert to String */ + return (*env)->NewStringUTF(env, (const char *)b64request); + } +} + +/* + * generate keypairs and further the request + * the real thing will need keytype and pqg numbers (for DSA) + */ +void +GenerateCertRequest(JNIEnv *env, + unsigned int ktype, const char *subject, int keysize, + PK11SlotInfo *slot, + unsigned char **b64request, + PQGParams *dsaParams) { + + CERTCertificateRequest *req; + + SECKEYPrivateKey *privk = NULL; + SECKEYPublicKey *pubk = NULL; + int i = 0; + SECStatus rv; + PRArenaPool *arena; + SECItem result_der, result; + SECItem *blob; + +#ifdef DEBUG + printf("in GenerateCertRequest(), subject=%s, keysize = %d", + subject, keysize); +#endif + + if( GenerateKeyPair(env, ktype, slot, &pubk, &privk, keysize, + dsaParams) != SECSuccess) { +#ifdef DEBUG + printf("Error generating keypair."); +#endif + } +#ifdef DEBUG + printf("before make_cert_request"); +#endif + + req = make_cert_request (env, subject, pubk); + +#ifdef DEBUG + printf("after make_cert_request"); +#endif + if (req == NULL) { + return; + } + + result_der.len = 0; + result_der.data = NULL; +#ifdef DEBUG + printf("before SEC_ASN1EncodeItem"); +#endif + + /* der encode the request */ + blob = SEC_ASN1EncodeItem(req->arena, &result_der, req, + CERT_CertificateRequestTemplate); + + /* sign the request */ + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( !arena ) { + JSS_throw(env, OUT_OF_MEMORY_ERROR); + return; + } + + rv = SEC_DerSignData(arena, &result, result_der.data, result_der.len, + privk, + (ktype==KEYTYPE_RSA)? SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST); + if (rv) { + JSS_nativeThrowMsg(env, TOKEN_EXCEPTION, + "signing of data failed"); + return; + } + + *b64request = (unsigned char*) BTOA_DataToAscii(result.data, result.len); +#ifdef DEBUG + printf("data = %s\n", *b64request); +#endif +} + +/****************************************************************** + * + * m a k e _ c e r t _ r e q u e s t + */ +static CERTCertificateRequest* +make_cert_request(JNIEnv *env, const char *subject, SECKEYPublicKey *pubk) +{ + CERTName *subj; + CERTSubjectPublicKeyInfo *spki; + + CERTCertificateRequest *req; + + /* Create info about public key */ + spki = SECKEY_CreateSubjectPublicKeyInfo(pubk); + if (!spki) { + JSS_nativeThrowMsg(env, TOKEN_EXCEPTION, + "unable to create subject public key"); + return NULL; + } + + subj = CERT_AsciiToName ((char *)subject); + if(subj == NULL) { + JSS_nativeThrowMsg(env, TOKEN_EXCEPTION, + "Invalid data in certificate description"); + } + + /* Generate certificate request */ + req = CERT_CreateCertificateRequest(subj, spki, 0); + if (!req) { + JSS_nativeThrowMsg(env, TOKEN_EXCEPTION, + "unable to make certificate request"); + return NULL; + } + +#ifdef DEBUG + printf("certificate request generated\n"); +#endif + + return req; +} + + +/****************************************************************** + * + * G e n e r a t e K e y P a i r + */ +static SECStatus +GenerateKeyPair(JNIEnv *env, unsigned int ktype, PK11SlotInfo *slot, SECKEYPublicKey **pubk, + SECKEYPrivateKey **privk, int keysize, PQGParams *dsaParams) +{ + + PK11RSAGenParams rsaParams; + + if (ktype == KEYTYPE_RSA) { + if( keysize == -1 ) { + rsaParams.keySizeInBits = DEFAULT_RSA_KEY_SIZE; + } else { + rsaParams.keySizeInBits = keysize; + } + rsaParams.pe = DEFAULT_RSA_PUBLIC_EXPONENT; + } + if(PK11_Authenticate( slot, PR_FALSE /*loadCerts*/, NULL /*wincx*/) + != SECSuccess) { + JSS_nativeThrowMsg(env, TOKEN_EXCEPTION, + "failure authenticating to key database"); + return SECFailure; + } + + if(PK11_NeedUserInit(slot)) { + JSS_nativeThrowMsg(env, TOKEN_EXCEPTION, + "token not initialized with password"); + return SECFailure; + } + + /************************************************** + * HACK to workaround bug #323494 + * On internal token, must call C_FindObjectsInit before creating + * any token objects. + *************************************************/ + if( slot==PK11_GetInternalSlot() || slot==PK11_GetInternalKeySlot() ) { + CK_ATTRIBUTE attr; + CK_OBJECT_CLASS class = CKO_PRIVATE_KEY; + + attr.type = CKA_CLASS; + attr.pValue = &class; + attr.ulValueLen = sizeof(class); + + PK11_NumberObjectsFor(slot, &attr, 1); + } + +#ifdef DEBUG + printf("key type == %d", ktype); +#endif + if (ktype == KEYTYPE_RSA) { + *privk = PK11_GenerateKeyPair (slot, + CKM_RSA_PKCS_KEY_PAIR_GEN, &rsaParams, + pubk, PR_TRUE /*isPerm*/, PR_TRUE /*isSensitive*/, NULL); + } else { /* dsa */ + *privk = PK11_GenerateKeyPair (slot, + CKM_DSA_KEY_PAIR_GEN, (void *)dsaParams, + pubk, PR_TRUE /*isPerm*/, PR_TRUE /*isSensitive*/, NULL); + } + if( *privk == NULL ) { + int errLength; + char *errBuf; + char *msgBuf; + + errLength = PR_GetErrorTextLength(); + if(errLength > 0) { + errBuf = PR_Malloc(errLength); + if(errBuf == NULL) { + JSS_throw(env, OUT_OF_MEMORY_ERROR); + return SECFailure; + } + PR_GetErrorText(errBuf); + } + msgBuf = PR_smprintf("Keypair Generation failed on token: %s", + errLength>0? errBuf : ""); + if(errLength>0) { + PR_Free(errBuf); + } + + JSS_throwMsg(env, TOKEN_EXCEPTION, msgBuf); + PR_Free(msgBuf); + return SECFailure; + } + + + if (*privk != NULL && *pubk != NULL) { +#ifdef DEBUG + printf("generated public/private key pair\n"); +#endif + } else { + JSS_nativeThrowMsg(env, TOKEN_EXCEPTION, + "failure generating key pair"); + return SECFailure; + } + + return SECSuccess; +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Token.java b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Token.java new file mode 100644 index 00000000000..9ab2c44b913 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Token.java @@ -0,0 +1,587 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs11; + +import java.util.*; +import com.netscape.jss.util.*; +import com.netscape.jss.crypto.*; +import java.security.NoSuchAlgorithmException; +import java.security.InvalidKeyException; +import java.security.InvalidParameterException; + +/** + * A PKCS #11 token. Currently, these can only be obtained from the + * CryptoManager class. + * + * @author nicolson + * @version $Revision: 1.1 $ $Date: 2000-12-15 20:50:21 $ + * @see com.netscape.jss.CryptoManager + */ +public final class PK11Token implements CryptoToken { + + //////////////////////////////////////////////////// + // exceptions + //////////////////////////////////////////////////// + /** + * Thrown if the operation requires that the token be logged in, and it + * isn't. + */ + static public class NotInitializedException + extends IncorrectPasswordException + { + public NotInitializedException() {} + public NotInitializedException(String mesg) {super(mesg);} + } + + //////////////////////////////////////////////////// + // public routines + //////////////////////////////////////////////////// + public com.netscape.jss.crypto.Signature + getSignatureContext(SignatureAlgorithm algorithm) + throws java.security.NoSuchAlgorithmException, TokenException + { + Assert.assert(algorithm!=null); + return Tunnel.constructSignature( algorithm, + new PK11Signature(this, algorithm) ); + } + + public JSSMessageDigest + getDigestContext(DigestAlgorithm algorithm) + throws java.security.NoSuchAlgorithmException, + java.security.DigestException + { + if( ! doesAlgorithm(algorithm) ) { + throw new java.security.NoSuchAlgorithmException(); + } + + return new PK11MessageDigest(this, algorithm); + } + + public Cipher + getCipherContext(EncryptionAlgorithm algorithm) + throws java.security.NoSuchAlgorithmException, TokenException + { + if( ! doesAlgorithm(algorithm) ) { + throw new java.security.NoSuchAlgorithmException( + algorithm+" is not supported by this token"); + } + return new PK11Cipher(this, algorithm); + } + + public KeyGenerator + getKeyGenerator(KeyGenAlgorithm algorithm) + throws java.security.NoSuchAlgorithmException, TokenException + { + if( ! doesAlgorithm(algorithm) ) { + throw new java.security.NoSuchAlgorithmException( + algorithm+" is not supported by this token"); + } + return new PK11KeyGenerator(this, algorithm); + } + + /** + * Allows a SymmetricKey to be cloned on a different token. + * + * @exception SymmetricKey.NotExtractableException If the key material + * cannot be extracted from the current token. + * @exception InvalidKeyException If the owning token cannot process + * the key to be cloned. + */ + public SymmetricKey cloneKey(SymmetricKey key) + throws SymmetricKey.NotExtractableException, + InvalidKeyException, TokenException + { + return PK11KeyGenerator.clone(key, this); + } + + public KeyWrapper + getKeyWrapper(KeyWrapAlgorithm algorithm) + throws java.security.NoSuchAlgorithmException, TokenException + { + if( ! doesAlgorithm(algorithm) ) { + throw new java.security.NoSuchAlgorithmException( + algorithm+" is not supported by this token"); + } + return new PK11KeyWrapper(this, algorithm); + } + + public java.security.SecureRandom + getRandomGenerator() + throws NotImplementedException, TokenException + { + throw new NotImplementedException(); + } + + public com.netscape.jss.crypto.KeyPairGenerator + getKeyPairGenerator(KeyPairAlgorithm algorithm) + throws java.security.NoSuchAlgorithmException, TokenException + { + Assert.assert(algorithm!=null); + return new KeyPairGenerator(algorithm, + new PK11KeyPairGenerator(this, algorithm)); + } + + public native boolean isLoggedIn() throws TokenException; + + /** + * Log into the token. If you are already logged in, this method has + * no effect, even if the PIN is wrong. + * + * @param callback A callback to use to obtain the password, or a + * Password object. + * @exception NotInitializedException The token has not yet been + * initialized. + * @exception IncorrectPasswordException The specified password + * was incorrect. + */ + public void login(PasswordCallback callback) + throws NotInitializedException, IncorrectPasswordException, + TokenException + { + if(callback == null) { + callback = new NullPasswordCallback(); + } + nativeLogin(callback); + } + + protected native void nativeLogin(PasswordCallback callback) + throws NotInitializedException, IncorrectPasswordException, + TokenException; + + /** + * @return true if the token is writable, false if it is read-only. + * Writable tokens can have their keys generated on the internal token + * and then moved out. + */ + public native boolean isWritable(); + + /** + * Determines if the given token is present on the system. + * This would return false, for example, for a smart card reader + * that didn't have a card inserted. + */ + public native boolean isPresent(); + + /** + * Log out of the token. + * + * @exception TokenException If you are already logged in, or an + * unspecified error occurs. + */ + public native void logout() throws TokenException; + + public native int getLoginMode() throws TokenException; + + public native void setLoginMode(int mode) throws TokenException; + + public native int getLoginTimeoutMinutes() throws TokenException; + + public native void setLoginTimeoutMinutes(int timeoutMinutes) + throws TokenException; + + /** + * Determines whether this is a removable token. For example, a smart card + * is removable, while the Netscape internal module and a hardware + * accelerator card are not removable. + * @return true if the token is removable, false otherwise. + */ + //public native boolean isRemovable(); + + /** + * Initialize PIN. This sets the user's new PIN, using the current + * security officer PIN for authentication. + * + * @param ssopw The security officer's current password. + * @param userpw The user's new password. + * @exception IncorrectPinException If the security officer PIN is + * incorrect. + * @exception TokenException If the PIN was already initialized, + * or there was an unspecified error in the token. + */ + public void initPassword(PasswordCallback ssopwcb, + PasswordCallback userpwcb) + throws IncorrectPasswordException, AlreadyInitializedException, + TokenException + { + byte[] ssopwArray = null; + byte[] userpwArray = null; + Password ssopw=null; + Password userpw=null; + PasswordCallbackInfo pwcb = makePWCBInfo(); + + if(ssopwcb==null) { + ssopwcb = new NullPasswordCallback(); + } + if(userpwcb==null) { + userpwcb = new NullPasswordCallback(); + } + + try { + + // Make sure the password hasn't already been set, doing special + // checks for the internal module + if(!PWInitable()) { + throw new AlreadyInitializedException(); + } + + // Verify the SSO Password, except on internal module + if( isInternalKeyStorageToken() ) { + ssopwArray = new byte[] {0}; + } else { + ssopw = ssopwcb.getPasswordFirstAttempt(pwcb); + ssopwArray = Tunnel.getPasswordByteCopy(ssopw); + while( ! SSOPasswordIsCorrect(ssopwArray) ) { + Password.wipeBytes(ssopwArray); + ssopw.clear(); + ssopw = ssopwcb.getPasswordAgain(pwcb); + ssopwArray = Tunnel.getPasswordByteCopy(ssopw); + } + } + + // Now change the PIN + userpw = userpwcb.getPasswordFirstAttempt(pwcb); + userpwArray = Tunnel.getPasswordByteCopy(userpw); + initPassword(ssopwArray, userpwArray); + + } catch (PasswordCallback.GiveUpException e) { + throw new IncorrectPasswordException(e.toString()); + } finally { + // zero-out the arrays + if(ssopwArray != null) { + Password.wipeBytes(ssopwArray); + } + if(ssopw != null) { + ssopw.clear(); + } + if(userpwArray != null) { + Password.wipeBytes(userpwArray); + } + if(userpw != null) { + userpw.clear(); + } + } + } + + /** + * Make sure the PIN can be initialized. This is mainly to check the + * internal module. + */ + protected native boolean PWInitable() throws TokenException; + + protected native boolean SSOPasswordIsCorrect(byte[] ssopw) + throws TokenException, AlreadyInitializedException; + + protected native void initPassword(byte[] ssopw, byte[] userpw) + throws IncorrectPasswordException, AlreadyInitializedException, + TokenException; + + /** + * Determine whether the token has been initialized yet. + */ + public native boolean + passwordIsInitialized() throws TokenException; + + /** + * Change password. This changes the user's PIN after it has already + * been initialized. + * + * @param oldPIN The user's old PIN. + * @param newPIN The new PIN. + * @exception IncorrectPasswordException If the old PIN is incorrect. + * @exception TokenException If some other error occurs on the token. + * + */ + public void changePassword(PasswordCallback oldPINcb, + PasswordCallback newPINcb) + throws IncorrectPasswordException, TokenException + { + byte[] oldPW = null; + byte[] newPW = null; + Password oldPIN=null; + Password newPIN=null; + PasswordCallbackInfo pwcb = makePWCBInfo(); + + if(oldPINcb==null) { + oldPINcb = new NullPasswordCallback(); + } + if(newPINcb==null) { + newPINcb = new NullPasswordCallback(); + } + + try { + + // Verify the old password + oldPIN = oldPINcb.getPasswordFirstAttempt(pwcb); + oldPW = Tunnel.getPasswordByteCopy(oldPIN); + if( ! userPasswordIsCorrect(oldPW) ) { + do { + Password.wipeBytes(oldPW); + oldPIN.clear(); + oldPIN = oldPINcb.getPasswordAgain(pwcb); + oldPW = Tunnel.getPasswordByteCopy(oldPIN); + } while( ! userPasswordIsCorrect(oldPW) ); + } + + // Now change the PIN + newPIN = newPINcb.getPasswordFirstAttempt(pwcb); + newPW = Tunnel.getPasswordByteCopy(newPIN); + changePassword(oldPW, newPW); + + } catch (PasswordCallback.GiveUpException e) { + throw new IncorrectPasswordException(e.toString()); + } finally { + if(oldPW != null) { + Password.wipeBytes(oldPW); + } + if(oldPIN != null) { + oldPIN.clear(); + } + if(newPW != null) { + Password.wipeBytes(newPW); + } + if(newPIN != null) { + newPIN.clear(); + } + } + } + + protected PasswordCallbackInfo makePWCBInfo() { + return new TokenCallbackInfo(getName()); + } + + /** + * Check the given password, return true if it's right, false if it's + * wrong. + */ + protected native boolean userPasswordIsCorrect(byte[] pw) + throws TokenException; + + /** + * Change the password on the token from the old one to the new one. + */ + protected native void changePassword(byte[] oldPIN, byte[] newPIN) + throws IncorrectPasswordException, TokenException; + + public native String getName(); + + public java.security.Provider + getProvider() { + Assert.notYetImplemented("Providers not implemented by PK11Token yet"); + return null; + } + + public CryptoStore + getCryptoStore() { + return cryptoStore; + } + + /** + * Determines whether this token is capable of performing the given + * PKCS #11 mechanism. + */ +/* + public boolean doesMechanism(Mechanism mech) { + return doesMechanismNative(mech.getValue()); + } +*/ + + /** + * Deep-comparison operator. + * + * @return true if these tokens point to the same underlying native token. + * false otherwise, or if compare is null. + */ + public boolean equals(Object obj) { + if(obj==null) { + return false; + } else { + if( ! (obj instanceof PK11Token) ) { + return false; + } + return tokenProxy.equals(((PK11Token)obj).tokenProxy); + } + } + + //protected native boolean doesMechanismNative(int mech); + + /** + * Determines whether this token is capable of performing the given + * algorithm. + */ + public native boolean doesAlgorithm(Algorithm alg); + + /** + * Generates a PKCS#10 certificate request including Begin/End brackets + * @param subject subject dn of the certificate + * @param keysize size of the key + * @param keyType "rsa" or "dsa" + * @param P The DSA prime parameter + * @param Q The DSA sub-prime parameter + * @param G The DSA base parameter + * @ return String that represents a PKCS#10 b64 encoded blob with + * begin/end brackets + */ + public String generateCertRequest(String subject, int keysize, + String keyType, + byte[] P, byte[] Q, + byte[] G) + throws TokenException, InvalidParameterException, PQGParamGenException + { + + if (keyType.equalsIgnoreCase("dsa")) { + if ((P == null) && (Q == null) && (G == null)) { + System.out.println("no pqg supplied, self-generating..."); + PQGParams pqg; + try { + pqg = PQGParams.generate(keysize); + } catch (PQGParamGenException e) { + System.out.println(e.toString()); + throw e; + } + byte[] p = PQGParams.BigIntegerToUnsignedByteArray(pqg.getP()); + byte[] q = PQGParams.BigIntegerToUnsignedByteArray(pqg.getQ()); + byte[] g = PQGParams.BigIntegerToUnsignedByteArray(pqg.getG()); + P = p; + Q = q; + G = g; + String pk10String; + try { + pk10String = + generatePK10(subject, keysize, keyType, p, + q, g); + } catch (TokenException e) { + throw e; + } catch (InvalidParameterException e) { + throw e; + } + + return ("-----BEGIN NEW CERTIFICATE REQUEST-----\n"+ + pk10String + + "\n-----END NEW CERTIFICATE REQUEST-----"); + } else if ((P == null) || (Q == null) || (G == null)) { + throw new InvalidParameterException("need all P, Q, and G"); + } + + } + String pk10String; + try { + pk10String = + generatePK10(subject, keysize, keyType, P, + Q, G); + } catch (TokenException e) { + throw e; + } catch (InvalidParameterException e) { + throw e; + } + + return ("-----BEGIN NEW CERTIFICATE REQUEST-----\n"+ + pk10String + + "\n-----END NEW CERTIFICATE REQUEST-----"); + } + + protected native String generatePK10(String subject, int keysize, + String keyType, + byte[] P, byte[] Q, + byte[] G) + throws TokenException, InvalidParameterException; + + //////////////////////////////////////////////////// + // construction and finalization + //////////////////////////////////////////////////// + + /* + * Default constructor should never be called. + */ + protected PK11Token() { + Assert.assert(false); + } + + /** + * Creates a new PK11Token. Should only be called from PK11Token's + * native code. + * @param pointer A byte array containing a pointer to a PKCS #11 slot. + */ + protected PK11Token(byte[] pointer, boolean internal, boolean keyStorage) { + Assert.assert(pointer!=null); + tokenProxy = new TokenProxy(pointer); + mIsInternalCryptoToken = internal; + mIsInternalKeyStorageToken = keyStorage; + cryptoStore = new PK11Store(tokenProxy); + } + +/* + protected PK11Token(TokenProxy proxy) { + Assert.assert(proxy!=null); + this.tokenProxy = proxy; + } +*/ + + TokenProxy getProxy() { + return tokenProxy; + } + + + /** + * @return true if this is the internal token used for bulk crypto. + */ + public boolean isInternalCryptoToken() { + return mIsInternalCryptoToken; + } + protected boolean mIsInternalCryptoToken; + + /** + * @return true if this is the internal key storage token. + */ + public boolean isInternalKeyStorageToken() { + return mIsInternalKeyStorageToken; + } + protected boolean mIsInternalKeyStorageToken; + + ////////////////////////////////////////////////// + // Private Data + ////////////////////////////////////////////////// + protected TokenProxy tokenProxy; + + protected PK11Store cryptoStore; +} + +/** + * This class just hardwires the type to be TOKEN so we don't have to mess + * with Java constants in native code. + */ +class TokenCallbackInfo extends PasswordCallbackInfo { + public TokenCallbackInfo(String name) { + super(name, TOKEN); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11TokenCert.java b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11TokenCert.java new file mode 100644 index 00000000000..4451bdd488e --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11TokenCert.java @@ -0,0 +1,54 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs11; + +import com.netscape.jss.crypto.*; + +/** + * A user certificate that lives on a PKCS #11 token. + */ +public final class PK11TokenCert extends PK11Cert implements TokenCertificate +{ + public byte[] getUniqueID() { + return super.getUniqueID(); + } + + public CryptoToken getOwningToken() { + return super.getOwningToken(); + } + + PK11TokenCert(byte[] pointer) { + super(pointer); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/TokenProxy.java b/mozilla/security/jss/org/mozilla/jss/pkcs11/TokenProxy.java new file mode 100644 index 00000000000..ca8d3ff7521 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/TokenProxy.java @@ -0,0 +1,48 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs11; + +import com.netscape.jss.util.NativeProxy; +import com.netscape.jss.util.Debug; + +final class TokenProxy extends NativeProxy { + public TokenProxy(byte[] pointer) { + super(pointer); + } + protected native void releaseNativeResources(); + protected void finalize() throws Throwable { + Debug.trace(Debug.OBNOXIOUS, "Finalizing a TokenProxy"); + super.finalize(); + } + } diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/Tunnel.java b/mozilla/security/jss/org/mozilla/jss/pkcs11/Tunnel.java new file mode 100644 index 00000000000..9a5f56db654 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/Tunnel.java @@ -0,0 +1,68 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs11; + +import com.netscape.jss.crypto.SignatureAlgorithm; +import com.netscape.jss.crypto.SignatureSpi; +import com.netscape.jss.crypto.Signature; +import com.netscape.jss.util.Password; + +final class Tunnel { + + private static class CryptoTunnel extends com.netscape.jss.crypto.Tunnel + { + public static Signature + constructSignature(SignatureAlgorithm alg, SignatureSpi engine) { + return ConstructSignature(alg, engine); + } + } + + private static class UtilTunnel extends com.netscape.jss.util.Tunnel + { + public static byte[] + getPasswordByteCopy(Password pw) { + return GetPasswordByteCopy(pw); + } + } + + static Signature + constructSignature(SignatureAlgorithm alg, SignatureSpi engine) { + return CryptoTunnel.constructSignature(alg, engine); + } + + static byte[] + getPasswordByteCopy(Password pw) { + return UtilTunnel.getPasswordByteCopy(pw); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/config.mk b/mozilla/security/jss/org/mozilla/jss/pkcs11/config.mk new file mode 100644 index 00000000000..7f5a19fa3d3 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/config.mk @@ -0,0 +1,69 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +####################################################################### +# Set the LD_LIBS value to encompass all static JSS, security, and # +# dbm libraries # +####################################################################### + +LD_LIBS += $(LIBJSSCRYPTO) \ + $(LIBJSSUTIL) \ + $(LIBJSSPOLICY) \ + $(LIBJSSHCLHACKS) \ + $(LIBSECMOD) \ + $(LIBCERT) \ + $(LIBKEY) \ + $(LIBCRYPTO) \ + $(LIBHASH) \ + $(LIBSECUTIL) \ + $(LIBDBM) \ + $(NULL) + +####################################################################### +# Append additional LD_LIBS value to encompass all dynamic NSPR 2.0, # +# java, and system libraries # +####################################################################### + +ifeq ($(OS_ARCH), WINNT) + LD_LIBS += $(DLLPLDS) $(DLLPLC) $(DLLPR) $(DLLSYSTEM) +else + LD_LIBS += -L$(SOURCE_LIB_DIR) -lplds3 -lplc3 -lnspr3 $(DLLSYSTEM) +endif + + +####################################################################### +# Turn off any Export Control Policy for these libraries # +####################################################################### + +POLICY = + diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/manifest.mn b/mozilla/security/jss/org/mozilla/jss/pkcs11/manifest.mn new file mode 100644 index 00000000000..a268334b87d --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/manifest.mn @@ -0,0 +1,170 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +CORE_DEPTH = ../../../../.. + +MODULE = ninja + +NS_USE_JDK = 1 + +REQUIRES = nspr20 dbm security + +PACKAGE = com/netscape/jss/pkcs11 + +# These are meant to be used within Ninja only. +PRIVATE_EXPORTS = pk11util.h \ + secmodi.h \ + secmodti.h \ + rsa.h \ + $(NULL) + +JNI_GEN = \ + com.netscape.jss.pkcs11.CertProxy \ + com.netscape.jss.pkcs11.CipherContextProxy \ + com.netscape.jss.pkcs11.PK11Module \ + com.netscape.jss.pkcs11.ModuleProxy \ + com.netscape.jss.pkcs11.PK11Cert \ + com.netscape.jss.pkcs11.PK11Cipher \ + com.netscape.jss.pkcs11.PK11KeyWrapper \ + com.netscape.jss.pkcs11.PK11MessageDigest \ + com.netscape.jss.pkcs11.PK11PrivKey \ + com.netscape.jss.pkcs11.PK11PubKey \ + com.netscape.jss.pkcs11.PK11SymKey \ + com.netscape.jss.pkcs11.PK11KeyPairGenerator \ + com.netscape.jss.pkcs11.PK11KeyGenerator \ + com.netscape.jss.pkcs11.PrivateKeyProxy \ + com.netscape.jss.pkcs11.PublicKeyProxy \ + com.netscape.jss.pkcs11.SymKeyProxy \ + com.netscape.jss.pkcs11.KeyProxy \ + com.netscape.jss.pkcs11.PK11Token \ + com.netscape.jss.pkcs11.TokenProxy \ + com.netscape.jss.pkcs11.PK11Signature \ + com.netscape.jss.pkcs11.PK11Store \ + com.netscape.jss.pkcs11.PK11KeyPairGenerator \ + com.netscape.jss.pkcs11.SigContextProxy \ + com.netscape.jss.pkcs11.PK11RSAPublicKey \ + com.netscape.jss.pkcs11.PK11DSAPublicKey \ + com.netscape.jss.pkcs11.PK11SecureRandom \ + $(NULL) + +CLASSES = \ + CertProxy \ + CipherContextProxy \ + KeyProxy \ + KeyType \ + ModuleProxy \ + PK11Cert \ + PK11Cipher \ + PK11InternalCert \ + PK11TokenCert \ + PK11InternalTokenCert \ + PK11DSAPublicKey \ + PK11Key \ + PK11KeyGenerator \ + PK11KeyPairGenerator \ + PK11KeyWrapper \ + PK11MessageDigest \ + PK11Module \ + PK11PrivKey \ + PK11PubKey \ + PK11RSAPublicKey \ + PK11Signature \ + PK11SymKey \ + PK11Store \ + PK11Token \ + PK11SecureRandom \ + PrivateKeyProxy \ + PublicKeyProxy \ + SigContextProxy \ + SymKeyProxy \ + TokenCallbackInfo \ + TokenProxy \ + Tunnel \ + $(NULL) + +PRIVATE_CLASSES = \ + pwcb \ + $(NULL) + + +JSRCS = \ + CipherContextProxy.java \ + KeyProxy.java \ + KeyType.java \ + ModuleProxy.java \ + PK11Cert.java \ + PK11Cipher.java \ + PK11DSAPublicKey.java \ + PK11InternalCert.java \ + PK11InternalTokenCert.java \ + PK11Key.java \ + PK11KeyGenerator.java \ + PK11KeyPairGenerator.java \ + PK11KeyWrapper.java \ + PK11MessageDigest.java \ + PK11Module.java \ + PK11PrivKey.java \ + PK11PubKey.java \ + PK11RSAPublicKey.java \ + PK11SecureRandom.java \ + PK11Signature.java \ + PK11Store.java \ + PK11SymKey.java \ + PK11Token.java \ + PK11TokenCert.java \ + TokenProxy.java \ + Tunnel.java \ + $(NULL) + +PRIVATE_JSRCS = + + +CSRCS = \ + PK11Cert.c \ + PK11Cipher.c \ + PK11KeyGenerator.c \ + PK11KeyPairGenerator.c \ + PK11KeyWrapper.c \ + PK11MessageDigest.c \ + PK11Module.c \ + PK11PrivKey.c \ + PK11PubKey.c \ + PK11Signature.c \ + PK11SecureRandom.c \ + PK11Store.c \ + PK11SymKey.c \ + PK11Token.c \ + $(NULL) + + +LIBRARY_NAME = jsspkcs11 diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/pk11util.h b/mozilla/security/jss/org/mozilla/jss/pkcs11/pk11util.h new file mode 100644 index 00000000000..c4a3c92d7bd --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/pk11util.h @@ -0,0 +1,414 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +/* need to include these first: + * + * certt.h + * nspr.h + * jni.h + * secmodt.h + */ + +#ifndef JSS_PK11_UTIL_H +#define JSS_PK11_UTIL_H + +PR_BEGIN_EXTERN_C + + +/*===================================================================== + K E Y S +=====================================================================*/ + +/*********************************************************************** + * + * J S S _ P K 1 1 _ w r a p P r i v K e y + * privk: will be eaten by the wrapper and set to NULL. + * Returns: a new PK11PrivKey, or NULL if an exception occurred. + */ +PR_EXTERN( jobject ) +JSS_PK11_wrapPrivKey(JNIEnv *env, SECKEYPrivateKey **privk); + +/*********************************************************************** + * + * J S S _ P K 1 1 _ w r a p P u b K e y + * privk: will be eaten by the wrapper and set to NULL. + * Returns: a new PK11PubKey, or NULL if an exception occurred. + */ +PR_EXTERN( jobject ) +JSS_PK11_wrapPubKey(JNIEnv *env, SECKEYPublicKey **pubk); + + +/************************************************************************** + * Given a PrivateKey object, extracts the SECKEYPrivateKey* and stores it + * at the given address. + * + * privkObject: A JNI reference to a PrivateKey object. + * ptr: Address of a SECKEYPrivateKey* that will receive the pointer. + * Returns: PR_SUCCESS for success, PR_FAILURE if an exception was thrown. + */ +PR_EXTERN( PRStatus ) +JSS_PK11_getPrivKeyPtr(JNIEnv *env, jobject privkObject, + SECKEYPrivateKey** ptr); + +/*********************************************************************** + * Given a PublicKey object, extracts the SECKEYPublicKey* and stores it + * at the given address. + * + * pubkObject: A JNI reference to a PublicKey object. + * ptr: Address of a SECKEYPublicKey* that will receive the pointer. + * Returns: PR_SUCCESS for success, PR_FAILURE if an exception was thrown. + */ +PRStatus +JSS_PK11_getPubKeyPtr(JNIEnv *env, jobject pubkObject, + SECKEYPublicKey** ptr); + +/*********************************************************************** + * J S S _ P K 1 1 _ g e t S y m K e y P t r + * + * Given a Java PK11SymKey, extracts the C PK11SymKey and stores it at + * the given address. + */ +PR_EXTERN( PRStatus ) +JSS_PK11_getSymKeyPtr(JNIEnv *env, jobject symKeyObject, PK11SymKey **ptr); + +/*********************************************************************** + * + * J S S _ P K 1 1 _ w r a p S y m K e y + * symKey: will be stored in a Java wrapper. + * Returns: a new PK11SymKey, or NULL if an exception occurred. + */ +PR_EXTERN( jobject ) +JSS_PK11_wrapSymKey(JNIEnv *env, PK11SymKey **symKey); + +/*********************************************************************** + * JSS_PK11_getKeyType + * + * Converts a PrivateKey.KeyType object to a PKCS #11 key type. + * + * INPUTS + * keyTypeObj + * A com.netscape.jss.crypto.PrivateKey.KeyType object. + * RETURNS + * The key type, or nullKey if an exception occurred. + */ +PR_EXTERN( KeyType ) +JSS_PK11_getKeyType(JNIEnv *env, jobject keyTypeObj); + + + +/*===================================================================== + C E R T I F I C A T E S +=====================================================================*/ + + + +/****************************************************************** + * + * J S S _ P K 1 1 _ g e t C e r t P t r + * + * Given a PK11Cert object, extracts the CERTCertificate* and + * stores it at the given address. + * + * certObject: A JNI reference to a JSS Certificate object. + * ptr: Address of a CERTCertificate* that will receive the pointer. + * Returns: PR_SUCCESS for success, PR_FAILURE if an exception was thrown. + */ +PR_EXTERN( PRStatus ) +JSS_PK11_getCertPtr(JNIEnv *env, jobject certObject, CERTCertificate **ptr); + + +/**************************************************************** + * + * J S S _ P K 1 1 _ w r a p C e r t + * + * Builds a PK11Cert object from a CERTCertificate. + * ppCert: Pointer to pointer to CERTCertificate. The CERTCertificate + * will be wrapped in a Java certificate. If this fails, it + * will be deleted. In any case, the caller should never worry about, + * or use, this CERTCertificate again. To enforce this, *ppCert + * will be set to NULL whether the functions fails or succeeds. + * Returns: a new Java PK11Cert object, or NULL if an exception was thrown. + */ +PR_EXTERN( jobject ) +JSS_PK11_wrapCert(JNIEnv *env, CERTCertificate **ppCert); + + +/*===================================================================== + S T O R E S +=====================================================================*/ + +/************************************************************************ + * + * J S S _ g e t S t o r e S l o t P t r + * + * Retrieve the PK11SlotInfo pointer of the given PK11Store. + * + * INPUTS + * store + * A reference to a Java PK11Store + * slot + * address of a PK11SlotInfo* that will be loaded with + * the PK11SlotInfo pointer of the given token. + * RETURNS + * PR_SUCCESS if the operation was successful, PR_FAILURE if an + * exception was thrown. + */ +PR_EXTERN( PRStatus ) +JSS_PK11_getStoreSlotPtr(JNIEnv *env, jobject store, PK11SlotInfo **slot); + + + +/*===================================================================== + T O K E N S +=====================================================================*/ + + + +/****************************************************************** +** +** J S S _ P K 1 1 _ m a k e C r y p t o T o k e n F r o m P K 1 1 +** +** Returns a new CryptoToken object, or NULL if an exception was thrown. +**/ +PR_EXTERN( jobject ) +JSS_PK11_makeCryptoTokenFromPK11(JNIEnv *env, jobject pk11token); + +/*********************************************************************** + * + * J S S _ P K 1 1 _ w r a p P K 1 1 T o k e n + * + * Create a PK11Token object from a PKCS #11 slot. + * + * slot is a pointer to a PKCS #11 slot, which must not be NULL. It will + * be eaten by the wrapper and set to NULL. + * + * Returns a new PK11Token object, or NULL if an exception was thrown. + */ +PR_EXTERN( jobject ) +JSS_PK11_wrapPK11Token(JNIEnv *env, PK11SlotInfo **slot); + +/************************************************************************ + * + * J S S _ P K 1 1 _ g e t T o k e n S l o t P t r + * + * Retrieve the PK11SlotInfo pointer of the given token. + * + * tokenObject: A reference to a Java PK11Token + * ptr: address of a PK11SlotInfo* that will be loaded with the PK11SlotInfo + * pointer of the given token. + * returns: PR_SUCCESS if the operation was successful, PR_FAILURE if an + * exception was thrown. + */ +PR_EXTERN( PRStatus ) +JSS_PK11_getTokenSlotPtr(JNIEnv *env, jobject tokenObject, PK11SlotInfo **ptr); + + + +/*===================================================================== + M O D U L E S +=====================================================================*/ +/*********************************************************************** + * + * J S S _ P K 1 1 _ w r a p P K 1 1 M o d u l e + * + * Turns a SECMODModule* C structure into a PK11Module Java object. + * + * INPUTS + * ptr + * Address of a SECMODModule *. This pointer will be copied + * into the new Java object, then set to NULL. + * RETURNS + * A new Java PK11Module object, or NULL if an exception was thrown. + * In any case, the ptr parameter is eaten. + */ +PR_IMPLEMENT( jobject ) +JSS_PK11_wrapPK11Module(JNIEnv *env, SECMODModule **module); + + +/*********************************************************************** + * + * J S S _ P K 1 1 _ g e t M o d u l e P t r + * + * Retrieve the SECMODModule pointer of the given PK11Module. + * + * INPUTS + * module + * A reference to a Java PK11Module. + * ptr + * Address of a SECMODModule * that will be loaded with the + * SECMODModule pointer of the given PK11Module. + * RETURNS + * PR_FAILURE if an exception was thrown, or PR_SUCCESS if the + * peration succeeded. + */ +PR_EXTERN( PRStatus ) +JSS_PK11_getModulePtr(JNIEnv *env, jobject module, SECMODModule **ptr); + + + + +/*===================================================================== + C O N T E X T S +=====================================================================*/ + + +typedef enum { SGN_CONTEXT, VFY_CONTEXT } SigContextType; +typedef struct SigContextProxyStr SigContextProxy; + +/*********************************************************************** + * J S S _ P K 1 1 _ g e t S i g C o n t e x t + * + * Extracts the context pointer from a ContextProxy. + * proxy: a non-NULL SigContextProxy object. + * ptr: address of a SGNContext* or VFYContext* where the pointer will + * be stored. + * type: address of a SigContextType where the type of context will + * be stored. + * Returns: PR_SUCCESS, unless an exception was thrown. + */ +PR_IMPLEMENT( PRStatus ) +JSS_PK11_getSigContext(JNIEnv *env, jobject proxy, void**pContext, + SigContextType* pType); + +/********************************************************************** + * + * J S S _ P K 1 1 _ m a k e S i g C o n t e x t P r o x y + * + * Wraps a context in a ContextProxy. + * + * ctxt: address of a SGNContext* or VFYContext* that must not be NULL. + * It will be eaten by the wrapper and set to NULL. + * type: the type of context, SGN_CONTEXT or VFY_CONTEXT. + * Returns: a new ContextProxy object wrapping the given context, + * or NULL if an exception was thrown. + */ +PR_EXTERN( jobject ) +JSS_PK11_wrapSigContextProxy(JNIEnv *env, void **ctxt, SigContextType type); + +/*********************************************************************** + * + * J S S _ P K 1 1 _ g e t C i p h e r C o n t e x t + * + * Extracts the PK11Context from a CipherContextProxy. + * + * proxy + * A CipherContextProxy. + * + * pContext + * Address of a PK11Context*, which will be filled with the pointer + * extracted from the CipherContextProxy. + * + * RETURNS + * PR_SUCCESS for success, or PR_FAILURE if an exception was thrown. + */ +PR_EXTERN( PRStatus ) +JSS_PK11_getCipherContext(JNIEnv *env, jobject proxy, PK11Context **pContext); + + +/*********************************************************************** + * + * J S S _ P K 1 1 _ w r a p C i p h e r C o n t e x t P r o x y + * + * Wraps a PK11Context in a CipherContextProxy. + * + * context + * address of a poitner to a PK11Context, which must not be NULL. + * It will be eaten by the wrapper and set to NULL, even if the + * function returns NULL. + * + * RETURNS + * A new CipherContextProxy, or NULL if an exception was thrown. + */ +PR_EXTERN( jobject ) +JSS_PK11_wrapCipherContextProxy(JNIEnv *env, PK11Context **context); + + +/*===================================================================== + P K C S # 1 1 H A C K S +=====================================================================*/ + +/*********************************************************************** + * + * J S S _ P K 1 1 _ g e t N e w S e s s i o n + * + * Creates a new session. If one cannot be created, the common shared session + * is returned, and *owner is set to PR_FALSE. Otherwise, the new + * session is returned and *owner is set to PR_TRUE. + * + * slot + * The slot on which to open a session. + * owner + * Pointer to a PRBool which will set to PR_TRUE if a new session was + * created, and to PR_FALSE if the shared session was returned. + * + * RETURNS + * A session that can be used for cryptographic operations. If *owner + * is false, the session is not owned by the called but rather is shared. + */ +PR_EXTERN( CK_SESSION_HANDLE ) +JSS_PK11_getNewSession(PK11SlotInfo *slot, PRBool *owner); + +/*********************************************************************** + * + * J S S _ P K 1 1 _ c l o s e S e s s i o n + * + * Closes a session that was returned by JSS_PK11_GetNewSession. + * + * slot + * The slot on which this session lives. + * + * session + * The sessin to close. + * + * owner + * As returned by JSS_PK11_GetNewSession. PR_TRUE if the session was + * created especially for the caller, PR_FALSE if it is the common + * shared session. + */ +PR_EXTERN( void ) +JSS_PK11_closeSession(PK11SlotInfo *slot, CK_SESSION_HANDLE session, + PRBool owner); + +/*********************************************************************** + * + * J S S _ P K 1 1 _ g e t E r r o r S t r i n g + * + * Returns a simple error string for a given PKCS #11 error. + */ +PR_EXTERN( char* ) +JSS_PK11_getErrorString(CK_RV crv); + + +PR_END_EXTERN_C + +#endif diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/secmodi.h b/mozilla/security/jss/org/mozilla/jss/pkcs11/secmodi.h new file mode 100644 index 00000000000..f72ae3047a6 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/secmodi.h @@ -0,0 +1,77 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +#ifndef _SECMODI_H_ +#define _SECMODI_H_ 1 +#include "pkcs11.h" +#include "prlock.h" +#include "mcom_db.h" +#include "secoidt.h" +#include "secdert.h" +#include "certt.h" +#include "secmodti.h" + +#ifdef PKCS11_USE_THREADS +#define PK11_USE_THREADS(x) x +#else +#define PK11_USE_THREADS(x) +#endif + +SEC_BEGIN_PROTOS + +/* proto-types */ +SECMODModule * SECMOD_NewModule(void); /* create a new module */ +SECMODModule * SECMOD_NewInternal(void); /* create an internal module */ + +/* Data base functions */ +void SECMOD_InitDB(char *); +SECMODModuleList * SECMOD_ReadPermDB(void); + +/*void SECMOD_ReferenceModule(SECMODModule *); */ + +/* Library functions */ +SECStatus SECMOD_LoadModule(SECMODModule *); +SECStatus SECMOD_UnloadModule(SECMODModule *); + +void SECMOD_SlotDestroyModule(SECMODModule *module, PRBool fromSlot); +CK_RV pk11_notify(CK_SESSION_HANDLE session, CK_NOTIFICATION event, + CK_VOID_PTR pdata); +void pk11_SignedToUnsigned(CK_ATTRIBUTE *attrib); +CK_OBJECT_HANDLE pk11_FindObjectByTemplate(PK11SlotInfo *slot, + CK_ATTRIBUTE *inTemplate,int tsize); +SEC_END_PROTOS + +#define PK11_GETTAB(x) ((CK_FUNCTION_LIST_PTR)((x)->functionList)) +#define PK11_SETATTRS(x,id,v,l) (x)->type = (id); \ + (x)->pValue=(v); (x)->ulValueLen = (l); +#endif + diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs11/secmodti.h b/mozilla/security/jss/org/mozilla/jss/pkcs11/secmodti.h new file mode 100644 index 00000000000..32c06668924 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs11/secmodti.h @@ -0,0 +1,174 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +#include "prmon.h" +#include "prtypes.h" + +/* internal data structures */ + +/* structure to allow us to implement the read/write locks for our + * module lists */ +struct SECMODListLockStr { + PRLock *mutex; /*general mutex to protect this data structure*/ + PRMonitor *monitor; /* monitor to allow us to signal */ + int state; /* read/write/waiting state */ + int count; /* how many waiters on this lock */ +}; + +/* represet a pkcs#11 slot reference counted. */ +struct PK11SlotInfoStr { + /* the PKCS11 function list for this slot */ + void *functionList; + SECMODModule *module; /* our parent module */ + /* Boolean to indicate the current state of this slot */ + PRBool needTest; /* Has this slot been tested for Export complience */ + PRBool isPerm; /* is this slot a permanment device */ + PRBool isHW; /* is this slot a hardware device */ + PRBool isInternal; /* is this slot one of our internal PKCS #11 devices */ + PRBool disabled; /* is this slot disabled... */ + PK11DisableReasons reason; /* Why this slot is disabled */ + PRBool readOnly; /* is the token in this slot read-only */ + PRBool needLogin; /* does the token of the type that needs + * authentication (still true even if token is logged + * in) */ + PRBool hasRandom; /* can this token generated random numbers */ + PRBool defRWSession; /* is the default session RW (we open our default + * session rw if the token can only handle one session + * at a time. */ + PRBool isThreadSafe; /* copied from the module */ + /* The actual flags (many of which are distilled into the above PRBools */ + CK_FLAGS flags; /* flags from PKCS #11 token Info */ + /* a default session handle to do quick and dirty functions */ + CK_SESSION_HANDLE session; + PRLock *sessionLock; /* lock for this session */ + /* our ID */ + CK_SLOT_ID slotID; + /* persistant flags saved from startup to startup */ + unsigned long defaultFlags; + /* keep track of who is using us so we don't accidently get freed while + * still in use */ + int refCount; + PRLock *refLock; + /* Password control functions for this slot. many of these are only + * active if the appropriate flag is on in defaultFlags */ + int askpw; /* what our password options are */ + int timeout; /* If we're ask_timeout, what is our timeout time is + * seconds */ + int authTransact; /* allow multiple authentications off one password if + * they are all part of the same transaction */ + int64 authTime; /* when were we last authenticated */ + int minPassword; /* smallest legal password */ + int maxPassword; /* largest legal password */ + uint16 series; /* break up the slot info into various groups of + * inserted tokens so that keys and certs can be + * invalidated */ + uint16 wrapKey; /* current wrapping key for SSL master secrets */ + CK_MECHANISM_TYPE wrapMechanism; + /* current wrapping mechanism for current wrapKey */ + CK_OBJECT_HANDLE refKeys[1]; /* array of existing wrapping keys for */ + CK_MECHANISM_TYPE *mechanismList; /* list of mechanism supported by this + * token */ + int mechanismCount; + /* cache the certificates stored on the token of this slot */ + CERTCertificate **cert_array; + int array_size; + int cert_count; + char serial[16]; + /* since these are odd sizes, keep them last. They are odd sizes to + * allow them to become null terminated strings */ + char slot_name[65]; + char token_name[33]; + PRBool hasRSAInfo; + CK_FLAGS RSAInfoFlags; +}; + +/* hold slot default flags until we initialize a slot. This structure is only + * useful between the time we define a module (either by hand or from the + * database) and the time the module is loaded. Not reference counted */ +struct PK11PreSlotInfoStr { + CK_SLOT_ID slotID; /* slot these flags are for */ + unsigned long defaultFlags; /* bit mask of default implementation this slot + * provides */ + int askpw; /* slot specific password bits */ + long timeout; /* slot specific timeout value */ +}; + +/* Symetric Key structure. Reference Counted */ +struct PK11SymKeyStr { + CK_MECHANISM_TYPE type; /* type of operation this key was created for*/ + CK_OBJECT_HANDLE objectID; /* object id of this key in the slot */ + PK11SlotInfo *slot; /* Slot this key is loaded into */ + void *cx; /* window context in case we need to loggin */ + PRBool owner; + SECItem data; /* raw key data if available */ + CK_SESSION_HANDLE session; + PRBool sessionOwner; + int refCount; /* number of references to this key */ + PRLock *refLock; + int size; /* key size in bytes */ + PK11Origin origin; /* where this key came from + (see def in secmodt.h */ + uint16 series; /* break up the slot info into various groups of + * inserted tokens so that keys and certs can be + * invalidated */ +}; + + +/* + * hold a hash, encryption or signing context for multi-part operations. + * hold enough information so that multiple contexts can be interleaved + * if necessary. ... Not RefCounted. + */ +struct PK11ContextStr { + CK_ATTRIBUTE_TYPE operation; /* type of operation this context is doing + * (CKA_ENCRYPT, CKA_SIGN, CKA_HASH, etc. */ + PK11SymKey *key; /* symetric key used in this context */ + PK11SlotInfo *slot; /* slot this context is operationing on */ + CK_SESSION_HANDLE session; /* session this context is using */ + PRLock *sessionLock; /* lock before accessing a PKCS #11 + * session */ + PRBool ownSession;/* do we own the session? */ + void *cx; /* window context in case we need to loggin*/ + void *savedData;/* save data when we are multiplexing on a + * single context */ + unsigned long savedLength; /* length of the saved context */ + SECItem *param; /* mechanism parameters used to build this + context */ + PRBool init; /* has this contexted been initialized */ + CK_MECHANISM_TYPE type; /* what is the PKCS #11 this context is + * representing (usually what algorithm is + * being used (CKM_RSA_PKCS, CKM_DES, + * CKM_SHA, etc.*/ + PRBool fortezzaHack; /*Fortezza SSL has some hacked semantics*/ +}; + diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs12/AuthenticatedSafes.java b/mozilla/security/jss/org/mozilla/jss/pkcs12/AuthenticatedSafes.java new file mode 100644 index 00000000000..fca6fb14453 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs12/AuthenticatedSafes.java @@ -0,0 +1,517 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.pkcs12; + +import com.netscape.jss.util.Debug; +import java.io.*; +import com.netscape.jss.asn1.*; +import com.netscape.jss.pkcs7.*; +import com.netscape.jss.crypto.*; +import com.netscape.jss.pkix.primitive.*; +import com.netscape.jss.util.*; +import com.netscape.jss.CryptoManager; +import java.security.*; +import java.security.spec.AlgorithmParameterSpec; + +/** + * An AuthenticatedSafes, which is a SEQUENCE of + * SafeContents. + */ +public class AuthenticatedSafes implements ASN1Value { + + private SEQUENCE sequence; + + /** + * The default number of hash iterations (1) when performing PBE keygen. + */ + public static final int DEFAULT_ITERATIONS = 1; + + /** + * Salt length is variable with PKCS #12. NSS uses 16 bytes, MSIE + * uses 20. We'll use 20 to get the 4 extra bytes of security. + */ + private static final int SALT_LENGTH = 20; + + /** + * The default PBE key generation algorithm: SHA-1 with RC2 40-bit CBC. + */ + public static final PBEAlgorithm DEFAULT_KEY_GEN_ALG = + PBEAlgorithm.PBE_SHA1_RC2_40_CBC; + + // security dynamics has a weird way of packaging things, we'll + // work with it for debugging + private static final boolean ACCEPT_SECURITY_DYNAMICS = false; + + /** + * Default constructor, creates an empty AuthenticatedSafes. + */ + public AuthenticatedSafes() { + sequence = new SEQUENCE(); + } + + /** + * Creates an AuthenticatedSafes from a SEQUENCE of ContentInfo. + * @param sequence A non-null sequence of ContentInfo. + */ + public AuthenticatedSafes(SEQUENCE sequence) { + if( sequence==null) { + throw new IllegalArgumentException("parameter is null"); + } + if( Debug.DEBUG ) { + for( int i = 0; i < sequence.size(); i++ ) { + if( ! (sequence.elementAt(i) instanceof ContentInfo) ) { + throw new IllegalArgumentException( + "element "+i+" of sequence is not a ContentInfo"); + } + } + } + this.sequence = sequence; + } + + /** + * Returns the raw SEQUENCE which constitutes this + * AuthenticatedSafes. The elements of this sequence are some + * form of SafeContents, wrapped in a ContentInfo or + * an EncryptedData. + */ + public SEQUENCE getSequence() { + return sequence; + } + + /** + * Returns the size of the sequence, which is the number of SafeContents + * in this AuthenticatedSafes. + */ + public int getSize() { + return sequence.size(); + } + + /** + * Returns true if the SafeContents at the given index in the + * AuthenticatedSafes is encrypted. If it is encrypted, a password + * must be supplied to getSafeContentsAt when accessing + * this SafeContents. + */ + public boolean safeContentsIsEncrypted(int index) { + ContentInfo ci = (ContentInfo) sequence.elementAt(index); + return ci.getContentType().equals(ContentInfo.ENCRYPTED_DATA); + } + + /** + * Returns the SafeContents at the given index in the AuthenticatedSafes, + * decrypting it if necessary. + * + *

The algorithm used to extract encrypted SafeContents does not + * conform to version 1.0 of the spec. Instead, it conforms to the + * draft 1.0 spec, because this is what Communicator and MSIE seem + * to conform to. This looks like an implementation error that has + * become firmly entrenched to preserve interoperability. The draft + * spec dictates that the encrypted content in the EncryptedContentInfo + * is the DER encoding of a SafeContents. This is simple enough. The + * 1.0 final spec says that the SafeContents is wrapped in a ContentInfo, + * then the ContentInfo is BER encoded, then the value octets (not the + * tag or length) are encrypted. No wonder people stayed with the old way. + * + * @param password The password to use to decrypt the SafeContents if + * it is encrypted. If the SafeContents is known to not be encrypted, + * this parameter can be null. If the password is incorrect, the + * decoding will fail somehow, probably with an InvalidBERException, + * BadPaddingException, or IllegalBlockSizeException. + * @param index The index of the SafeContents to extract. + * @return A SafeContents object, which is merely a + * SEQUENCE of SafeBags. + * @exception IllegalArgumentException If no password was provided, + * but the SafeContents is encrypted. + */ + public SEQUENCE getSafeContentsAt(Password password, int index) + throws IllegalStateException, CryptoManager.NotInitializedException, + NoSuchAlgorithmException, InvalidBERException, IOException, + InvalidKeyException, InvalidAlgorithmParameterException, TokenException, + IllegalBlockSizeException, BadPaddingException + { + + ContentInfo ci = (ContentInfo) sequence.elementAt(index); + + if( ci.getContentType().equals(ContentInfo.ENCRYPTED_DATA) ) { + // SafeContents is encrypted + + if( password == null ) { + // can't decrypt if we don't have a password + throw new IllegalStateException("No password to decode "+ + "encrypted SafeContents"); + } + + EncryptedContentInfo encCI = (EncryptedContentInfo) + ((EncryptedData)ci.getInterpretedContent()). + getEncryptedContentInfo(); + + // this should be a BER-encoded SafeContents + byte[] decrypted = encCI.decrypt(password, + new PasswordConverter()); + + //print_byte_array(decrypted); + + try { + SEQUENCE.OF_Template seqt = new SEQUENCE.OF_Template( + SafeBag.getTemplate() ); + return (SEQUENCE) ASN1Util.decode(seqt, decrypted); + } catch(InvalidBERException e) { + if( ACCEPT_SECURITY_DYNAMICS ) { + // try the security dynamics approach + ContentInfo.Template cit = ContentInfo.getTemplate(); + ci = (ContentInfo) ASN1Util.decode(cit, decrypted); + if( ! ci.getContentType().equals(ContentInfo.DATA) ) { + throw new InvalidBERException(""); + } + OCTET_STRING os = (OCTET_STRING) ci.getInterpretedContent(); + SEQUENCE.OF_Template seqt = new SEQUENCE.OF_Template( + SafeBag.getTemplate() ); + return (SEQUENCE) ASN1Util.decode(seqt, os.toByteArray()); + } else { + throw e; + } + } + + } else if( ci.getContentType().equals(ContentInfo.DATA) ) { + // This SafeContents is not encrypted + + SEQUENCE.OF_Template seqt = new SEQUENCE.OF_Template( + SafeBag.getTemplate() ); + return (SEQUENCE) ASN1Util.decode(seqt, + ((OCTET_STRING)ci.getInterpretedContent()). + toByteArray() ); + } else { + throw new InvalidBERException("AuthenticatedSafes element is"+ + " neither a Data or an EncryptedData"); + } + } + + static void print_byte_array(byte[] bytes) { + int online=0; + for(int i=0; i < bytes.length; i++, online++) { + if( online > 25 ) { + System.out.println(""); + online=0; + } + System.out.print(Integer.toHexString(bytes[i]&0xff) + " "); + } + System.out.println(""); + } + + /** + * Returns the decrypted content from the encrypted content info. + private static byte[] + decryptEncryptedContentInfo(EncryptedContentInfo eci, Password pass) + throws IllegalStateException,CryptoManager.NotInitializedException, + NoSuchAlgorithmException, InvalidBERException, IOException, + InvalidKeyException, InvalidAlgorithmParameterException, TokenException, + IllegalBlockSizeException, BadPaddingException + { + OCTET_STRING encryptedContent = eci.getEncryptedContent(); + if( encryptedContent == null ) { + return null; + } + + // get the key gen parameters + AlgorithmIdentifier algid = eci.getContentEncryptionAlgorithm(); + KeyGenAlgorithm kgAlg = KeyGenAlgorithm.fromOID( algid.getOID() ); + System.out.println("ContentEncryptionAlg: "+kgAlg); + ASN1Value params = algid.getParameters(); + if( params == null ) { + throw new InvalidAlgorithmParameterException( + "PBE algorithms require parameters"); + } + byte[] encodedParams = ASN1Util.encode(params); + PBEParameter pbeParams = (PBEParameter) + ASN1Util.decode( PBEParameter.getTemplate(), encodedParams ); + PBEKeyGenParams kgp = new PBEKeyGenParams(pass, + pbeParams.getSalt(), pbeParams.getIterations() ); + + + // compute the key and IV + CryptoToken token = + CryptoManager.getInstance().getInternalCryptoToken(); + KeyGenerator kg = token.getKeyGenerator( kgAlg ); + kg.setCharToByteConverter( new PasswordConverter() ); + kg.initialize( kgp ); + SymmetricKey key = kg.generate(); + + // compute algorithm parameters + EncryptionAlgorithm encAlg = keyGenAlgToEncryptionAlg(kgAlg); + AlgorithmParameterSpec algParams; + if( encAlg.getParameterClass().equals( IVParameterSpec.class ) ) { + algParams = new IVParameterSpec( kg.generatePBE_IV() ); + } else { + algParams = null; + } + + // perform the decryption + Cipher cipher = token.getCipherContext( encAlg ); + System.out.println("EncryptionAlg: "+encAlg); + cipher.initDecrypt(key, algParams ); + return cipher.doFinal( encryptedContent.toByteArray() ); + } + */ + + /** + * Appends an unencrypted SafeContents to the end of the AuthenticatedSafes. + */ + public void addSafeContents(SEQUENCE safeContents) { + checkSafeContents(safeContents); + + ContentInfo ci = new ContentInfo( ASN1Util.encode(safeContents) ); + + sequence.addElement(ci); + } + + /** + * Verifies that each element is a SafeBag. Throws an + * IllegalArgumentException otherwise. + */ + private static void checkSafeContents(SEQUENCE safeContents) { + int size = safeContents.size(); + for( int i = 0; i < size; i++) { + if( ! (safeContents.elementAt(i) instanceof SafeBag) ) { + throw new IllegalArgumentException( + "Element "+i+" of SafeContents is not a SafeBag"); + } + } + } + + /** + * Encrypts a SafeContents and adds it to the AuthenticatedSafes. + * + * @param keyGenAlg The algorithm used to generate a key from the password. + * Must be a PBE algorithm. DEFAULT_KEY_GEN_ALG is + * usually fine here. It only provides 40-bit security, but if the + * private key material is packaged in its own + * EncryptedPrivateKeyInfo, the security of the SafeContents + * is not as important. + * @param password The password to use to generate the encryption key + * and IV. + * @param salt The salt to use to generate the key and IV. If null is + * passed in, the salt will be generated randomly, which is usually + * the right thing to do. + * @param iterationCount The number of hash iterations to perform when + * generating the key and IV. Use DEFAULT_ITERATIONS unless + * you want to be clever. + * @param safeContents A SafeContents, which is a SEQUENCE of SafeBags. + * Each element of the sequence must in fact be an instance of + * SafeBag. + */ + public void addEncryptedSafeContents(PBEAlgorithm keyGenAlg, + Password password, byte[] salt, int iterationCount, + SEQUENCE safeContents) + throws CryptoManager.NotInitializedException, InvalidKeyException, + InvalidAlgorithmParameterException, TokenException, + NoSuchAlgorithmException, BadPaddingException, + IllegalBlockSizeException + { + try { + + // generate salt if necessary + if( salt == null ) { + // generate random salt + JSSSecureRandom rand = CryptoManager.getInstance(). + createPseudoRandomNumberGenerator(); + salt = new byte[SALT_LENGTH]; + rand.nextBytes(salt); + } + + EncryptedContentInfo encCI = + EncryptedContentInfo.createPBE(keyGenAlg, password, salt, + iterationCount, new PasswordConverter(), + ASN1Util.encode(safeContents)); + + EncryptedData encData = new EncryptedData(encCI); + + ContentInfo ci = new ContentInfo(encData); + + sequence.addElement( ci ); + } catch( CharConversionException e ) { + Assert.notReached("CharConversionException while converting password"); + } + } + + /* + private static EncryptedContentInfo + createEncryptedContentInfo(Password password, byte[] salt, + int iterationCount, KeyGenAlgorithm keyGenAlg, + SEQUENCE safeContents) + throws CryptoManager.NotInitializedException, NoSuchAlgorithmException, + InvalidKeyException, InvalidAlgorithmParameterException, TokenException, + BadPaddingException, IllegalBlockSizeException + { + + try { + + // check key gen algorithm + if( ! keyGenAlg.isPBEAlg() ) { + throw new NoSuchAlgorithmException("Key generation algorithm"+ + " is not a PBE algorithm"); + } + + CryptoManager cman = CryptoManager.getInstance(); + + // generate salt if necessary + if( salt == null ) { + // generate random salt + JSSSecureRandom rand = cman.createPseudoRandomNumberGenerator(); + salt = new byte[SALT_LENGTH]; + rand.nextBytes(salt); + } + + // generate key + CryptoToken token = cman.getInternalCryptoToken(); + KeyGenerator kg = token.getKeyGenerator( keyGenAlg ); + PBEKeyGenParams pbekgParams = new PBEKeyGenParams( + password, salt, iterationCount); + kg.setCharToByteConverter( new PasswordConverter() ); + kg.initialize(pbekgParams); + SymmetricKey key = kg.generate(); + + // generate IV + EncryptionAlgorithm encAlg = keyGenAlgToEncryptionAlg(keyGenAlg); + AlgorithmParameterSpec params=null; + if( encAlg.getParameterClass().equals( IVParameterSpec.class ) ) { + params = new IVParameterSpec( kg.generatePBE_IV() ); + } + + // perform encryption + Cipher cipher = token.getCipherContext( encAlg ); + cipher.initEncrypt( key, params ); + byte[] encrypted = cipher.doFinal( Cipher.pad( + ASN1Util.encode(safeContents), encAlg.getBlockSize()) ); + + // make encryption algorithm identifier + PBEParameter pbeParam = new PBEParameter( salt, iterationCount ); + AlgorithmIdentifier encAlgID = new AlgorithmIdentifier( + keyGenAlg.toOID(), pbeParam); + + // create EncryptedContentInfo + EncryptedContentInfo encCI = new EncryptedContentInfo( + ContentInfo.DATA, + encAlgID, + new OCTET_STRING(encrypted) ); + + return encCI; + + } catch( CharConversionException e ) { + Assert.notReached("Unable to convert password characters"); + return null; + } + } + */ + + + /* + private static EncryptionAlgorithm + keyGenAlgToEncryptionAlg(KeyGenAlgorithm kgAlg) + throws NoSuchAlgorithmException + { + + if( kgAlg==KeyGenAlgorithm.PBE_MD2_DES_CBC || + kgAlg==KeyGenAlgorithm.PBE_MD5_DES_CBC || + kgAlg==KeyGenAlgorithm.PBE_SHA1_DES_CBC) { + return EncryptionAlgorithm.DES_CBC; + } else if( kgAlg==KeyGenAlgorithm.PBE_SHA1_RC4_128 || + kgAlg==KeyGenAlgorithm.PBE_SHA1_RC4_40 ) { + return EncryptionAlgorithm.RC4; + } else if( kgAlg==KeyGenAlgorithm.PBE_SHA1_DES3_CBC ) { + return EncryptionAlgorithm.DES3_CBC; + } else if( kgAlg==KeyGenAlgorithm.PBE_SHA1_RC2_128 || + kgAlg==KeyGenAlgorithm.PBE_SHA1_RC2_40 ) { + return EncryptionAlgorithm.RC2_CBC; + } else { + throw new NoSuchAlgorithmException(kgAlg.toString()); + } + } + */ + + /////////////////////////////////////////////////////////////////////// + // DER encoding + /////////////////////////////////////////////////////////////////////// + private static final Tag TAG = SEQUENCE.TAG; + + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + encode(TAG, ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + sequence.encode(implicitTag, ostream); + } + + private static final Template templateInstance = new Template(); + + public static Template getTemplate() { + return templateInstance; + } + + + /** + * A Template class for decoding an AuthenticatedSafes from its + * BER encoding. + */ + public static class Template implements ASN1Template { + + private SEQUENCE.OF_Template seqt; + + public Template() { + seqt = new SEQUENCE.OF_Template( ContentInfo.getTemplate() ); + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws InvalidBERException, IOException + { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws InvalidBERException, IOException + { + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); + + return new AuthenticatedSafes(seq); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs12/CertBag.java b/mozilla/security/jss/org/mozilla/jss/pkcs12/CertBag.java new file mode 100644 index 00000000000..63ffe5e487d --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs12/CertBag.java @@ -0,0 +1,192 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs12; + +import com.netscape.jss.asn1.*; +import java.io.*; +import com.netscape.jss.util.Assert; + +/** + * A PKCS #12 cert bag. + */ +public class CertBag implements ASN1Value { + + + /////////////////////////////////////////////////////////////////////// + // Cert Type OIDs + /////////////////////////////////////////////////////////////////////// + private static final OBJECT_IDENTIFIER CERT_TYPES = + OBJECT_IDENTIFIER.PKCS9.subBranch(22); + + public static final OBJECT_IDENTIFIER X509_CERT_TYPE = + CERT_TYPES.subBranch(1); + + public static final OBJECT_IDENTIFIER SDSI_CERT_TYPE = + CERT_TYPES.subBranch(2); + + /////////////////////////////////////////////////////////////////////// + // members and member access + /////////////////////////////////////////////////////////////////////// + private OBJECT_IDENTIFIER certType; + private ANY cert; + private SEQUENCE sequence; + + /** + * Returns the certType field of the CertBag. Currently defined types are: + *

    + *
  • X509Certificate (X509_CERT_TYPE) + *
  • SDSICertificate (SDSI_CERT_TYPE) + *
+ */ + public OBJECT_IDENTIFIER getCertType() { + return certType; + } + + /** + * Returns the cert field of the CertBag. + */ + public ANY getCert() { + return cert; + } + + /** + * Returns the cert field of the CertBag based on its type. + *
    + *
  • If the type is X509_CERT_TYPE, returns + * and OCTET_STRING which is the DER-encoding of an X.509 certificate. + *
  • If the type is SDSI_CERT_TYPE, returns + * an IA5String. + *
  • For all other types, returns an ANY. + * + * @exception InvalidBERException If the cert is not encoded correctly. + */ + public ASN1Value getInterpretedCert() throws InvalidBERException { + if( certType.equals(X509_CERT_TYPE) ) { + return cert.decodeWith(OCTET_STRING.getTemplate()); + } else if( certType.equals(SDSI_CERT_TYPE) ) { + return cert.decodeWith(IA5String.getTemplate()); + } else { + return cert; + } + } + + + /////////////////////////////////////////////////////////////////////// + // constructors + /////////////////////////////////////////////////////////////////////// + private CertBag() { } + + /** + * Creates a CertBag from a type and a cert. + */ + public CertBag(OBJECT_IDENTIFIER certType, ASN1Value cert) { + if( certType==null || cert==null ) { + throw new IllegalArgumentException("certType or cert is null"); + } + this.certType = certType; + System.out.println("CertBag has type "+certType.toString()); + if( cert instanceof ANY ) { + this.cert = (ANY) cert; + } else { + try { + byte[] encoded = ASN1Util.encode(cert); + this.cert = (ANY) ASN1Util.decode( ANY.getTemplate(), encoded); + } catch(InvalidBERException e) { + Assert.notReached("converting ASN1Value to ANY failed"); + } + } + sequence = new SEQUENCE(); + sequence.addElement(this.certType); + sequence.addElement(new EXPLICIT(new Tag(0), this.cert) ); + } + + /////////////////////////////////////////////////////////////////////// + // DER encoding + /////////////////////////////////////////////////////////////////////// + private static final Tag TAG = SEQUENCE.TAG; + + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + sequence.encode(ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + sequence.encode(implicitTag, ostream); + } + + private static final Template templateInstance = new Template(); + public static Template getTemplate() { + return templateInstance; + } + + /** + * A Template class for decoding CertBags from their BER encoding. + */ + public static class Template implements ASN1Template { + + private SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + seqt.addElement( OBJECT_IDENTIFIER.getTemplate() ); + seqt.addElement( new EXPLICIT.Template( + new Tag(0), + ANY.getTemplate() ) ); + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws InvalidBERException, IOException + { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws InvalidBERException, IOException + { + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); + + return new CertBag( (OBJECT_IDENTIFIER) seq.elementAt(0), + ((EXPLICIT)seq.elementAt(1)).getContent() ); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs12/MacData.java b/mozilla/security/jss/org/mozilla/jss/pkcs12/MacData.java new file mode 100644 index 00000000000..a22a8656ef9 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs12/MacData.java @@ -0,0 +1,231 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs12; + +import java.io.*; +import com.netscape.jss.asn1.*; +import com.netscape.jss.crypto.*; +import com.netscape.jss.CryptoManager; +import com.netscape.jss.pkcs7.*; +import com.netscape.jss.util.*; +import java.security.*; +import com.netscape.jss.pkix.primitive.AlgorithmIdentifier; + +public class MacData implements ASN1Value { + + private DigestInfo mac; + private OCTET_STRING macSalt; + private INTEGER macIterationCount; + + private static final int DEFAULT_ITERATIONS = 1; + + // 20 is the length of SHA-1 hash output + private static final int SALT_LENGTH = 20; + + public DigestInfo getMac() { + return mac; + } + + public OCTET_STRING getMacSalt() { + return macSalt; + } + + public INTEGER getMacIterationCount() { + return macIterationCount; + } + + public MacData() { } + + /** + * Creates a MacData from the given parameters. + * + * @param macIterationCount 1 is the default and should be used for + * maximum compatibility. null can also be used, in which case + * the macIterationCount will be omitted from the structure + * (and the default value of 1 will be implied). + */ + public MacData(DigestInfo mac, OCTET_STRING macSalt, + INTEGER macIterationCount) + { + if( mac==null || macSalt==null || macIterationCount==null ) { + throw new IllegalArgumentException("null parameter"); + } + + this.mac = mac; + this.macSalt = macSalt; + this.macIterationCount = macIterationCount; + } + + /** + * Creates a MacData by computing a HMAC on the given bytes. An HMAC + * is a message authentication code, which is a keyed digest. It proves + * not only that data has not been tampered with, but also that the + * entity that created the HMAC possessed the symmetric key. + * + * @param password The password used to generate a key using a + * PBE mechanism. + * @param macSalt The salt used as input to the PBE key generation + * mechanism. If null is passed in, new random salt will be created. + * @param iterations The iteration count for creating the PBE key. + * @param toBeMACed The data on which the HMAC will be computed. + * @exception CryptoManager.NotInitializedException If the crypto subsystem + * has not been initialized yet. + * @exception TokenException If an error occurs on a crypto token. + */ + public MacData( Password password, byte[] macSalt, + int iterations, byte[] toBeMACed ) + throws CryptoManager.NotInitializedException, + DigestException, TokenException, CharConversionException + { + try { + + CryptoManager cm = CryptoManager.getInstance(); + CryptoToken token = cm.getInternalCryptoToken(); + + if(macSalt == null) { + JSSSecureRandom rand = cm.createPseudoRandomNumberGenerator(); + macSalt = new byte[ SALT_LENGTH ]; + rand.nextBytes(macSalt); + } + + // generate key from password and salt + KeyGenerator kg = token.getKeyGenerator( KeyGenAlgorithm.PBA_SHA1_HMAC); + PBEKeyGenParams params = new PBEKeyGenParams(password, macSalt, + iterations); + kg.setCharToByteConverter(new PasswordConverter()); + kg.initialize(params); + SymmetricKey key = kg.generate(); + + + // perform the digesting + JSSMessageDigest digest = token.getDigestContext(HMACAlgorithm.SHA1); + digest.initHMAC(key); + byte[] digestBytes = digest.digest(toBeMACed); + + + // put everything into a DigestInfo + AlgorithmIdentifier algID = new AlgorithmIdentifier( + DigestAlgorithm.SHA1.toOID() ); + this.mac = new DigestInfo( algID, new OCTET_STRING(digestBytes)); + this.macSalt = new OCTET_STRING(macSalt); + this.macIterationCount = new INTEGER(iterations); + + } catch( NoSuchAlgorithmException e ) { + Assert.notReached("SHA-1 HMAC algorithm not found on internal "+ + " token ("+ e.toString() + ")"); + } catch( InvalidAlgorithmParameterException e ) { + Assert.notReached("Invalid PBE algorithm parameters"); + } catch( java.lang.IllegalStateException e ) { + Assert.notReached("IllegalStateException"); + } catch( InvalidKeyException e ) { + Assert.notReached("Invalid key exception"); + } + } + + /////////////////////////////////////////////////////////////////////// + // DER encoding + /////////////////////////////////////////////////////////////////////// + + public Tag getTag() { + return TAG; + } + private static final Tag TAG = SEQUENCE.TAG; + + + public void encode(OutputStream ostream) throws IOException { + encode(TAG, ostream); + } + + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + SEQUENCE seq = new SEQUENCE(); + + seq.addElement(mac); + seq.addElement(macSalt); + if( ! macIterationCount.equals(new INTEGER(DEFAULT_ITERATIONS)) ) { + // 1 is the default, only include this element if it is not + // the default + seq.addElement(macIterationCount); + } + + seq.encode(implicitTag, ostream); + } + + private static final Template templateInstance = new Template(); + public static final Template getTemplate() { + return templateInstance; + } + + /** + * A Template for decoding a MacData from its BER encoding. + */ + public static class Template implements ASN1Template { + + private SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + + seqt.addElement( DigestInfo.getTemplate() ); + seqt.addElement( OCTET_STRING.getTemplate() ); + seqt.addElement( INTEGER.getTemplate(), + new INTEGER(DEFAULT_ITERATIONS) ); + } + + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + + public ASN1Value decode(InputStream istream) + throws InvalidBERException, IOException + { + return decode(TAG, istream); + } + + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws InvalidBERException, IOException + { + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); + + return new MacData( (DigestInfo) seq.elementAt(0), + (OCTET_STRING) seq.elementAt(1), + (INTEGER) seq.elementAt(2) ); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs12/Makefile b/mozilla/security/jss/org/mozilla/jss/pkcs12/Makefile new file mode 100644 index 00000000000..9b72e07f79e --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs12/Makefile @@ -0,0 +1,76 @@ +#! gmake +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +####################################################################### +# (1) Include initial platform-independent assignments (MANDATORY). # +####################################################################### + +include manifest.mn + +####################################################################### +# (2) Include "global" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/config.mk + +####################################################################### +# (3) Include "component" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/$(MODULE)/config/config.mk + +####################################################################### +# (4) Include "local" platform-dependent assignments (OPTIONAL). # +####################################################################### + +include config.mk + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### + + + diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs12/PFX.java b/mozilla/security/jss/org/mozilla/jss/pkcs12/PFX.java new file mode 100644 index 00000000000..1d5618850bd --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs12/PFX.java @@ -0,0 +1,477 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs12; + +import com.netscape.jss.asn1.*; +import com.netscape.jss.pkcs7.*; +import com.netscape.jss.pkix.cert.*; +import java.io.*; +import com.netscape.jss.util.Password; +import com.netscape.jss.CryptoManager; +import com.netscape.jss.pkix.primitive.*; +import com.netscape.jss.pkix.primitive.Attribute; +import com.netscape.jss.crypto.*; +import java.security.*; +import com.netscape.jss.pkix.cert.Certificate; + +/** + * The top level ASN.1 structure for a PKCS #12 blob. + * + *

    The general procedure for creating a PFX blob is as follows:

      + * + *
    • Create instances of SafeBag containing things such as + * private keys, certificates, or arbitrary secrets. + *
    • Store the SafeBags in one or more SEQUENCEs. Each SEQUENCE is + * called a SafeContents. + *
    • Create an AuthenticatedSafes. Store each SafeContents into the + * AuthenticatedSafes with addEncryptedSafeContents or + * addSafeContents. + *

      Standard procedure for browsers is for the AuthenticatedSafes to contain + * two instances of SafeContents, one encrypted and the other not. + * Anything you want encrypted can go in the encrypted SafeContents, + * and anything you want in plaintext can go in the regular SafeContents. + * Keep in mind that private key SafeBags usually consist of an + * EncryptedPrivateKeyInfo, which has its own (strong) encryption, + * in which case it is not essential that the SafeContents containing + * the private key also be encrypted. + *

    • Create a PFX containing the AuthenticatedSafes instance, using the + * PFX(AuthenticatedSafes) constructor. + *
    • Add a MAC to the PFX so it can be verified, using + * PFX.computeMacData. + *
    + * + * To decode a PFX,
      + * + *
    • Use a PFX.Template to decode the ASN.1 into a + * PFX object. + *
    • Check the output of PFX.verifyAuthSafes to verify + * the MAC on the PFX. + *
    • Use PFX.getAuthSafes to extract the AuthenticatedSafes + * instance. + *
    • Use AuthenticatedSafes.getSafeContentsAt to grab the + * SafeContents objects in the AuthenticatedSafes. + *
    • Each SafeContents is a SEQUENCE of SafeBags, each of which may + * contain a private key, cert, or arbitrary secret. + *
    + */ +public class PFX implements ASN1Value { + + /////////////////////////////////////////////////////////////////////// + // Members + /////////////////////////////////////////////////////////////////////// + private INTEGER version; + private AuthenticatedSafes authSafes; + private MacData macData; // may be null + private byte[] encodedAuthSafes; // may be null + + // currently we are on version 3 of the standard + private static final INTEGER VERSION = new INTEGER(3); + + /** + * The default number of iterations to use when generating the MAC. + * Currently, it is 1. + */ + public static final int DEFAULT_ITERATIONS = 1; + + + public INTEGER getVersion() { + return version; + } + + public AuthenticatedSafes getAuthSafes() { + return authSafes; + } + + /** + * Returns the MacData of this PFX, which is used to verify the contents. + * This field is optional. If it is not present, null is returned. + */ + public MacData getMacData() { + return macData; + } + + private void setEncodedAuthSafes(byte[] encodedAuthSafes) { + this.encodedAuthSafes = encodedAuthSafes; + } + + /** + * Verifies the HMAC on the authenticated safes, using the password + * provided. + * + * @param password The password to use to compute the HMAC. + * @param reason If supplied, the reason for the verification failure + * will be appended to this StringBuffer. + * @return true if the MAC verifies correctly, false otherwise. If + * this PFX does not contain a MacData, returns false. + */ + public boolean verifyAuthSafes(Password password, StringBuffer reason) + throws CryptoManager.NotInitializedException + { + try { + + if(reason == null) { + // this is just so we don't get a null pointer exception + reason = new StringBuffer(); + } + + if( macData == null ) { + reason.append("No MAC present in PFX"); + return false; + } + + if( encodedAuthSafes == null ) { + // We weren't decoded from a template, we were constructed, + // so just verify the encoding of the AuthSafes provided to + // the constructor. + encodedAuthSafes = ASN1Util.encode(authSafes); + } + + // create a new MacData based on the encoded Auth Safes + DigestInfo macDataMac = macData.getMac(); + MacData testMac = new MacData( password, + macData.getMacSalt().toByteArray(), + macData.getMacIterationCount().intValue(), + encodedAuthSafes ); + + if( testMac.getMac().equals(macDataMac) ) { + return true; + } else { + reason.append("Digests do not match"); + return false; + } + + } catch( java.security.DigestException e ) { + e.printStackTrace(); + reason.append("A DigestException occurred"); + return false; + } catch( TokenException e ) { + reason.append("A TokenException occurred"); + return false; + } catch( CharConversionException e ) { + reason.append("An exception occurred converting the password from"+ + " chars to bytes"); + return false; + } + } + + /////////////////////////////////////////////////////////////////////// + // Constructors + /////////////////////////////////////////////////////////////////////// + private PFX() { } + + /** + * Creates a PFX with the given parameters. + */ + public PFX( INTEGER version, AuthenticatedSafes authSafes, + MacData macData) { + if( version==null || authSafes==null ) { + throw new IllegalArgumentException("null parameter"); + } + + this.version = version; + this.authSafes = authSafes; + this.macData = macData; + } + + /** + * Creates a PFX with the default version. + */ + public PFX( AuthenticatedSafes authSafes, MacData macData ) { + this( VERSION, authSafes, macData ); + } + + /** + * Creates a PFX with the default version and no MacData. The MacData + * can be added later with computeMacData. + * @see #computeMacData + */ + public PFX( AuthenticatedSafes authSafes ) { + this( VERSION, authSafes, null ); + } + + /** + * Computes the macData field and adds it to the PFX. The macData field + * is a Message Authentication Code of the AuthenticatedSafes, and + * is used to prove the authenticity of the PFX. + * + * @param password The password to be used to create the password-based MAC. + * @param salt The salt to be used. If null is passed in, a new salt + * will be created from a random source. + * @param iterationCount The iteration count for the key generation. + * Use DEFAULT_ITERATIONS unless there's a need to be clever. + */ + public void computeMacData(Password password, + byte[] salt, int iterationCount) + throws CryptoManager.NotInitializedException, DigestException, + TokenException, CharConversionException + { + macData = new MacData( password, salt, iterationCount, + ASN1Util.encode(authSafes) ); + } + + + /////////////////////////////////////////////////////////////////////// + // DER encoding + /////////////////////////////////////////////////////////////////////// + + public Tag getTag() { + return TAG; + } + private static final Tag TAG = SEQUENCE.TAG; + + + public void encode(OutputStream ostream) throws IOException { + encode(TAG, ostream); + } + + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + SEQUENCE seq = new SEQUENCE(); + + seq.addElement(version); + seq.addElement( new ContentInfo( ASN1Util.encode(authSafes) ) ); + if(macData != null) { + seq.addElement(macData); + } + seq.encode(implicitTag, ostream); + } + + /** + * A Template for decoding a BER-encoded PFX. + */ + public static class Template implements ASN1Template { + + private SEQUENCE.Template seqt; + public Template() { + seqt = SEQUENCE.getTemplate(); + + seqt.addElement( INTEGER.getTemplate() ); + seqt.addElement( ContentInfo.getTemplate() ); + seqt.addOptionalElement( MacData.getTemplate() ); + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + + public ASN1Value decode(InputStream istream) + throws InvalidBERException, IOException + { + return decode(TAG, istream); + } + + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws InvalidBERException, IOException + { + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); + + ContentInfo authSafesCI = (ContentInfo) seq.elementAt(1); + if( ! authSafesCI.getContentType().equals(ContentInfo.DATA) ) { + throw new InvalidBERException( + "ContentInfo containing AuthenticatedSafes does not have"+ + " content-type DATA"); + } + OCTET_STRING authSafesOS = (OCTET_STRING) + authSafesCI.getInterpretedContent(); + AuthenticatedSafes authSafes = (AuthenticatedSafes) + ASN1Util.decode( AuthenticatedSafes.getTemplate(), + authSafesOS.toByteArray() ); + + PFX pfx = new PFX( (INTEGER) seq.elementAt(0), + authSafes, + (MacData) seq.elementAt(2) ); + + // record the encoding of the auth safes so we can verify the + // MAC later. We can't just re-encode the AuthSafes because + // it is BER, and the re-encoding might be different from + // the original encoding. + pfx.setEncodedAuthSafes(authSafesOS.toByteArray()); + + return pfx; + } + } + + public static void main(String []args) { + + try { + + if( args.length != 2 ) { + System.out.println("Usage: PFX "); + System.exit(-1); + } + FileInputStream fis = new FileInputStream(args[1]); + int certfile = 0; + + CryptoManager.initialize( args[0]+"secmod.db", + args[0]+"key3.db", args[0]+"cert7.db"); + + // Decode the P12 file + PFX.Template pfxt = new PFX.Template(); + PFX pfx = (PFX) pfxt.decode(new BufferedInputStream(fis, 2048)); + System.out.println("Decoded PFX"); + + // now peruse it for interesting info + System.out.println("Version: "+pfx.getVersion()); + AuthenticatedSafes authSafes = pfx.getAuthSafes(); + SEQUENCE asSeq = authSafes.getSequence(); + System.out.println("AuthSafes has "+ + asSeq.size()+" SafeContents"); + System.out.println("Enter password: "); + Password pass = Password.readPasswordFromConsole(); + + // get new password + System.out.println("Enter new password:"); + Password newPass = Password.readPasswordFromConsole(); + + + // verify the PFX + StringBuffer sb = new StringBuffer(); + if( pfx.verifyAuthSafes(pass, sb) ) { + System.out.println("AuthSafes verifies correctly"); + } else { + System.out.println("AuthSafes failed to verify because: "+ + sb); + } + + // get new AuthSafes ready + AuthenticatedSafes newAuthSafes = new AuthenticatedSafes(); + + for(int i=0; i < asSeq.size(); i++) { + SEQUENCE safeContents = authSafes.getSafeContentsAt(pass,i); + + System.out.println("\n\nSafeContents #"+i+" has "+ + safeContents.size()+" bags"); + for(int j=0; j < safeContents.size(); j++) { + SafeBag safeBag = (SafeBag) safeContents.elementAt(j); + System.out.println("\nBag "+j+" has type "+ + safeBag.getBagType() ); + SET attribs = safeBag.getBagAttributes(); + if( attribs == null ) { + System.out.println("Bag has no attributes"); + } else { + for(int b=0; b < attribs.size(); b++) { + Attribute a = (Attribute) attribs.elementAt(b); + if( a.getType().equals(SafeBag.FRIENDLY_NAME)) { + BMPString bs = (BMPString) ((ANY)a.getValues(). + elementAt(0)).decodeWith( + BMPString.getTemplate()); + System.out.println("Friendly Name: "+bs); + } else if(a.getType().equals(SafeBag.LOCAL_KEY_ID)){ + OCTET_STRING os =(OCTET_STRING) + ((ANY)a.getValues(). + elementAt(0)).decodeWith( + OCTET_STRING.getTemplate()); + System.out.println("LocalKeyID:"); + AuthenticatedSafes. + print_byte_array(os.toByteArray()); + } else { + System.out.println("Unknown attribute type"); + } + } + } + ASN1Value val = safeBag.getInterpretedBagContent(); + if( val instanceof PrivateKeyInfo ) { + System.out.println("content is PrivateKeyInfo"); + } else if( val instanceof EncryptedPrivateKeyInfo ) { + EncryptedPrivateKeyInfo epki = + ((EncryptedPrivateKeyInfo)val); + System.out.println( + "content is EncryptedPrivateKeyInfo, algoid:" + + epki.getEncryptionAlgorithm().getOID()); + PrivateKeyInfo pki = epki.decrypt(pass, + new PasswordConverter() ); + byte[] salt = new byte[20]; + JSSSecureRandom rand = CryptoManager.getInstance(). + getSecureRNG(); + rand.nextBytes(salt); + epki = EncryptedPrivateKeyInfo.createPBE( + PBEAlgorithm.PBE_SHA1_DES3_CBC, newPass, + salt, 1, new PasswordConverter(), pki); + + // replace the old safe bag with the new + safeContents.insertElementAt( + new SafeBag( safeBag.getBagType(), + epki, safeBag.getBagAttributes()), i); + safeContents.removeElementAt(i+1); + } else if( val instanceof CertBag ) { + System.out.println(" content is CertBag"); + CertBag cb = (CertBag) val; + if( cb.getCertType().equals(CertBag.X509_CERT_TYPE)) { + OCTET_STRING os = + (OCTET_STRING)cb.getInterpretedCert(); + FileOutputStream fos = new FileOutputStream( + "cert"+(certfile++)+".der"); + os.encode(fos); + fos.close(); + Certificate cert = (Certificate) + ASN1Util.decode(Certificate.getTemplate(), + os.toByteArray()); + cert.getInfo().print(System.out); + } else { + System.out.println("Unrecognized cert type"); + } + } else { + System.out.println("content is ANY"); + } + } + + // Add the new safe contents to the authsafes + if( authSafes.safeContentsIsEncrypted(i) ) { + newAuthSafes.addEncryptedSafeContents( + authSafes.DEFAULT_KEY_GEN_ALG, newPass, + null, authSafes.DEFAULT_ITERATIONS, safeContents); + } else { + newAuthSafes.addSafeContents( safeContents ); + } + } + + // Create new PFX from new authsafes + PFX newPfx = new PFX(newAuthSafes); + newPfx.computeMacData(newPass, null, DEFAULT_ITERATIONS); + + FileOutputStream fos = new FileOutputStream("newjss.p12"); + newPfx.encode(fos); + fos.close(); + + + } catch( Exception e ) { + e.printStackTrace(); + } + } + +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs12/PK12Token.java b/mozilla/security/jss/org/mozilla/jss/pkcs12/PK12Token.java new file mode 100644 index 00000000000..cde423052e4 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs12/PK12Token.java @@ -0,0 +1,728 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.pkcs12; + +import java.io.*; +import java.text.*; +import java.util.*; +import com.netscape.jss.crypto.*; +import com.netscape.jss.pkcs11.*; +import com.netscape.jss.util.*; + +/** + * A PKCS #12 "virtual token". Currently, these extend + * tokens found in the PK11Token class. + * + * @author mharmsen + * @version $Revision: 1.1 $ $Date: 2000-12-15 20:50:34 $ + * @see com.netscape.jss.pkcs12.PK12Token + **/ + +public +class PK12Token +extends PK11Token +{ + ////////////////////////////////////////////////////////////////////////// + // Inner "Member" Classes + ////////////////////////////////////////////////////////////////////////// + + protected abstract + class PK12Store + implements CryptoStore + { + ////////////////////////////////////////////////////////////////////// + // Inner "Member" Public Methods + ////////////////////////////////////////////////////////////////////// + + public X509Certificate + getCertByNickname( String nickname ) + throws ObjectNotFoundException, NotImplementedException, + TokenException + { + throw new + NotImplementedException( "Method \"" + + "getCertByNickname( String nickname )" + + "\" is not implemented!" ); + } + + + public X509Certificate + getCertByDER( byte[] derCert ) + throws ObjectNotFoundException, NotImplementedException, + InvalidDERException, TokenException + { + throw new + NotImplementedException( "Method \"" + + "getCertByDER( byte[] derCert )" + + "\" is not implemented!" ); + } + + + public X509Certificate + getCertByIssuerAndSerialNum( byte[] derIssuer, String issuer, + long serialNumber ) + throws ObjectNotFoundException, NotImplementedException, + InvalidDERException, TokenException + { + throw new + NotImplementedException( "Method \"" + + "getCertByIssuerAndSerialNum( " + + "byte[] derIssuer, String issuer, " + + "long serialNumber )" + + "\" is not implemented!" ); + } + +/* + public X509Certificate + getCertByPrivateKey( PrivateKey key ) + throws ObjectNotFoundException, NotImplementedException, + IllegalArgumentException, TokenException + { + throw new + NotImplementedException( "Method \"" + + "getCertByPrivateKey( PrivateKey key )" + + "\" is not implemented!" ); + } + + + public X509Certificate + getCertByPublicKey( PublicKey key ) + throws ObjectNotFoundException, NotImplementedException, + IllegalArgumentException, TokenException + { + throw new + NotImplementedException( "Method \"" + + "getCertByPublicKey( PublicKey key )" + + "\" is not implemented!" ); + } + + + public X509Certificate + getCertByKeyID( byte[] keyID ) + throws ObjectNotFoundException, NotImplementedException, + IllegalArgumentException, TokenException + { + throw new + NotImplementedException( "Method \"" + + "getCertByKeyID( byte[] keyID )" + + "\" is not implemented!" ); + } + + + public void + deleteCert( X509Certificate cert ) + throws ObjectNotFoundException, NotImplementedException, + IllegalArgumentException, TokenException + { + throw new + NotImplementedException( "Method \"" + + "deleteCert( X509Certificate cert )" + + "\" is not implemented!" ); + } + */ + + /** + * Add a new certificate to the private "certificates" + * data member. + * + * For example: + *
    +         *     storeCertByNickname( certificate, nickname );
    +         * 
    + * + * @param newCertificate The new certificate which + * must already exist on the + * corresponding PKCS #11 token. + * + * @exception NoSuchItemOnTokenException This exception is thrown in + * the case of an inability to + * remove the certificate from + * the vector. + **/ + + public synchronized void + storeCertByNickname( X509Certificate newCertificate, String nickname ) + throws NoSuchItemOnTokenException, NotImplementedException, + TokenException + { + // (1) Add specified certificate to the private + // data member named "certificates" + + if( certificates.contains( newCertificate ) != true ) { + // Add this certificate + certificates.addElement( newCertificate ); + } + else { + // Update this certificate + if( certificates.removeElement( newCertificate ) != true ) { + Assert.notReached( "Certificate has vanished " + + "from vector!" ); + throw new + NoSuchItemOnTokenException( "storeCertByNickname(): " + + "Could not update " + + "certificate named \"" + + nickname + + "\"!" ); + } + else { + certificates.addElement( newCertificate ); + } + } + + + // (2) Call HCL native methods in "exportToPKCS12File" + // to export all data contained in the private data + // member named "certificates" into a disk file + // specified by the data member named "filename", + // always creating/recreating it from scratch. + // + // NOTE: This assumes that a certificate may + // exist without it's corresponding key + // in the key vector space. However, a + // key may NOT exist without its + // corresponding certificate existing + // in its certificate vector space. + + exportToPKCS12File(); + } + + + public PrivateKey + getPrivKeyByKeyID( byte[] keyID ) + throws NoSuchItemOnTokenException, NotImplementedException, + TokenException + { + throw new + NotImplementedException( "Method \"" + + "getPrivKeyByKeyID( byte[] keyID )" + + "\" is not implemented!" ); + } + + + public PrivateKey + getPrivKeyByCert( java.security.cert.Certificate cert ) + throws ObjectNotFoundException, NotImplementedException, + IllegalArgumentException, TokenException + { + throw new + NotImplementedException( "Method \"" + + "getPrivKeyByCert( " + + "java.security.cert.Certificate " + + "cert )" + + "\" is not implemented!" ); + } + + + public void + deletePrivKey( PrivateKey key ) + throws NotImplementedException, NoSuchItemOnTokenException, + TokenException + { + throw new + NotImplementedException( "Method \"" + + "deletePrivKey( PrivateKey key )" + + "\" is not implemented!" ); + } + + + public void + storePrivKey( PrivateKey newKey ) + throws NoSuchItemOnTokenException, NotImplementedException, + TokenException + { + throw new + NotImplementedException( "Method \"" + + "storePrivKey( " + + "PK11PrivKey newKey )" + + "\" is not implemented!" ); + } + + + public void + storePasswordByNickname( Password password, String nickname ) + throws NotImplementedException, TokenException + { + throw new + NotImplementedException( "Method \"" + + "storePasswordByNickname( " + + "Password password, String nickname )" + + "\" is not implemented!" ); + } + + + public Password + getPasswordByNickname( String nickname ) + throws ObjectNotFoundException, NotImplementedException, + TokenException + { + throw new + NotImplementedException( "Method \"" + + "getPasswordByNickname( " + + "String nickname )" + + "\" is not implemented!" ); + } + + + public void + deletePasswordByNickname( String nickname ) + throws ObjectNotFoundException, NotImplementedException, + TokenException + { + throw new + NotImplementedException( "Method \"" + + "deletePasswordByNickname( " + + "String nickname )" + + "\" is not implemented!" ); + } + + + public void + storeObjectByNickname( Serializable object, String nickname ) + throws NotImplementedException, TokenException + { + throw new + NotImplementedException( "Method \"" + + "storeObjectByNickname( " + + "Serializable object, " + + "String nickname )" + + "\" is not implemented!" ); + } + + + public Serializable + getObjectByNickname( String nickname ) + throws ObjectNotFoundException, NotImplementedException, + TokenException + { + throw new + NotImplementedException( "Method \"" + + "getObjectByNickname( " + + "String nickname )" + + "\" is not implemented!" ); + } + + + public void + deleteObjectByNickname( String nickname ) + throws ObjectNotFoundException, NotImplementedException, + TokenException + { + throw new + NotImplementedException( "Method \"" + + "deleteObjectByNickname( " + + "String nickname )" + + "\" is not implemented!" ); + } + + + ////////////////////////////////////////////////////////////////////// + // Inner "Member" Protected Methods + ////////////////////////////////////////////////////////////////////// + + /** + * This protected synchronized method is always called + * whenever it is known that a file does NOT exist + * (as denoted by the second argument to the PK12Token + * factory "constructor" method). This method is called + * whenever a certificate, or a certificate along with its + * corresponding private key need to be saved to an external file. + * + * In each case, this new file, referenced by the PK12Token + * "file" data member, is created/recreated and EVERYTHING + * in the "certificates" PK12Token data member is copied + * into this new PKCS #12 file. + * + * CALLED BY: storeCertByNickname() + **/ + + protected synchronized void + exportToPKCS12File() + { + PK12TokenProxy exportProxy = createPK12TokenExportContext(); + + for( Enumeration certificate = certificates.elements() ; + certificate.hasMoreElements() ; ) { + + exportPK12Token( exportProxy, + ( X509Certificate ) certificate.nextElement() ); + } + + destroyPK12TokenExportContext( exportProxy ); + } + + + ////////////////////////////////////////////////////////////////////// + // Inner "Member" Private Methods + ////////////////////////////////////////////////////////////////////// + + /** + * These private native methods are always called via the protected + * synchronized java method called exportToPKCS12File(): + * + * createPK12TokenExportContext(): creates, opens, and + * truncates the PKCS #12 file + * intended for export + * + * exportPK12Token(): actually exports a single + * piece of data from the Java + * data member "certificates" + * along with its corresponding + * private key if it exists + * + * destroyPK12TokenExportContext(): closes the PKCS #12 file + * intended for export + * + * CALLED BY: exportToPKCS12File() + **/ + + private native PK12TokenProxy + createPK12TokenExportContext(); + + private native void + exportPK12Token( PK12TokenProxy exportProxy, X509Certificate certificate ); + + private native void + destroyPK12TokenExportContext( PK12TokenProxy exportProxy ); + } + + + ////////////////////////////////////////////////////////////////////////// + // Factory Constructor Methods + ////////////////////////////////////////////////////////////////////////// + + /** + * A user calls this static factory method instead of a java constructer + * to initialize the PK12Token class. This native function obtains a + * PKCS #11 slot, transforms it into a JNI byte array, and then calls + * the protected java constructor, PK12Token( filename, flag, slot ). + * + * For example: + *
    +     *     PK12Token token = makePK12Token( "pkcs12file.p12",
    +     *                                      PK12Token.Flag.FILE_EXISTS );
    +     * 
    + * + * @param filename A String containing the name of a PKCS #12 file. + * + * @param flag A Flag containing whether the PKCS #12 file + * should already exist (in which case "flag" is + * Flag.FILE_EXISTS) or should be created (in which + * case "flag" is Flag.CREATE_FILE). + * + * @return PK12Token This method actually invokes the constructor. + **/ + + static public native PK12Token + makePK12Token( String filename, Flag flag ); + + + ////////////////////////////////////////////////////////////////////////// + // Constructor + ////////////////////////////////////////////////////////////////////////// + + /** + * Default constructor which should never be called. + **/ + + private + PK12Token() + { + Assert.assert( false ); + } + + + /** + * Create a new PK12Token. Note that this constructor is always + * invoked from the native code which comprises the "factory method", + * makePK12Token( filename, flag ). + * + * CALLED BY: makePK12Token( String filename, + * Flag flag ) + * + * @param filename A String containing the name of a + * PKCS #12 file. + * + * @param flag A Flag containing whether the PKCS #12 + * file should already exist (in which case + * "flag" is Flag.FILE_EXISTS) or should be + * created (in which case "flag" is + * Flag.CREATE_FILE). + * + * @param slot A byte array containing the corresponding + * PKCS #11 slot. + * + * @exception InvalidPKCS12FileException An exception thrown whenever a file is + * expected to exist, and doesn't. + **/ + + protected + PK12Token( String filename, Flag flag, byte[] slot ) + throws InvalidPKCS12FileException + { + // (1) Call constructor of superclass + super( slot , false, false); + + + // (2) Ensure that a valid filename was passed in + File file; + try { + file = new File( filename ); + } + catch( NullPointerException e ) { + throw new InvalidPKCS12FileException( "PK12Token( String filename, " + + "Flag flag ): Must specify " + + "non-null \"filename\"!" ); + } + + + // (3) Perform initialization dependent upon flag + if( flag == Flag.FILE_EXISTS ) + { + // (a) Check to ensure that specified filename exists + // and is a "normal" file, and if it is, then + // call HCL native methods to "importFromPKCS12File" + // all data contained in a disk file specified by + // the data member named "filename" into the + // private data member named "certificates". + // + // NOTE: This assumes that the PKCS #12 disk + // file only contains certificates and + // keys, since HCL can only process + // these two types of items from a + // PKCS #12 file. + if( ( file.exists() == true ) && ( file.isFile() == true ) ) { + importFromPKCS12File(); + } + else { + throw new InvalidPKCS12FileException( "PK12Token( String filename, " + + "Flag flag ): Could not open " + + "file named \"" + + filename + + "\"!" ); + } + } + else if( flag == Flag.CREATE_FILE ) { + // (b) Check to ensure that specified filename does NOT exist + if( file.exists() == false ) { + throw new InvalidPKCS12FileException( "PK12Token( String filename, " + + "Flag flag ): File named \"" + + filename + + "\" already exists!" ); + } + } + else { + // (c) Bad or missing flag value + Assert.notReached( "Caller was able to insert an illegal " + + "value for Flag!" ); + throw new InvalidPKCS12FileException( "PK12Token( String filename, " + + "Flag flag ): Only the \"flag\" " + + "values of Flag.FILE_EXISTS or " + + "Flag.CREATE_FILE are allowed!" ); + } + } + + + ////////////////////////////////////////////////////////////////////////// + // Finalizer (Destructor) + ////////////////////////////////////////////////////////////////////////// + + /** + * Destroy a PK12Token. Actually, this method does + * nothing more than call its superclass's finalize + * method. + **/ + + // protected void + // finalize() + // { + // super.finalize(); + // } + + + ////////////////////////////////////////////////////////////////////////// + // Exception Classes + ////////////////////////////////////////////////////////////////////////// + + /** + * Thrown if the operation requires a specified file + * to exist, and it doesn't. + **/ + + static public + class InvalidPKCS12FileException + extends Exception + { + public + InvalidPKCS12FileException() {} + + public + InvalidPKCS12FileException( String message ) { + super( message ); + } + } + + + ////////////////////////////////////////////////////////////////////////// + // Protected Methods + ////////////////////////////////////////////////////////////////////////// + + /** + * This protected synchronized method is always called whenever it is + * known that a file already exists (as denoted by the second argument to + * the PK12Token factory "constructor" method). This method is called + * whenever a certificate or key need to be read in from an external file. + * + * In each case, the new file is opened, and all of its + * certificates are read into the internal "certificates" data member as + * well as the default certificate database; all of its keys are read into + * either the PKCS #11 internal module or the PKCS #11 FIPS module + * (whichever one has been selected), as well as the default key database. + * + * CALLED BY: PK12Token() constructor + **/ + + protected synchronized void + importFromPKCS12File() + { + PK12TokenProxy importProxy = createPK12TokenImportContext(); + + importPK12Token( importProxy ); + + destroyPK12TokenImportContext( importProxy ); + } + + + /** + * These private native methods are always called via the protected + * synchronized java method called importFromPKCS12File(): + * + * createPK12TokenImportContext(): opens the PKCS #12 file + * intended to be imported + * + * importPK12Token(): actually imports all certificate + * data into the Java data member + * "certificates" and places this + * information into the default + * certificate database; if a + * private key is encountered, + * then it is placed into the + * selected key token and also + * into the default key database + * + * destroyPK12TokenImportContext(): closes the PKCS #12 file + * intended for import + * + * CALLED BY: importFromPKCS12File() + **/ + + protected native PK12TokenProxy + createPK12TokenImportContext(); + + protected native void + importPK12Token( PK12TokenProxy importProxy ); + + protected native void + destroyPK12TokenImportContext( PK12TokenProxy importProxy ); + + + ////////////////////////////////////////////////////////////////////////// + // Public Data + ////////////////////////////////////////////////////////////////////////// + + // Emulate enumerations + static public + class Flag + { + private Flag() {} + + static public final Flag FILE_EXISTS = new Flag(); + static public final Flag CREATE_FILE = new Flag(); + } + + + ////////////////////////////////////////////////////////////////////////// + // Protected Data + ////////////////////////////////////////////////////////////////////////// + + + ////////////////////////////////////////////////////////////////////////// + // Private Data + ////////////////////////////////////////////////////////////////////////// + + private String filename; + private Vector certificates; +} + + +class PK12TokenProxy +extends com.netscape.jss.util.NativeProxy +{ + ////////////////////////////////////////////////////////////////////////// + // Constructor + ////////////////////////////////////////////////////////////////////////// + + public + PK12TokenProxy( byte[] pointer ) + { + super( pointer ); + } + + + ////////////////////////////////////////////////////////////////////////// + // Finalizer (Destructor) + ////////////////////////////////////////////////////////////////////////// + + protected void + finalize() + throws Throwable + { + super.finalize(); + } + + + ////////////////////////////////////////////////////////////////////////// + // Protected Methods + ////////////////////////////////////////////////////////////////////////// + + + /** + * This is a "no-op" because all freeing of "C" resources is performed + * inside "C" by the + * destroyPK12TokenExportContext( exportProxy ) and the + * destroyPK12TokenImportContext( importProxy ) functions. + **/ + + protected void + releaseNativeResources() {} +} + diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs12/PasswordConverter.java b/mozilla/security/jss/org/mozilla/jss/pkcs12/PasswordConverter.java new file mode 100644 index 00000000000..bd2640a5a95 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs12/PasswordConverter.java @@ -0,0 +1,62 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs12; + +import com.netscape.jss.crypto.KeyGenerator; +import com.netscape.jss.util.Assert; + +/** + * Converts password chars to bytes. The output format is big-endian Unicode, + * with two zero bytes of null-termination at the end. + */ +public final class PasswordConverter + implements KeyGenerator.CharToByteConverter { + + public byte[] convert(char[] chars) { + byte[] bytes = new byte[ (chars.length+1) * 2 ]; + + int c; // char index + int b; // byte index + for(c=0, b=0; c < chars.length; c++) { + bytes[b++] = (byte) ((chars[c] & 0xff00) >>> 8); + bytes[b++] = (byte) (chars[c] & 0xff); + } + bytes[b++] = 0; + bytes[b++] = 0; + Assert.assert(b == bytes.length); + + return bytes; + } + } + diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs12/SafeBag.java b/mozilla/security/jss/org/mozilla/jss/pkcs12/SafeBag.java new file mode 100644 index 00000000000..2c66707f980 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs12/SafeBag.java @@ -0,0 +1,410 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs12; + +import com.netscape.jss.asn1.*; +import java.io.*; +import com.netscape.jss.pkix.primitive.*; +import com.netscape.jss.util.*; +import java.security.*; +import java.security.MessageDigest; +import com.netscape.jss.crypto.*; +import com.netscape.jss.CryptoManager; + +/** + * A PKCS #12 SafeBag structure. + */ +public final class SafeBag implements ASN1Value { + + /////////////////////////////////////////////////////////////////////// + // members and member access + /////////////////////////////////////////////////////////////////////// + private OBJECT_IDENTIFIER bagType; + private ANY bagContent; + private SET bagAttributes; // may be null + + public OBJECT_IDENTIFIER getBagType() { + return bagType; + } + + /** + * Returns the contents of this bag as an ANY. + */ + public ANY getBagContent() { + return bagContent; + } + + /** + * Returns the bagContent interpreted by type. + * @return If type is KeyBag, a PrivateKeyInfo. + *
    If type is PKCS-8ShroudedKeyBag, an EncryptedPrivateKeyInfo. + *
    If type is CertBag, a CertBag. + *
    For any other type, returns an ANY. + */ + public ASN1Value getInterpretedBagContent() throws InvalidBERException { + + if( bagType.equals(KEY_BAG) ) { + return bagContent.decodeWith(PrivateKeyInfo.getTemplate()); + } else if( bagType.equals(PKCS8_SHROUDED_KEY_BAG)) { + return bagContent.decodeWith(EncryptedPrivateKeyInfo.getTemplate()); + } else if( bagType.equals(CERT_BAG) ) { + return bagContent.decodeWith(CertBag.getTemplate()); + } else { + return bagContent; + } + } + + /** + * Returns the attributes of this bag. May return null if this bag + * has no attributes. Each element of the set is a + * com.netscape.jss.pkix.primitive.Attribute. + */ + public SET getBagAttributes() { + return bagAttributes; + } + + /////////////////////////////////////////////////////////////////////// + // OIDs + /////////////////////////////////////////////////////////////////////// + + /** + * The OID branch for PKCS #12, version 1.0. + */ + public static final OBJECT_IDENTIFIER PKCS12_VERSION_1= + OBJECT_IDENTIFIER.PKCS12.subBranch(10); + + /** + * The OID branch for the PKCS #12 bag types. + */ + public static final OBJECT_IDENTIFIER PKCS12_BAG_IDS = + PKCS12_VERSION_1.subBranch(1); + + /** + * A bag containing a private key. The bag content is a KeyBag, + * which is equivalent to a PKCS #8 PrivateKeyInfo + */ + public static final OBJECT_IDENTIFIER KEY_BAG = PKCS12_BAG_IDS.subBranch(1); + + /** + * A bag containing a private key encrypted à la PKCS #8. The bag + * content is a PKCS #8 EncryptedPrivateKeyInfo. + */ + public static final OBJECT_IDENTIFIER PKCS8_SHROUDED_KEY_BAG = + PKCS12_BAG_IDS.subBranch(2); + + /** + * A bag containing a certificate. The bag content is CertBag. + */ + public static final OBJECT_IDENTIFIER CERT_BAG = + PKCS12_BAG_IDS.subBranch(3); + + /** + * A bag containing a certificate revocation list. + * The bag content is CRLBag. + */ + public static final OBJECT_IDENTIFIER CRL_BAG = + PKCS12_BAG_IDS.subBranch(4); + + /** + * A bag containing an arbitrary secret. The bag content is + * SecretBag. + */ + public static final OBJECT_IDENTIFIER SECRET_BAG = + PKCS12_BAG_IDS.subBranch(5); + + /** + * A bag containing a nested SafeContent . The bag content is + * SafeContents, which is merely a SEQUENCE of SafeBag. + */ + public static final OBJECT_IDENTIFIER SAFE_CONTENTS_BAG = + PKCS12_BAG_IDS.subBranch(6); + + /** + * A FriendlyName attribute. The value is a BMPString. + */ + public static final OBJECT_IDENTIFIER FRIENDLY_NAME = + OBJECT_IDENTIFIER.PKCS9.subBranch(20); + + /** + * A LocalKeyID attribute. The value is an octet string. + */ + public static final OBJECT_IDENTIFIER LOCAL_KEY_ID = + OBJECT_IDENTIFIER.PKCS9.subBranch(21); + + /////////////////////////////////////////////////////////////////////// + // Constructors + /////////////////////////////////////////////////////////////////////// + + private SafeBag() { } + + /** + * Creates a new SafeBag from its components. + * + * @param bagType The type of this bag. For compatibility, it should + * be one of the constants defined in this class. + * @param bagContent The contents of the bag. The type of this parameter + * is defined by the bagType parameter. + * @param bagAttributes A SET of Attributes for this SafeBag. Since + * attributes are optional, this parameter may be null. + */ + public SafeBag(OBJECT_IDENTIFIER bagType, ASN1Value bagContent, + SET bagAttributes) + { + if( bagType==null || bagContent==null ) { + throw new IllegalArgumentException("bagType or bagContent is null"); + } + this.bagType = bagType; + try { + if( bagContent instanceof ANY ) { + this.bagContent = (ANY) bagContent; + } else { + byte[] encoded = ASN1Util.encode(bagContent); + this.bagContent = (ANY) ASN1Util.decode(ANY.getTemplate(), + encoded); + } + } catch( InvalidBERException e ) { + Assert.notReached("failed to convert ASN1Value to ANY"); + } + this.bagAttributes = bagAttributes; + } + + /** + * Creates a SafeBag that contains an X.509 Certificate. + * The SafeBag will have a localKeyID attribute equal + * to the SHA-1 hash of the certificate, and a friendlyName + * attribute equal to the supplied string. This is the way Communicator + * makes a CertBag. The same localKeyID attribute should be stored + * in the matching private key bag. + * + * @param cert A DER-encoded X.509 certificate. + * @param friendlyName Will be stored in the friendlyName + * attribute of the SafeBag. Should be the nickname of the cert. + */ + public static SafeBag + createCertBag(byte[] cert, String friendlyName) + throws DigestException, NoSuchAlgorithmException, + InvalidBERException { + return createCertBag(cert, friendlyName, getLocalKeyIDFromCert(cert)); + } + + /** + * Creates a SafeBag that contains an X.509 Certificate. + * The SafeBag will have the given localKeyID attribute, + * and a friendlyName + * attribute equal to the supplied string. This is the way Communicator + * makes a CertBag. The same localKeyID attribute should be stored + * in the matching private key bag. + * + * @param cert A DER-encoded X.509 certificate. + * @param friendlyName Will be stored in the friendlyName + * attribute of the SafeBag. Should be the nickname of the cert. + * @param localKeyID The bytes to used for the localKeyID. These should + * be obtained from the getLocalKeyIDFromCert method. + * @exception InvalidBERException If the cert is not a valid DER encoding. + * @see #getLocalKeyIDFromCert + */ + public static SafeBag + createCertBag(byte[] cert, String friendlyName, byte[] localKeyID) + throws InvalidBERException { + try { + + // create CertBag + CertBag cb = new CertBag(CertBag.X509_CERT_TYPE, new ANY(cert) ); + + // setup attributes + SET attributes = new SET(); + // friendly name should be cert nickname + attributes.addElement(new Attribute( + FRIENDLY_NAME, + new BMPString(friendlyName) )); + attributes.addElement( new Attribute( + LOCAL_KEY_ID, + new OCTET_STRING(localKeyID) )); + + return new SafeBag(CERT_BAG, cb, attributes); + } catch( CharConversionException e ) { + throw new AssertionException("CharConversionException converting"+ + " Unicode to BMPString"); + } + } + + /** + * Computes the LocalKeyID attribute that should be stored with a key + * and certificate. + * + * @param derCert A DER-encoded X.509 certificate. + * @return The SHA-1 hash of the cert, which should be used as the + * localKeyID attribute for the cert's SafeBag. + */ + public static final byte[] + getLocalKeyIDFromCert(byte[] derCert) + throws DigestException, NoSuchAlgorithmException { + MessageDigest digester = MessageDigest.getInstance("SHA-1"); + return digester.digest(derCert); + } + + + /** + * Creates a SafeBag containing a PKCS-8ShroudedKeyBag, which is + * an EncryptedPrivateKeyInfo. The key will be encrypted using + * a triple-DES PBE algorithm, using the supplied password. + * + * @param privk The PrivateKeyInfo containing the private key. + * @param friendlyName The nickname for the key; should be the same + * as the nickname of the associated cert. + * @param localKeyID The localKeyID for the key; should be the same as + * the localKeyID of the associated cert. + * @param The password used to encrypt the private key. + */ + public static SafeBag + createEncryptedPrivateKeyBag(PrivateKeyInfo privk, String friendlyName, + byte[] localKeyID, Password password) + throws CryptoManager.NotInitializedException, TokenException + { + try { + + PBEAlgorithm pbeAlg = PBEAlgorithm.PBE_SHA1_DES3_CBC; + final int DEFAULT_ITERATIONS = 1; + byte[] salt = new byte[pbeAlg.getSaltLength()]; + + JSSSecureRandom rand = CryptoManager.getInstance().getSecureRNG(); + rand.nextBytes(salt); + + EncryptedPrivateKeyInfo epki= EncryptedPrivateKeyInfo.createPBE( + PBEAlgorithm.PBE_SHA1_DES3_CBC, password, salt, + DEFAULT_ITERATIONS, new PasswordConverter(), privk); + + SET attributes = new SET(); + attributes.addElement(new Attribute( + FRIENDLY_NAME, + new BMPString(friendlyName) )); + attributes.addElement( new Attribute( + LOCAL_KEY_ID, + new OCTET_STRING(localKeyID) )); + + return new SafeBag(PKCS8_SHROUDED_KEY_BAG , epki, attributes); + } catch(java.security.NoSuchAlgorithmException e) { + throw new AssertionException( + "Unable to find PBE algorithm: "+e); + } catch(java.security.InvalidKeyException e) { + throw new AssertionException( + "InvalidKeyException while creating EncryptedContentInfo: "+e); + } catch(java.security.InvalidAlgorithmParameterException e) { + throw new AssertionException( + "InvalidAlgorithmParameterException while creating"+ + " EncryptedContentInfo: "+e); + } catch(java.io.CharConversionException e) { + throw new AssertionException( + "CharConversionException while creating EncryptedContentInfo: "+ + e); + } + } + + /////////////////////////////////////////////////////////////////////// + // DER encoding + /////////////////////////////////////////////////////////////////////// + private static final Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + encode(TAG, ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + SEQUENCE seq = new SEQUENCE(); + + seq.addElement( bagType ); + seq.addElement( new EXPLICIT(new Tag(0), bagContent) ); + if( bagAttributes!=null ) { + seq.addElement( bagAttributes ); + } + + seq.encode(implicitTag, ostream); + } + + private static final Template templateInstance = new Template(); + public static Template getTemplate() { + return templateInstance; + } + + /** + * A template for decoding SafeBags. + */ + public static class Template implements ASN1Template { + + private SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + + seqt.addElement( OBJECT_IDENTIFIER.getTemplate() ); + seqt.addElement( new EXPLICIT.Template( + new Tag(0), + ANY.getTemplate() ) + ); + seqt.addOptionalElement( new SET.OF_Template( + Attribute.getTemplate() ) ); + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws InvalidBERException, IOException + { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws InvalidBERException, IOException + { + try { + + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); + + return new SafeBag( (OBJECT_IDENTIFIER) seq.elementAt(0), + ((EXPLICIT)seq.elementAt(1)).getContent(), + (SET) seq.elementAt(2) ); + + } catch( InvalidBERException e ) { + throw new InvalidBERException(e, "SafeBag"); + } + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs12/SecretBag.java b/mozilla/security/jss/org/mozilla/jss/pkcs12/SecretBag.java new file mode 100644 index 00000000000..eddc3ccfef0 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs12/SecretBag.java @@ -0,0 +1,151 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs12; + +import com.netscape.jss.asn1.*; +import com.netscape.jss.util.Assert; +import java.io.*; + +public class SecretBag implements ASN1Value { + + /////////////////////////////////////////////////////////////////////// + // members and member access + /////////////////////////////////////////////////////////////////////// + private OBJECT_IDENTIFIER secretType; + private ANY secret; + private SEQUENCE sequence; + + /** + * Returns the type of secret stored in the SecretBag. + */ + public OBJECT_IDENTIFIER getSecretType() { + return secretType; + } + + /** + * Returns the secret stored in the SecretBag. + */ + public ANY getSecret() { + return secret; + } + + /////////////////////////////////////////////////////////////////////// + // Constructors + /////////////////////////////////////////////////////////////////////// + private SecretBag() { } + + /** + * Creates a SecretBag with the given secret type and secret. Neither + * may be null. + */ + public SecretBag(OBJECT_IDENTIFIER secretType, ASN1Value secret) { + if( secretType==null || secret==null ) { + throw new IllegalArgumentException("SecretBag parameter is null"); + } + + this.secretType = secretType; + if( secret instanceof ANY ) { + this.secret = (ANY) secret; + } else { + byte[] encoded = ASN1Util.encode(secret); + try { + this.secret = (ANY) ASN1Util.decode(ANY.getTemplate(), encoded); + } catch(InvalidBERException e) { + Assert.notReached("Failed to convert ASN1Value to ANY"); + } + } + + sequence = new SEQUENCE(); + sequence.addElement(secretType); + sequence.addElement( new EXPLICIT(new Tag(0), this.secret) ); + } + + /////////////////////////////////////////////////////////////////////// + // DER encoding + /////////////////////////////////////////////////////////////////////// + + private static final Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + sequence.encode(ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + sequence.encode(implicitTag, ostream); + } + + private static final Template templateInstance = new Template(); + public static Template getTemplate() { + return templateInstance; + } + + /** + * A Template class for decoding SecretBags from BER. + */ + public static class Template implements ASN1Template { + + private SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + seqt.addElement( OBJECT_IDENTIFIER.getTemplate() ); + seqt.addElement( new EXPLICIT.Template( + new Tag(0), ANY.getTemplate()) ); + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws InvalidBERException, IOException + { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws InvalidBERException, IOException + { + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); + + return new SecretBag( (OBJECT_IDENTIFIER)seq.elementAt(0), + ((EXPLICIT)seq.elementAt(1)).getContent() ); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs12/SelfTest.java b/mozilla/security/jss/org/mozilla/jss/pkcs12/SelfTest.java new file mode 100644 index 00000000000..0cd4ad89d9e --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs12/SelfTest.java @@ -0,0 +1,91 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs12; + +import java.io.*; +import java.text.*; +import java.util.*; +import com.netscape.jss.util.*; + +/** + * A PKCS #12 "virtual token". Currently, these extend + * tokens found in the PK11Token class. + * + * @author mharmsen + * @version $Revision: 1.1 $ $Date: 2000-12-15 20:50:38 $ + * @see com.netscape.jss.pkcs11.PK11Token + */ +public class SelfTest +{ + //////////////////////////////////////////////////// + // exceptions + //////////////////////////////////////////////////// + + + //////////////////////////////////////////////////// + // public methods + //////////////////////////////////////////////////// + + public static void TestPK12TokenConstructor() + { + PK12Token p1 = PK12Token.makePK12Token( "test0.p12", PK12Token.Flag.FILE_EXISTS ); + PK12Token p2 = PK12Token.makePK12Token( "test1.p12", PK12Token.Flag.CREATE_FILE ); + PK12Token p3 = PK12Token.makePK12Token( "test2.p12", PK12Token.Flag.CREATE_FILE ); + PK12Token p5 = PK12Token.makePK12Token( "", PK12Token.Flag.FILE_EXISTS ); + } + + public static void main(String[] args) + { + TestPK12TokenConstructor(); + } + + //////////////////////////////////////////////////// + // private methods + //////////////////////////////////////////////////// + + + //////////////////////////////////////////////////// + // construction and finalization + //////////////////////////////////////////////////// + + + ////////////////////////////////////////////////// + // Public Data + ////////////////////////////////////////////////// + + + ////////////////////////////////////////////////// + // Private Data + ////////////////////////////////////////////////// +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs12/config.mk b/mozilla/security/jss/org/mozilla/jss/pkcs12/config.mk new file mode 100644 index 00000000000..efdc02d6022 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs12/config.mk @@ -0,0 +1,94 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +####################################################################### +# Adjust specific variables for all platforms # +####################################################################### + +ifndef BUILD_OPT + ifdef LIBRARY_NAME + ifeq ($(OS_ARCH), WINNT) + ifeq ($(OS_TARGET), WIN16) + SHARED_LIBRARY_G = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION)16_g.dll + IMPORT_LIBRARY_G = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION)16_g.lib + else + SHARED_LIBRARY_G = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION)32_g.dll + IMPORT_LIBRARY_G = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION)32_g.lib + endif + else + ifeq ($(OS_ARCH)$(OS_RELEASE), AIX4.1) + SHARED_LIBRARY_G = $(OBJDIR)/lib$(LIBRARY_NAME)$(LIBRARY_VERSION)_shr_g.a + else + SHARED_LIBRARY_G = $(OBJDIR)/lib$(LIBRARY_NAME)$(LIBRARY_VERSION)_g.$(DLL_SUFFIX) + endif + ifdef HAVE_PURIFY + ifdef DSO_BACKEND + PURE_LIBRARY_G = $(OBJDIR)/purelib$(LIBRARY_NAME)$(LIBRARY_VERSION)_g.$(DLL_SUFFIX) + endif + endif + endif + endif +endif + +####################################################################### +# Set the LD_LIBS value to encompass all static JSS, security, and # +# dbm libraries # +####################################################################### + +LD_LIBS += $(LIBJSSPKCS11) \ + $(LIBJSSHCLHACKS) \ + $(LIBJSSCRYPTO) \ + $(LIBJSSUTIL) \ + $(LIBJSSPOLICY) \ + $(LIBSECMOD) \ + $(LIBPKCS12) \ + $(LIBPKCS7) \ + $(LIBCERT) \ + $(LIBKEY) \ + $(LIBCRYPTO) \ + $(LIBHASH) \ + $(LIBSECUTIL) \ + $(LIBDBM) \ + $(NULL) + +####################################################################### +# Append additional LD_LIBS value to encompass all dynamic NSPR 2.0, # +# java, and system libraries # +####################################################################### + +ifeq ($(OS_ARCH), WINNT) + LD_LIBS += $(DLLPLDS) $(DLLPLC) $(DLLPR) $(DLLSYSTEM) +else + LD_LIBS += -L$(SOURCE_LIB_DIR) -lplds3 -lplc3 -lnspr3 $(DLLSYSTEM) +endif + diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs12/manifest.mn b/mozilla/security/jss/org/mozilla/jss/pkcs12/manifest.mn new file mode 100644 index 00000000000..b26b35f9c3e --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs12/manifest.mn @@ -0,0 +1,60 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +CORE_DEPTH = ../../../../.. + +MODULE = ninja + +NS_USE_JDK = 1 + +PACKAGE = com/netscape/jss/pkcs12 + +CLASSES = \ + AuthenticatedSafes \ + CertBag \ + MacData \ + PasswordConverter \ + PFX \ + SafeBag \ + SecretBag \ + $(NULL) + +JSRCS = \ + AuthenticatedSafes.java \ + CertBag.java \ + MacData.java \ + PasswordConverter.java \ + PFX.java \ + SafeBag.java \ + SecretBag.java \ + $(NULL) diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs12/package.html b/mozilla/security/jss/org/mozilla/jss/pkcs12/package.html new file mode 100644 index 00000000000..50f86010077 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs12/package.html @@ -0,0 +1,38 @@ + + + +Creating and interpreting PKCS #12 blobs. The PFX class is the top-level +structure of a PKCS #12 blob. + + diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs7/Attribute.java b/mozilla/security/jss/org/mozilla/jss/pkcs7/Attribute.java new file mode 100644 index 00000000000..8f99652537d --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs7/Attribute.java @@ -0,0 +1,138 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.pkcs7; + +import com.netscape.jss.asn1.*; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; +import com.netscape.jss.util.Assert; + +/** + * An Attribute, which has the following ASN.1 + * definition (roughly): + *
    + *      Attribute ::= SEQUENCE {
    + *          type        OBJECT IDENTIFIER,
    + *          value       SET }
    + * 
    + */ +public class Attribute implements ASN1Value { + + private OBJECT_IDENTIFIER type; + private SET values; + + public static final Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + private Attribute() { } + + public Attribute(OBJECT_IDENTIFIER type, SET values) { + this.type = type; + this.values = values; + } + + public Attribute(OBJECT_IDENTIFIER type, ASN1Value value) { + this.type = type; + this.values = new SET(); + values.addElement(value); + } + + public OBJECT_IDENTIFIER getType() { + return type; + } + + /** + * If this AVA was constructed, returns the SET of ASN1Values passed to the + * constructor. If this Atrribute was decoded with an Attribute.Template, + * returns a SET of ANYs. + */ + public SET getValues() { + return values; + } + + public void encode(OutputStream ostream) throws IOException { + encode(TAG, ostream); + } + + public void encode(Tag implicit, OutputStream ostream) + throws IOException + { + SEQUENCE seq = new SEQUENCE(); + seq.addElement(type); + seq.addElement(values); + + seq.encode(implicit, ostream); + } + + public static Template getTemplate() { + return templateInstance; + } + private static Template templateInstance = new Template(); + +/** + * A Template for decoding an Attribute. + */ +public static class Template implements ASN1Template { + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicit, InputStream istream) + throws IOException, InvalidBERException + { + SEQUENCE.Template seqt = new SEQUENCE.Template(); + + seqt.addElement( new OBJECT_IDENTIFIER.Template() ); + seqt.addElement( new SET.OF_Template(new ANY.Template())); + + SEQUENCE seq = (SEQUENCE) seqt.decode(implicit, istream); + + // The template should have enforced this + Assert.assert(seq.size() == 2); + + return new Attribute( (OBJECT_IDENTIFIER) seq.elementAt(0), + (SET) seq.elementAt(1)); + } +} + +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs7/ContentInfo.java b/mozilla/security/jss/org/mozilla/jss/pkcs7/ContentInfo.java new file mode 100644 index 00000000000..86d71452883 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs7/ContentInfo.java @@ -0,0 +1,268 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs7; + +import java.io.*; +import com.netscape.jss.asn1.*; +import java.util.Vector; +import com.netscape.jss.util.Assert; +import java.math.BigInteger; +import java.io.ByteArrayInputStream; + +/** + * A PKCS #7 ContentInfo structure. + */ +public class ContentInfo implements ASN1Value { + + public static final Tag TAG = SEQUENCE.TAG; // XXX is this right? + + + public static OBJECT_IDENTIFIER DATA = + new OBJECT_IDENTIFIER(new long[] { 1, 2, 840, 113549, 1, 7, 1 }); + public static OBJECT_IDENTIFIER SIGNED_DATA = + new OBJECT_IDENTIFIER(new long[] { 1, 2, 840, 113549, 1, 7, 2 }); + public static OBJECT_IDENTIFIER ENVELOPED_DATA = + new OBJECT_IDENTIFIER(new long[] { 1, 2, 840, 113549, 1, 7, 3 }); + public static OBJECT_IDENTIFIER SIGNED_AND_ENVELOPED_DATA = + new OBJECT_IDENTIFIER(new long[] { 1, 2, 840, 113549, 1, 7, 4 }); + public static OBJECT_IDENTIFIER DIGESTED_DATA = + new OBJECT_IDENTIFIER(new long[] { 1, 2, 840, 113549, 1, 7, 5 }); + public static OBJECT_IDENTIFIER ENCRYPTED_DATA = + new OBJECT_IDENTIFIER(new long[] { 1, 2, 840, 113549, 1, 7, 6 }); + + + + + + private OBJECT_IDENTIFIER contentType; + private ANY content; + private SEQUENCE sequence = new SEQUENCE(); + + private ContentInfo() {} + + /** + * Creates a ContentInfo with the given type and content. + * + * @param contentType The contentType of the ContentInfo. + * @param content The content of the ContentInfo. May be null + * to signify that the optional content field is not present. + */ + public ContentInfo(OBJECT_IDENTIFIER contentType, ASN1Value content) { + this.contentType = contentType; + sequence.addElement(contentType); + if (content != null) { + if( content instanceof ANY ) { + this.content = (ANY) content; + } else { + // convert content to ANY + try { + this.content = (ANY) ASN1Util.decode(ANY.getTemplate(), + ASN1Util.encode(content) ); + } catch(InvalidBERException e) { + Assert.notReached("InvalidBERException while converting"+ + "ASN1Value to ANY"); + } + } + sequence.addElement(new EXPLICIT(new Tag(0),content) ); + } + } + + /** + * Creates a ContentInfo of type data. + */ + public ContentInfo(byte[] data) { + this( DATA, new OCTET_STRING(data) ); + } + + /** + * Creates a ContentInfo of type signedData. + */ + public ContentInfo(SignedData sd) { + this( SIGNED_DATA, sd); + } + + /** + * Creates a ContentInfo of type envelopedData. + */ + public ContentInfo(EnvelopedData ed) { + this( ENVELOPED_DATA, ed ); + } + + /** + * Creates a ContentInfo of type signedAndEnvelopedData. + */ + public ContentInfo(SignedAndEnvelopedData sed) { + this( SIGNED_AND_ENVELOPED_DATA, sed ); + } + + /** + * Creates a ContentInfo of type digestedData. + */ + public ContentInfo(DigestedData dd) { + this( DIGESTED_DATA, dd ); + } + + /** + * Creates a ContentInfo of type encryptedData. + */ + public ContentInfo(EncryptedData ed) { + this( ENCRYPTED_DATA, ed ); + } + + /** + * Returns the contentType field, which determines what kind of content + * is contained in this ContentInfo. It will usually be one of the six + * predefined types, but may also be a user-defined type. + */ + public OBJECT_IDENTIFIER getContentType() { + return contentType; + } + + /** + * Returns true if the content field is present. + */ + public boolean hasContent() { + return (content != null); + } + + /** + * Returns the content, interpreted based on its type. If there is no + * content, null is returned. + *

    If the contentType is + * one of the six standard types, the returned object will be of that + * type. For example, if the ContentInfo has contentType signedData, + * a SignedData object will be returned. If the contentType is data, + * an OCTET_STRING will be returned. + *

    If the contentType is not one of the six standard types, + * the returned object will be an ANY. + *

+ */ + public ASN1Value getInterpretedContent() throws InvalidBERException { + if(contentType.equals(DATA)) { + return content.decodeWith( new OCTET_STRING.Template() ); + } else if( contentType.equals(SIGNED_DATA) ) { + return content.decodeWith( new SignedData.Template() ); + } else if( contentType.equals(ENVELOPED_DATA) ) { + return content.decodeWith( new EnvelopedData.Template()); + } else if( contentType.equals(SIGNED_AND_ENVELOPED_DATA) ) { + return content.decodeWith( + new SignedAndEnvelopedData.Template() ); + } else if( contentType.equals(DIGESTED_DATA) ) { + return content.decodeWith( new DigestedData.Template() ); + } else if( contentType.equals(ENCRYPTED_DATA) ) { + return content.decodeWith( new EncryptedData.Template()); + } else { + // unknown type + return content; + } + } + + /** + * Returns the content encoded as an ANY. If there is no content, + * null is returned. + */ + public ANY getContent() { + return content; + } + + public void encode(OutputStream ostream) throws IOException { + encode(getTag(),ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + sequence.encode(implicitTag,ostream); + } + + public Tag getTag() { + return ContentInfo.TAG; + } + + /** + * Returns a singleton instance of a decoding template for ContentInfo. + */ + public static Template getTemplate() { + return templateInstance; + } + private static Template templateInstance = new Template(); + + /** + * A template for decoding a ContentInfo blob + * + */ + public static class Template implements ASN1Template { + public boolean tagMatch(Tag tag) { + return (tag.equals(ContentInfo.TAG)); + } + + private SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + seqt.addElement(new OBJECT_IDENTIFIER.Template()); + seqt.addOptionalElement( + new EXPLICIT.Template( + new Tag(0), new ANY.Template() + )); + } + + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + return decode(ContentInfo.TAG,istream); + } + + + public ASN1Value decode(Tag implicitTag, InputStream istream ) + throws IOException, InvalidBERException + { + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag,istream); + Assert.assert(seq.size() == 2); + ASN1Value content; + + if( seq.elementAt(1) == null ) { + content = null; + } else { + content = ((EXPLICIT)seq.elementAt(1)).getContent(); + } + + return new ContentInfo( + (OBJECT_IDENTIFIER) seq.elementAt(0), + content + ); + } + } // end of template + +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs7/DigestInfo.java b/mozilla/security/jss/org/mozilla/jss/pkcs7/DigestInfo.java new file mode 100644 index 00000000000..2f1ad58be7a --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs7/DigestInfo.java @@ -0,0 +1,153 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs7; + +import com.netscape.jss.asn1.*; +import com.netscape.jss.pkix.primitive.*; +import java.io.*; +import com.netscape.jss.util.Assert; + +public class DigestInfo implements ASN1Value { + + private AlgorithmIdentifier digestAlgorithm; + private OCTET_STRING digest; + private SEQUENCE sequence; + + private DigestInfo() { } + + public DigestInfo(AlgorithmIdentifier digestAlgorithm, OCTET_STRING digest){ + if( digestAlgorithm==null || digest==null ) { + throw new IllegalArgumentException(); + } + sequence = new SEQUENCE(); + this.digestAlgorithm = digestAlgorithm; + sequence.addElement(digestAlgorithm); + this.digest = digest; + sequence.addElement(digest); + } + + public AlgorithmIdentifier + getDigestAlgorithm() { + return digestAlgorithm; + } + + public OCTET_STRING + getDigest() { + return digest; + } + + private static final Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + public boolean equals(Object obj) { + if( obj==null || !(obj instanceof DigestInfo)) { + return false; + } + DigestInfo di = (DigestInfo)obj; + + return byteArraysAreSame(di.digest.toByteArray(), digest.toByteArray()); + } + + /** + * Compares two non-null byte arrays. Returns true if they are identical, + * false otherwise. + */ + private static boolean byteArraysAreSame(byte[] left, byte[] right) { + + Assert.assert(left!=null && right!=null); + + if( left.length != right.length ) { + return false; + } + + for(int i = 0 ; i < left.length ; i++ ) { + if( left[i] != right[i] ) { + return false; + } + } + + return true; + } + + public void encode(OutputStream ostream) throws IOException { + sequence.encode(ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + sequence.encode(implicitTag, ostream); + } + + private static final Template templateInstance = new Template(); + public static Template getTemplate() { + return templateInstance; + } + + /** + * A class for decoding the BER encoding of a DigestInfo. + */ + public static class Template implements ASN1Template { + + private SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + seqt.addElement( AlgorithmIdentifier.getTemplate()); + seqt.addElement( OCTET_STRING.getTemplate() ); + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream ostream) + throws InvalidBERException, IOException + { + return decode(TAG, ostream); + } + + public ASN1Value decode(Tag implicitTag, InputStream ostream) + throws InvalidBERException, IOException + { + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, ostream); + + return new DigestInfo( + (AlgorithmIdentifier) seq.elementAt(0), + (OCTET_STRING) seq.elementAt(1) ); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs7/DigestedData.java b/mozilla/security/jss/org/mozilla/jss/pkcs7/DigestedData.java new file mode 100644 index 00000000000..244af7d9bb6 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs7/DigestedData.java @@ -0,0 +1,149 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs7; + +import com.netscape.jss.asn1.*; +import com.netscape.jss.pkix.primitive.*; +import java.io.*; + +public class DigestedData implements ASN1Value { + + /////////////////////////////////////////////////////////////////////// + // members and member access + /////////////////////////////////////////////////////////////////////// + private INTEGER version; + private AlgorithmIdentifier digestAlgorithm; + private ContentInfo contentInfo; + private OCTET_STRING digest; + private SEQUENCE sequence; // for DER encoding + + public INTEGER getVersion() { + return version; + } + + public AlgorithmIdentifier getDigestAlgorithm() { + return digestAlgorithm; + } + + public ContentInfo getContentInfo() { + return contentInfo; + } + + public OCTET_STRING getDigest() { + return digest; + } + + /////////////////////////////////////////////////////////////////////// + // constructors + /////////////////////////////////////////////////////////////////////// + private DigestedData() { } + + public DigestedData(INTEGER version, AlgorithmIdentifier digestAlgorithm, + ContentInfo contentInfo, OCTET_STRING digest) + { + if( version==null || digestAlgorithm==null || contentInfo==null || + digest==null ) { + throw new IllegalArgumentException("DigestedData constructor" + +" parameter is null"); + } + + this.version = version; + this.digestAlgorithm = digestAlgorithm; + this.contentInfo = contentInfo; + this.digest = digest; + + sequence = new SEQUENCE(); + sequence.addElement(version); + sequence.addElement(digestAlgorithm); + sequence.addElement(contentInfo); + sequence.addElement(digest); + } + + /////////////////////////////////////////////////////////////////////// + // DER encoding + /////////////////////////////////////////////////////////////////////// + + private static final Tag TAG = SEQUENCE.TAG; + + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + sequence.encode(ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException { + sequence.encode(implicitTag, ostream); + } + + /** + * A Template for decoding BER-encoded DigestData items. + */ + public static class Template implements ASN1Template { + + private SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + + seqt.addElement( INTEGER.getTemplate() ); + seqt.addElement( AlgorithmIdentifier.getTemplate() ); + seqt.addElement( ContentInfo.getTemplate() ); + seqt.addElement( OCTET_STRING.getTemplate() ); + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws InvalidBERException, IOException { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws InvalidBERException, IOException { + + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); + + return new DigestedData( + (INTEGER) seq.elementAt(0), + (AlgorithmIdentifier) seq.elementAt(1), + (ContentInfo) seq.elementAt(2), + (OCTET_STRING) seq.elementAt(3) ); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs7/EncryptedContentInfo.java b/mozilla/security/jss/org/mozilla/jss/pkcs7/EncryptedContentInfo.java new file mode 100644 index 00000000000..c21c12a65f5 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs7/EncryptedContentInfo.java @@ -0,0 +1,353 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs7; + +import com.netscape.jss.pkix.primitive.*; + +import java.io.*; +import com.netscape.jss.asn1.*; +import java.util.Vector; +import com.netscape.jss.util.Assert; +import java.math.BigInteger; +import java.io.ByteArrayInputStream; +import com.netscape.jss.crypto.*; +import java.security.*; +import java.security.spec.AlgorithmParameterSpec; +import com.netscape.jss.util.Password; +import com.netscape.jss.CryptoManager; + +/** + * The PKCS #7 type EncryptedContentInfo, which encapsulates + * encrypted data. + */ +public class EncryptedContentInfo implements ASN1Value { + + /////////////////////////////////////////////////////////////////////// + // members and member access + /////////////////////////////////////////////////////////////////////// + private OBJECT_IDENTIFIER contentType; + private AlgorithmIdentifier contentEncryptionAlgorithm; + private OCTET_STRING encryptedContent; // may be null + + private SEQUENCE sequence = new SEQUENCE(); + + public OBJECT_IDENTIFIER getContentType() { + return contentType; + } + + public AlgorithmIdentifier getContentEncryptionAlgorithm() { + return contentEncryptionAlgorithm; + } + + public OCTET_STRING getEncryptedContent() { + return encryptedContent; + } + + public boolean hasEncryptedContent() { + return (encryptedContent!=null); + } + + /////////////////////////////////////////////////////////////////////// + // Constructors + /////////////////////////////////////////////////////////////////////// + private EncryptedContentInfo() { + } + + /** + * Create a EnvelopedData ASN1 object. + */ + public EncryptedContentInfo( + OBJECT_IDENTIFIER contentType, + AlgorithmIdentifier contentEncryptionAlgorithm, + OCTET_STRING encryptedContent) + { + this(contentType, + contentEncryptionAlgorithm, + encryptedContent, + false); + + } + + public EncryptedContentInfo( + OBJECT_IDENTIFIER contentType, + AlgorithmIdentifier contentEncryptionAlgorithm, + OCTET_STRING encryptedContent, + boolean createHackedCRSCompatibleECI) + { + this.contentType = contentType; + this.contentEncryptionAlgorithm = contentEncryptionAlgorithm; + this.encryptedContent = encryptedContent; + + sequence.addElement(contentType); + sequence.addElement(contentEncryptionAlgorithm); + if(encryptedContent != null) { + if (createHackedCRSCompatibleECI) { + sequence.addElement(new EXPLICIT(new Tag(0), encryptedContent)); + } + else { + sequence.addElement(new Tag(0), encryptedContent); + } + } + } + + public static EncryptedContentInfo createCRSCompatibleEncryptedContentInfo(OBJECT_IDENTIFIER contentType, + AlgorithmIdentifier contentEncryptionAlgorithm, + OCTET_STRING encryptedContent) + { + return new EncryptedContentInfo(contentType, + contentEncryptionAlgorithm, + encryptedContent, + true); + } + + + /////////////////////////////////////////////////////////////////////// + // Crypto shortcuts + /////////////////////////////////////////////////////////////////////// + + /** + * Creates a new EncryptedContentInfo, where the data is encrypted + * with a password-based key. + * + * @param keyGenAlg The algorithm for generating a symmetric key from + * a password, salt, and iteration count. + * @param password The password to use in generating the key. + * @param salt The salt to use in generating the key. + * @param iterationCount The number of hashing iterations to perform + * while generating the key. + * @param charToByteConverter The mechanism for converting the characters + * in the password into bytes. If null, the default mechanism + * will be used, which is UTF8. + * @param toBeEncrypted The bytes to be encrypted and stored in the + * EncryptedContentInfo. Before they are encrypted, they will be + * padded using PKCS padding. + */ + public static EncryptedContentInfo + createPBE(PBEAlgorithm keyGenAlg, Password password, byte[] salt, + int iterationCount, + KeyGenerator.CharToByteConverter charToByteConverter, + byte[] toBeEncrypted) + throws CryptoManager.NotInitializedException, NoSuchAlgorithmException, + InvalidKeyException, InvalidAlgorithmParameterException, TokenException, + CharConversionException + { + + try { + + // check key gen algorithm + if( ! (keyGenAlg instanceof PBEAlgorithm) ) { + throw new NoSuchAlgorithmException("Key generation algorithm"+ + " is not a PBE algorithm"); + } + PBEAlgorithm pbeAlg = (PBEAlgorithm) keyGenAlg; + + CryptoManager cman = CryptoManager.getInstance(); + + // generate key + CryptoToken token = cman.getInternalCryptoToken(); + KeyGenerator kg = token.getKeyGenerator( keyGenAlg ); + PBEKeyGenParams pbekgParams = new PBEKeyGenParams( + password, salt, iterationCount); + if( charToByteConverter != null ) { + kg.setCharToByteConverter( charToByteConverter ); + } + kg.initialize(pbekgParams); + SymmetricKey key = kg.generate(); + + // generate IV + EncryptionAlgorithm encAlg = pbeAlg.getEncryptionAlg(); + AlgorithmParameterSpec params=null; + if( encAlg.getParameterClass().equals( IVParameterSpec.class ) ) { + params = new IVParameterSpec( kg.generatePBE_IV() ); + } + + // perform encryption + Cipher cipher = token.getCipherContext( encAlg ); + cipher.initEncrypt( key, params ); + byte[] encrypted = cipher.doFinal( Cipher.pad( + toBeEncrypted, encAlg.getBlockSize()) ); + + // make encryption algorithm identifier + PBEParameter pbeParam = new PBEParameter( salt, iterationCount ); + AlgorithmIdentifier encAlgID = new AlgorithmIdentifier( + keyGenAlg.toOID(), pbeParam); + + // create EncryptedContentInfo + EncryptedContentInfo encCI = new EncryptedContentInfo( + ContentInfo.DATA, + encAlgID, + new OCTET_STRING(encrypted) ); + + return encCI; + + } catch( IllegalBlockSizeException e ) { + Assert.notReached("IllegalBlockSizeException in EncryptedContentInfo" + +".createPBE"); + } catch( BadPaddingException e ) { + Assert.notReached("BadPaddingException in EncryptedContentInfo" + +".createPBE"); + } + return null; + } + + /** + * Decrypts the content of an EncryptedContentInfo encrypted with a + * PBE key. + * + * @param pass The password to use in generating the PBE decryption key. + * @param charToByteConverter The converter for converting the password + * characters into bytes. May be null to use the default. + * @return The decrypted contents of the EncryptedContentInfo. The contents + * are first unpadded using the PKCS padding mechanism. + */ + public byte[] + decrypt(Password pass, KeyGenerator.CharToByteConverter charToByteConverter) + throws IllegalStateException,CryptoManager.NotInitializedException, + NoSuchAlgorithmException, InvalidBERException, IOException, + InvalidKeyException, InvalidAlgorithmParameterException, TokenException, + IllegalBlockSizeException, BadPaddingException + { + if( encryptedContent == null ) { + return null; + } + + // get the key gen parameters + AlgorithmIdentifier algid = contentEncryptionAlgorithm; + KeyGenAlgorithm kgAlg = KeyGenAlgorithm.fromOID( algid.getOID() ); + if( !(kgAlg instanceof PBEAlgorithm) ) { + throw new NoSuchAlgorithmException("KeyGenAlgorithm is not a"+ + " PBE algorithm"); + } + ASN1Value params = algid.getParameters(); + if( params == null ) { + throw new InvalidAlgorithmParameterException( + "PBE algorithms require parameters"); + } + PBEParameter pbeParams; + if( params instanceof PBEParameter) { + pbeParams = (PBEParameter) params; + } else { + byte[] encodedParams = ASN1Util.encode(params); + pbeParams = (PBEParameter) + ASN1Util.decode( PBEParameter.getTemplate(), encodedParams ); + } + PBEKeyGenParams kgp = new PBEKeyGenParams(pass, + pbeParams.getSalt(), pbeParams.getIterations() ); + + + // compute the key and IV + CryptoToken token = + CryptoManager.getInstance().getInternalCryptoToken(); + KeyGenerator kg = token.getKeyGenerator( kgAlg ); + if( charToByteConverter != null ) { + kg.setCharToByteConverter( charToByteConverter ); + } + kg.initialize( kgp ); + SymmetricKey key = kg.generate(); + + // compute algorithm parameters + EncryptionAlgorithm encAlg = ((PBEAlgorithm)kgAlg).getEncryptionAlg(); + AlgorithmParameterSpec algParams; + if( encAlg.getParameterClass().equals( IVParameterSpec.class ) ) { + algParams = new IVParameterSpec( kg.generatePBE_IV() ); + } else { + algParams = null; + } + + // perform the decryption + Cipher cipher = token.getCipherContext( encAlg ); + cipher.initDecrypt(key, algParams); + return Cipher.unPad(cipher.doFinal( encryptedContent.toByteArray() )); + } + + + /////////////////////////////////////////////////////////////////////// + // DER encoding + /////////////////////////////////////////////////////////////////////// + + private static final Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + encode(getTag(),ostream); + } + + public void encode(Tag tag, OutputStream ostream) throws IOException { + sequence.encode(tag,ostream); + } + + public static Template getTemplate() { + return templateInstance; + } + private static final Template templateInstance = new Template(); + + /** + * A template file for decoding a EnvelopedData blob + * + */ + + public static class Template implements ASN1Template { + + public boolean tagMatch(Tag tag) { + return (tag.equals(EncryptedContentInfo.TAG)); + } + + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + return decode(TAG,istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws IOException, InvalidBERException + { + SEQUENCE.Template seqt = new SEQUENCE.Template(); + seqt.addElement(new OBJECT_IDENTIFIER.Template()); + seqt.addElement(new AlgorithmIdentifier.Template()); + seqt.addOptionalElement(new Tag(0), new OCTET_STRING.Template()); + + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag,istream); + Assert.assert(seq.size() ==3); + + return new EncryptedContentInfo( + (OBJECT_IDENTIFIER) seq.elementAt(0), + (AlgorithmIdentifier) seq.elementAt(1), + (OCTET_STRING) seq.elementAt(2) + ); + } + } // end of template + +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs7/EncryptedData.java b/mozilla/security/jss/org/mozilla/jss/pkcs7/EncryptedData.java new file mode 100644 index 00000000000..577e9bc2140 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs7/EncryptedData.java @@ -0,0 +1,160 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs7; + +import com.netscape.jss.asn1.*; +import java.io.*; + +/** + * The PKCS #7 structure EncryptedData. + */ +public class EncryptedData implements ASN1Value { + + /////////////////////////////////////////////////////////////////////// + // Members + /////////////////////////////////////////////////////////////////////// + private INTEGER version; + private EncryptedContentInfo encryptedContentInfo; + private SEQUENCE sequence; + + /** + * The default version number. This should always be used unless + * you really know what you are doing. + */ + public static final INTEGER DEFAULT_VERSION = new INTEGER(0); + + /////////////////////////////////////////////////////////////////////// + // Constructors + /////////////////////////////////////////////////////////////////////// + private EncryptedData() { } + + /** + * Creates a new EncryptedData. + * + * @param version Should usually be DEFAULT_VERSION unless you are being + * very clever. + */ + public EncryptedData( INTEGER version, + EncryptedContentInfo encryptedContentInfo ) + { + if( version == null || encryptedContentInfo == null ) { + throw new IllegalArgumentException("null parameter"); + } + + sequence = new SEQUENCE(); + + this.version = version; + sequence.addElement(version); + this.encryptedContentInfo = encryptedContentInfo; + sequence.addElement(encryptedContentInfo); + } + + /** + * Creates an EncryptedData with the default version. + */ + public EncryptedData( EncryptedContentInfo encryptedContentInfo ) { + this( DEFAULT_VERSION, encryptedContentInfo ); + } + + /////////////////////////////////////////////////////////////////////// + // Accessor Methods + /////////////////////////////////////////////////////////////////////// + public INTEGER getVersion() { + return version; + } + + public EncryptedContentInfo getEncryptedContentInfo() { + return encryptedContentInfo; + } + + + /////////////////////////////////////////////////////////////////////// + // DER encoding + /////////////////////////////////////////////////////////////////////// + + private static final Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + sequence.encode(ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + sequence.encode(implicitTag, ostream); + } + + public static Template getTemplate() { + return templateInstance; + } + private static final Template templateInstance = new Template(); + + /** + * A Template for decoding EncryptedData items. + */ + public static class Template implements ASN1Template { + + private SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + seqt.addElement( INTEGER.getTemplate() ); + seqt.addElement( EncryptedContentInfo.getTemplate() ); + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws InvalidBERException, IOException + { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws InvalidBERException, IOException + { + + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); + + return new EncryptedData( + (INTEGER) seq.elementAt(0), + (EncryptedContentInfo) seq.elementAt(1) ); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs7/EnvelopedData.java b/mozilla/security/jss/org/mozilla/jss/pkcs7/EnvelopedData.java new file mode 100644 index 00000000000..b3f9dcef92b --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs7/EnvelopedData.java @@ -0,0 +1,134 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs7; + +import java.io.*; +import com.netscape.jss.asn1.*; +import java.util.Vector; +import com.netscape.jss.util.Assert; +import java.math.BigInteger; +import java.io.ByteArrayInputStream; + +public class EnvelopedData implements ASN1Value { + public static final Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + private INTEGER version; + private SET recipientInfos; + private EncryptedContentInfo encryptedContentInfo; + + private SEQUENCE sequence = new SEQUENCE(); + + public INTEGER getVersion() { + return version; + } + public SET getRecipientInfos() { + return recipientInfos; + } + public EncryptedContentInfo getEncryptedContentInfo() { + return encryptedContentInfo; + } + + + + private EnvelopedData() { + } + + /** + * Create a EnvelopedData ASN1 object. + */ + + public EnvelopedData( INTEGER version, SET recipientInfos, + EncryptedContentInfo encryptedContentInfo) { + + this.version = version; + this.recipientInfos = recipientInfos; + this.encryptedContentInfo = encryptedContentInfo; + + sequence.addElement(version); + sequence.addElement(recipientInfos); + sequence.addElement(encryptedContentInfo); + } + + public void encode(OutputStream ostream) throws IOException { + encode(getTag(),ostream); + } + + public void encode(Tag tag, OutputStream ostream) throws IOException { + sequence.encode(tag,ostream); + } + + + /** + * A template file for decoding a EnvelopedData blob + * + */ + + public static class Template implements ASN1Template { + public Tag getTag() { + return EnvelopedData.TAG; + } + + public boolean tagMatch(Tag tag) { + return (tag.equals(EnvelopedData.TAG)); + } + + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + return decode(getTag(),istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws IOException, InvalidBERException + { + SEQUENCE.Template seqt = new SEQUENCE.Template(); + seqt.addElement(new INTEGER.Template()); + seqt.addElement(new SET.OF_Template(new RecipientInfo.Template())); + seqt.addElement(new EncryptedContentInfo.Template()); + + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag,istream); + Assert.assert(seq.size() ==3); + + return new EnvelopedData( + (INTEGER) seq.elementAt(0), + (SET) seq.elementAt(1), + (EncryptedContentInfo) seq.elementAt(2) + ); + } + } // end of template + +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs7/IssuerAndSerialNumber.java b/mozilla/security/jss/org/mozilla/jss/pkcs7/IssuerAndSerialNumber.java new file mode 100644 index 00000000000..1e249b6a200 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs7/IssuerAndSerialNumber.java @@ -0,0 +1,150 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs7; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; +import com.netscape.jss.asn1.*; +import com.netscape.jss.pkix.primitive.*; +import com.netscape.jss.util.Assert; + +/** + * An issuer name and serial number, used to uniquely identify a certificate. + */ +public class IssuerAndSerialNumber implements ASN1Value { + + /////////////////////////////////////////////////////////////////////// + // Members + /////////////////////////////////////////////////////////////////////// + private Name issuer; + private INTEGER serialNumber; + private SEQUENCE sequence; + + /////////////////////////////////////////////////////////////////////// + // Construction + /////////////////////////////////////////////////////////////////////// + + // no default constructor + private IssuerAndSerialNumber() { } + + /** + * Constructs an IssuerAndSerialNumber from its components. + * + * @param issuer Must not be null. + * @param serialNumber must not be null. + */ + public IssuerAndSerialNumber(Name issuer, INTEGER serialNumber) { + if(issuer==null || serialNumber==null) { + throw new IllegalArgumentException(); + } + sequence = new SEQUENCE(); + this.issuer = issuer; + sequence.addElement(issuer); + this.serialNumber = serialNumber; + sequence.addElement(serialNumber); + } + + /////////////////////////////////////////////////////////////////////// + // accessors + /////////////////////////////////////////////////////////////////////// + public Name getIssuer() { + return issuer; + } + + public INTEGER getSerialNumber() { + return serialNumber; + } + + /////////////////////////////////////////////////////////////////////// + // DER encoding + /////////////////////////////////////////////////////////////////////// + static Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + encode(TAG, ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + sequence.encode(implicitTag, ostream); + } + + /** + * Returns a singleton template instance. + */ + public static Template getTemplate() { + return templateInstance; + } + private static Template templateInstance = new Template(); + + /** + * A template for decoding an IssuerAndSerialNumber from its BER encoding. + */ + public static class Template implements ASN1Template { + private SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + seqt.addElement( Name.getTemplate() ); + seqt.addElement( INTEGER.getTemplate() ); + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws InvalidBERException, IOException + { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws InvalidBERException, IOException + { + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); + + Assert.assert(seq.size() == 2); + + return new IssuerAndSerialNumber( + (Name) seq.elementAt(0), + (INTEGER) seq.elementAt(1) ); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs7/Makefile b/mozilla/security/jss/org/mozilla/jss/pkcs7/Makefile new file mode 100644 index 00000000000..ea0708d450d --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs7/Makefile @@ -0,0 +1,75 @@ +#! gmake +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + + +####################################################################### +# (1) Include initial platform-independent assignments (MANDATORY). # +####################################################################### + +include manifest.mn + +####################################################################### +# (2) Include "global" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/config.mk + +####################################################################### +# (3) Include "component" configuration information. (OPTIONAL) # +####################################################################### +include $(CORE_DEPTH)/$(MODULE)/config/config.mk + + +####################################################################### +# (4) Include "local" platform-dependent assignments (OPTIONAL). # +####################################################################### + + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### + + diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs7/RecipientInfo.java b/mozilla/security/jss/org/mozilla/jss/pkcs7/RecipientInfo.java new file mode 100644 index 00000000000..6fae69b200f --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs7/RecipientInfo.java @@ -0,0 +1,161 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs7; + +import com.netscape.jss.pkix.primitive.*; + +import java.io.*; +import com.netscape.jss.asn1.*; +import java.util.Vector; +import com.netscape.jss.util.Assert; +import java.math.BigInteger; +import java.io.ByteArrayInputStream; + +public class RecipientInfo implements ASN1Value { + + public static final Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + private INTEGER version; + private IssuerAndSerialNumber issuerAndSerialNumber; + private AlgorithmIdentifier keyEncryptionAlgorithmID; + private OCTET_STRING encryptedKey; + + private SEQUENCE sequence = new SEQUENCE(); + + public INTEGER getVersion() { + return version; + } + public IssuerAndSerialNumber getissuerAndSerialNumber() { + return issuerAndSerialNumber; + } + public AlgorithmIdentifier getKeyEncryptionAlgorithmID() { + return keyEncryptionAlgorithmID; + } + public OCTET_STRING getEncryptedKey() { + return encryptedKey; + } + + + private static final Template templateInstance = new Template(); + + public static Template getTemplate() { + return templateInstance; + } + + + private RecipientInfo() { + } + + /** + * Create a RecipientInfo ASN1 object. + */ + + public RecipientInfo( INTEGER version, + IssuerAndSerialNumber issuerAndSerialNumber, + AlgorithmIdentifier keyEncryptionAlgorithmID, + OCTET_STRING encryptedKey) { + + Assert.assert(issuerAndSerialNumber != null); + Assert.assert(keyEncryptionAlgorithmID != null); + Assert.assert(encryptedKey != null); + + + this.version = version; + this.issuerAndSerialNumber = issuerAndSerialNumber; + this.keyEncryptionAlgorithmID = keyEncryptionAlgorithmID; + this.encryptedKey = encryptedKey; + + + sequence.addElement(version); + sequence.addElement(issuerAndSerialNumber); + sequence.addElement(keyEncryptionAlgorithmID); + sequence.addElement(encryptedKey); + + } + + public void encode(OutputStream ostream) throws IOException { + encode(getTag(),ostream); + } + + public void encode(Tag tag, OutputStream ostream) throws IOException { + sequence.encode(tag,ostream); + } + + + /** + * A template file for decoding a RecipientInfo blob + * + */ + + public static class Template implements ASN1Template { + public Tag getTag() { + return RecipientInfo.TAG; + } + + public boolean tagMatch(Tag tag) { + return (tag.equals(RecipientInfo.TAG)); + } + + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + return decode(getTag(),istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws IOException, InvalidBERException + { + SEQUENCE.Template seqt = new SEQUENCE.Template(); + seqt.addElement(new INTEGER.Template()); + seqt.addElement(new IssuerAndSerialNumber.Template()); + seqt.addElement(new AlgorithmIdentifier.Template()); + seqt.addElement(new OCTET_STRING.Template()); + + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag,istream); + Assert.assert(seq.size() ==4); + + return new RecipientInfo( + (INTEGER) seq.elementAt(0), + (IssuerAndSerialNumber) seq.elementAt(1), + (AlgorithmIdentifier) seq.elementAt(2), + (OCTET_STRING) seq.elementAt(3) + + ); + } + } // end of template + +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs7/SignedAndEnvelopedData.java b/mozilla/security/jss/org/mozilla/jss/pkcs7/SignedAndEnvelopedData.java new file mode 100644 index 00000000000..92d8d8d5608 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs7/SignedAndEnvelopedData.java @@ -0,0 +1,216 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs7; + +import com.netscape.jss.asn1.*; +import com.netscape.jss.pkix.primitive.*; +import java.io.*; + +public class SignedAndEnvelopedData implements ASN1Value { + + /////////////////////////////////////////////////////////////////////// + // members and member access + /////////////////////////////////////////////////////////////////////// + private INTEGER version; + private SET recipientInfos; + private SET digestAlgorithms; + private EncryptedContentInfo encryptedContentInfo; + private SET certificates; // may be null + private SET crls; // may be null + private SET signerInfos; + private SEQUENCE sequence; // for encoding + + /** + * Returns the version number. The current version is 1. + */ + public INTEGER getVersion() { + return version; + } + + /** + * Returns a SET of RecipientInfo. + */ + public SET getRecipientInfos() { + return recipientInfos; + } + + /** + * Returns a SET of AlgorithmIdentifier. + */ + public SET getDigestAlgorithms() { + return digestAlgorithms; + } + + /** + * Returns the encrypted content. + */ + public EncryptedContentInfo getEncryptedContentInfo() { + return encryptedContentInfo; + } + + /** + * Returns a SET of ANYs. May return null if the + * certificates field is not present. + */ + public SET getCertificates() { + return certificates; + } + + /** + * Returns a SET of ANYs. May return null if the crls + * field is not present. + */ + public SET getCrls() { + return crls; + } + + /** + * Returns a SET of SignerInfo. + */ + public SET getSignerInfos() { + return signerInfos; + } + + /////////////////////////////////////////////////////////////////////// + // Constructors + /////////////////////////////////////////////////////////////////////// + + private SignedAndEnvelopedData() { } + + public SignedAndEnvelopedData( + INTEGER version, + SET recipientInfos, + SET digestAlgorithms, + EncryptedContentInfo encryptedContentInfo, + SET certificates, + SET crls, + SET signerInfos) + { + if( version==null || recipientInfos==null || digestAlgorithms==null + || encryptedContentInfo==null || signerInfos==null ) { + throw new IllegalArgumentException( + "SignedAndEnvelopedData constructor parameter is null"); + } + + this.version = version; + this.recipientInfos = recipientInfos; + this.digestAlgorithms = digestAlgorithms; + this.encryptedContentInfo = encryptedContentInfo; + this.certificates = certificates; + this.crls = crls; + this.signerInfos = signerInfos; + + sequence = new SEQUENCE(); + sequence.addElement(version); + sequence.addElement(recipientInfos); + sequence.addElement(digestAlgorithms); + sequence.addElement(encryptedContentInfo); + if( certificates!=null ) { + sequence.addElement(certificates); + } + if( crls!=null ) { + sequence.addElement(crls); + } + sequence.addElement( signerInfos ); + } + + /////////////////////////////////////////////////////////////////////// + // DER encoding + /////////////////////////////////////////////////////////////////////// + + private static final Tag TAG = SEQUENCE.TAG; + + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + sequence.encode(ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + sequence.encode(implicitTag, ostream); + } + + + /** + * A Template class for decoding BER-encoded SignedAndEnvelopedData items. + */ + public static class Template implements ASN1Template { + + private SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + + seqt.addElement(INTEGER.getTemplate()); + seqt.addElement(new SET.OF_Template(RecipientInfo.getTemplate())); + seqt.addElement(new SET.OF_Template( + AlgorithmIdentifier.getTemplate()) ); + seqt.addElement(EncryptedContentInfo.getTemplate()); + seqt.addOptionalElement(new Tag(0), + new SET.OF_Template(ANY.getTemplate())); + seqt.addOptionalElement(new Tag(1), + new SET.OF_Template(ANY.getTemplate())); + seqt.addElement(new SET.OF_Template(SignerInfo.getTemplate())); + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws InvalidBERException, IOException + { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws InvalidBERException, IOException + { + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); + + return new SignedAndEnvelopedData( + (INTEGER) seq.elementAt(0), + (SET) seq.elementAt(1), + (SET) seq.elementAt(2), + (EncryptedContentInfo) seq.elementAt(3), + (SET) seq.elementAt(4), + (SET) seq.elementAt(5), + (SET) seq.elementAt(6) ); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs7/SignedData.java b/mozilla/security/jss/org/mozilla/jss/pkcs7/SignedData.java new file mode 100644 index 00000000000..ff4b15b2c10 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs7/SignedData.java @@ -0,0 +1,426 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs7; + +import java.io.*; +import java.util.Vector; +import com.netscape.jss.util.Assert; +import java.math.BigInteger; +import java.io.ByteArrayInputStream; +import com.netscape.jss.asn1.*; +import com.netscape.jss.pkix.primitive.*; +import com.netscape.jss.pkix.cert.Certificate; + +/* CUT THIS??? + *

Although all the normal functionality of a SignedData is supported + * with high-level methods, there is a low-level API for setting the + * individual fields of the structure. Using these calls is an unsupported + * way of accomplishing unforeseen tasks. If you have reason to use these + * methods, please notify the authors in case it is something that should + * be added to the high-level interface. + * +*/ + +/** + * A PKCS #7 SignedData structure. This class implements version 1 + * of the spec. + *

The certificates field should only contain X.509 certificates. + * PKCS #6 extended certificates will fail to decode properly. + * @author stevep + * @author nicolson + */ +public class SignedData implements ASN1Value { + + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + // Members + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + + private INTEGER version; + private SET digestAlgorithms; + private ContentInfo contentInfo; + private SET certificates; // [0] optional, may be null + private SET crls; // [1] optional, may be null + private SET signerInfos; + + // This class implements version 1 of the spec. + private static final INTEGER VERSION = new INTEGER(1); + + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + // Accessor methods + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + + private static void verifyNotNull(Object obj) { + if( obj == null ) { + throw new IllegalArgumentException(); + } + } + + /** + * Returns the version of this SignedData. The current version of the + * spec is version 1. + */ + public INTEGER getVersion() { + return version; + } + + /** + * Low-level function to set the version. + * @param version Must not be null. + public void setVersion(INTEGER version) { + verifyNotNull(version); + this.version = version; + } + */ + + /** + * Returns the digest algorithms used by the signers to digest the + * signed content. There may be more than one, if different signers + * use different digesting algorithms. + */ + public SET getDigestAlgorithmIdentifiers() { + return digestAlgorithms; + } + + /** + * Low-level function to set the digest algorithm identifiers. + * @param digestAlgIds Must not be null. + public void setDigestAlgorithmIdentifiers(SET digestAlgIds) { + verifyNotNull(digestAlgIds); + this.digestAlgorithms = digestAlgIds; + } + */ + + /** + * Returns the ContentInfo containing the signed content. The simple + * case is for the content to be of type data, although any + * content type can be signed. + */ + public ContentInfo getContentInfo() { + return contentInfo; + } + + /** + * Low-level function to set the contentInfo. + * @param ci Must not be null. + public void setContentInfo(ContentInfo ci) { + verifyNotNull(ci); + this.contentInfo = ci; + } + */ + + /** + * Returns the certificates field, which is a SET of + * X.509 certificates (com.netscape.jss.pkix.cert.Certificate). + * PKCS #6 Extended Certificates are not supported by this implementation. + * Returns null if this optional field is not present. + * + */ + public SET getCertificates() { + return certificates; + } + + /** + * Low-level function to set the certificates. + * @param certs May be null to signify that the certificates + * field is not present. + public void setCertificates(SET certs) { + this.certificates = certs; + } + */ + + /** + * Returns true if the certificates field is present. + */ + public boolean hasCertificates() { + return (certificates!=null); + } + + /** + * Returns the crls field, which contains a SET of certificate + * revocation lists represented by ANYs (com.netscape.jss.asn1.ANY). + * + */ + public SET getCrls() { + return crls; + } + + /** + * Low-level function to set the crls. + * @param certs May be null to signify that the crls + * field is not present. + public void setCrls(SET crls) { + this.crls = crls; + } + */ + + /** + * Returns true if the crls field is present. + */ + public boolean hasCrls() { + return (crls != null); + } + + /** + * Returns the signerInfos field, which is a SET of + * com.netscape.jss.pkcs7.SignerInfo. + */ + public SET getSignerInfos() { + return signerInfos; + } + + /** + * Low-level function to set the SignerInfos. + * @param signerInfos Must not be null. + public void setSignerInfos(SET signerInfos) { + verifyNotNull(sis); + this.signerInfos = signerInfos; + } + */ + + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + // Constructors + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + + /** + * Low-level constructor that merely initializes all fields to null. + private SignedData() {} + */ + + /** + * Create a SignedData ASN1 object. Both certificates and crls + * are optional. If you pass in a null for either value, that + * parameter will not get written in the sequence. + * + * @param digestAlgorithms A SET of zero or more + * algorithm identifiers. The purpose of this item is to list + * the digest algorithms used by the various signers to digest + * the signed content. This field will also be updated by + * the addSigner method. If all the signers are added + * with addSigner, it is not necessary to list + * the digest algorithms here. + *

If null is passed in, the + * digestAlgorithms field will be initialized + * with an empty SET. + * @param contentInfo The content that is being signed. This parameter + * may not be null. However, the content + * field of the contentInfo may be omitted, in which case the + * signatures contained in the SignerInfo structures + * are presumed to be on externally-supplied data. + * @param certificates A SET of com.netscape.jss.pkix.cert.Certificate, + * the certificates + * containing the public keys used to sign the content. It may + * also contain elements of the CA chain extending from the leaf + * certificates. It is not necessary to include the CA chain, or + * indeed to include any certificates, if the certificates are + * expected to already be possessed by the recipient. The recipient + * can use the issuer and serial number in the SignerInfo structure + * to search for the necessary certificates. If this parameter is + * null, the certificates field will be + * omitted. + * @param crls A SET of ASN1Values, which should encode to the ASN1 type + * CertificateRevocationList. This implementation does + * not interpret crls. If this parameter is null, + * the crls field will be omitted. + * @param signerInfos SignerInfo structures containing signatures + * of the content. Additional signerInfos can be added with + * the addSigner method. If this parameter is + * null, the field will be initialized with an + * empty SET. + */ + public SignedData( SET digestAlgorithms, + ContentInfo contentInfo, SET certificates, + SET crls, SET signerInfos) { + + version = VERSION; + + if(digestAlgorithms == null ) { + this.digestAlgorithms = new SET(); + } else { + this.digestAlgorithms = digestAlgorithms; + } + + verifyNotNull(contentInfo); + this.contentInfo = contentInfo; + + // certificates may be null + this.certificates = certificates; + + // crls may be null + this.crls = crls; + + if(signerInfos == null) { + this.signerInfos = new SET(); + } else { + this.signerInfos = signerInfos; + } + } + + /** + * Constructor for creating a SignedData from its encoding. + */ + SignedData( INTEGER version, + SET digestAlgorithms, + ContentInfo contentInfo, + SET certificates, + SET crls, + SET signerInfos ) + { + + verifyNotNull(version); + this.version = version; + + verifyNotNull(digestAlgorithms); + this.digestAlgorithms = digestAlgorithms; + + verifyNotNull(contentInfo); + this.contentInfo = contentInfo; + + // certificates may be null + this.certificates = certificates; + + // crls may be null + this.crls = crls; + + verifyNotNull(signerInfos); + this.signerInfos = signerInfos; + } + + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + // Cryptographic functions + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + + + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + // DER encoding + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + + static final Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + encode(getTag(),ostream); + } + + public void encode(Tag tag, OutputStream ostream) throws IOException { + SEQUENCE sequence = new SEQUENCE(); + + sequence.addElement(version); + sequence.addElement(digestAlgorithms); + sequence.addElement(contentInfo); + if( certificates != null ) { + sequence.addElement( new Tag(0), certificates ); + } + if( crls != null ) { + sequence.addElement( new Tag(1), crls ); + } + sequence.addElement(signerInfos); + + sequence.encode(tag,ostream); + } + + + /** + * A template file for decoding a SignedData blob + * + */ + public static class Template implements ASN1Template { + private SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + + // version + seqt.addElement(INTEGER.getTemplate()); + + // digestAlgorithms + seqt.addElement(new SET.OF_Template( + AlgorithmIdentifier.getTemplate())); + + // content info + seqt.addElement(ContentInfo.getTemplate()); + + // [0] IMPLICIT certificates OPTIONAL + seqt.addOptionalElement( + new Tag(0), + new SET.OF_Template(Certificate.getTemplate())); + + // [1] IMPLICIT CertificateRevocationLists OPTIONAL + seqt.addOptionalElement( + new Tag(1), + new SET.OF_Template(ANY.getTemplate())); + + // signerInfos + seqt.addElement(new SET.OF_Template(SignerInfo.getTemplate())); + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws IOException, InvalidBERException + { + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); + Assert.assert(seq.size() == 6); + + return new SignedData( + (INTEGER) seq.elementAt(0), + (SET) seq.elementAt(1), + (ContentInfo) seq.elementAt(2), + (SET) seq.elementAt(3), + (SET) seq.elementAt(4), + (SET) seq.elementAt(5) + ); + } + } // end of template + +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs7/SignerInfo.java b/mozilla/security/jss/org/mozilla/jss/pkcs7/SignerInfo.java new file mode 100644 index 00000000000..24a680add6d --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs7/SignerInfo.java @@ -0,0 +1,845 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs7; + +import java.io.*; +import com.netscape.jss.asn1.*; +import com.netscape.jss.util.Assert; +import com.netscape.jss.pkix.primitive.*; +import com.netscape.jss.crypto.*; +import java.util.Vector; +import java.math.BigInteger; +import java.io.ByteArrayInputStream; +import java.security.InvalidKeyException; +import java.security.SignatureException; +import java.security.NoSuchAlgorithmException; +import java.security.MessageDigest; +import com.netscape.jss.crypto.*; +import com.netscape.jss.*; +import java.security.PublicKey; + +/* + * The high-level interface takes care of all + * the logic and cryptography. If you need to use the low-level interface, + * please let us know what you are using it for. Perhaps it should be part + * of the high-level interface. + */ + +/** + * A PKCS #7 SignerInfo. + */ +public class SignerInfo implements ASN1Value { + + //////////////////////////////////////////////// + // PKCS #9 attributes + //////////////////////////////////////////////// + private static final OBJECT_IDENTIFIER + CONTENT_TYPE = OBJECT_IDENTIFIER.PKCS.subBranch(9).subBranch(3); + private static final OBJECT_IDENTIFIER + MESSAGE_DIGEST = OBJECT_IDENTIFIER.PKCS.subBranch(9).subBranch(4); + + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + // Members + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + + private INTEGER version; + private IssuerAndSerialNumber issuerAndSerialNumber; + private AlgorithmIdentifier digestAlgorithm; + private SET authenticatedAttributes; // [0] OPTIONAL + private AlgorithmIdentifier digestEncryptionAlgorithm; + private OCTET_STRING encryptedDigest; + private SET unauthenticatedAttributes; // [1] OPTIONAL + + // we only do version 1 of PKCS #7 + private static final INTEGER VERSION = new INTEGER(1); + + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + // Accessor methods + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + + /** + * Retrieves the version number of this SignerInfo. + */ + public INTEGER getVersion() { + return version; + } + + /** + * Low-level method to set the version. + * It is not normally necessary to call this. Use it at your own risk. + public void setVersion(INTEGER version) { + this.version = version; + } + */ + + /** + * Retrieves the issuer and serial number of the certificate whose + * private key was used to sign the SignerInfo. + */ + public IssuerAndSerialNumber getIssuerAndSerialNumber() { + return issuerAndSerialNumber; + } + + /** + * Low-level method to set the issuerAndSerialNumber. + * It is not normally necessary to call this. Use it at your own risk. + public void setIssuerAndSerialNumber( IssuerAndSerialNumber iasn ) { + this.issuerAndSerialNumber = iasn; + } + */ + + /** + * Retrieves the DigestAlgorithm used in this SignerInfo. + * + * @exception NoSuchAlgorithm If the algorithm is not recognized by JSS. + */ + public DigestAlgorithm getDigestAlgorithm() + throws NoSuchAlgorithmException + { + return DigestAlgorithm.fromOID( digestAlgorithm.getOID() ); + } + + + /** + * Retrieves the DigestAlgorithmIdentifier used in this SignerInfo. + */ + public AlgorithmIdentifier getDigestAlgorithmIdentifer() { + return digestAlgorithm; + } + + /** + * Low-level method to set the digest AlgorithmIdentifier. + * It is not normally necessary to call this. Use it at your own risk. + public void setDigestAlgorithmIdentifier(AlgorithmIdentifier algid) { + this.digestAlgorithm = algid; + } + */ + + /** + * Retrieves the authenticated attributes, if they exist. + * + */ + public SET getAuthenticatedAttributes() { + return authenticatedAttributes; + } + + /** + * Returns true if the authenticatedAttributes field is present. + */ + public boolean hasAuthenticatedAttributes() { + return (authenticatedAttributes != null); + } + + /** + * Low-level method to set the authenticatedAttributes field. + * It is not normally necessary to call this. Use it at your own risk. + public void setAuthenticatedAttributes(SET authAttrib) { + this.authenticatedAttributes = authAttrib; + } + */ + + /** + * Returns the raw signature (digest encryption) algorithm used in this + * SignerInfo. + * + * @exception NoSuchAlgorithmException If the algorithm is not recognized + * by JSS. + */ + public SignatureAlgorithm getDigestEncryptionAlgorithm() + throws NoSuchAlgorithmException + { + return SignatureAlgorithm.fromOID( + digestEncryptionAlgorithm.getOID() ); + } + + /** + * Returns the DigestEncryptionAlgorithmIdentifier used in this SignerInfo. + */ + public AlgorithmIdentifier getDigestEncryptionAlgorithmIdentifier() { + return digestEncryptionAlgorithm; + } + + /** + * Low-level method to set the digestEncryptionAlgorithm field. + * It is not normally necessary to call this. Use it at your own risk. + public void + setDigestEncryptionAlgorithmIdentifier(AlgorithmIdentifier algid) { + this.digestEncryptionAlgorithm= algid; + } + */ + + /** + * Retrieves the encrypted digest. + */ + public byte[] getEncryptedDigest() { + return encryptedDigest.toByteArray(); + } + + /** + * Low-level method to set the encryptedDigest field. + * It is not normally necessary to call this. Use it at your own risk. + public void setEncryptedDigest(byte[] ed) { + this.encryptedDigest = new OCTET_STRING(ed); + } + */ + + /** + * Retrieves the unauthenticated attributes, if they exist. + * + */ + public SET getUnauthenticatedAttributes() { + return unauthenticatedAttributes; + } + + /** + * Returns true if the unauthenticatedAttributes field is present. + */ + public boolean hasUnauthenticatedAttributes() { + return (unauthenticatedAttributes!=null); + } + + /** + * Low-level method to set the unauthenticatedAttributes field. + * It is not normally necessary to call this. Use it at your own risk. + public void setUnauthenticatedAttributes(SET unauthAttrib) { + this.unauthenticatedAttributes = unauthAttrib; + } + */ + + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + // Constructors + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + + /** + * Low-level default constructor. All fields are initialized to null. + * Before this SignerInfo can be processed or used in any way, all of + * the fields except authenticatedAttributes and + * unauthenticatedAttributes must be non-null. + *

It is not normally necessary to call this constructor.Use it at + * your own risk. + public SignerInfo() { + } + */ + + /** + * A constructor for creating a new SignerInfo from scratch. + * + * @param issuerAndSerialNumber The issuer and serial number of the + * certificate from which the public key was extracted to create + * this SignerInfo. + * @param signingAlg The algorithm to be used to sign the content. + * This should be a composite algorithm, such as + * RSASignatureWithMD5Digest, instead of a raw algorithm, such as + * RSASignature. + * Note that the digest portion of this algorithm must be the same + * algorithm as was used to digest the message content. + * @param authenticatedAttributes An optional set of Attributes, which + * will be signed along with the message content. This parameter may + * be null, or the SET may be empty. DO NOT insert + * the PKCS #9 content-type or message-digest attributes. They will + * be added automatically if they are necessary. + * @param unauthenticatedAttributes An optional set of Attributes, which + * will be included in the SignerInfo but not signed. This parameter + * may be null, or the SET may be empty. + * @param messageDigest The digest of the message contents. The digest + * must have been created with the digest algorithm specified by + * the signingAlg parameter. + * @param contentType The type of the ContentInfo that is being signed. + * If it is not data, then the PKCS #9 attributes + * content-type and message-digest will be automatically computed and + * added to the authenticated attributes. + */ + public SignerInfo( IssuerAndSerialNumber issuerAndSerialNumber, + SET authenticatedAttributes, + SET unauthenticatedAttributes, + OBJECT_IDENTIFIER contentType, + byte[] messageDigest, + SignatureAlgorithm signingAlg, + PrivateKey signingKey ) + throws InvalidKeyException, NoSuchAlgorithmException, + CryptoManager.NotInitializedException, SignatureException, + TokenException + { + version = VERSION; + this.issuerAndSerialNumber = issuerAndSerialNumber; + this.digestAlgorithm = + new AlgorithmIdentifier(signingAlg.getDigestAlg().toOID(),null); + + // if content-type is not data, add message-digest and content-type + // to authenticated attributes. + if( ! contentType.equals(ContentInfo.DATA) ) { + if( authenticatedAttributes == null ) { + authenticatedAttributes = new SET(); + } + Attribute attrib = new Attribute(CONTENT_TYPE, ContentInfo.DATA); + authenticatedAttributes.addElement(attrib); + attrib = new Attribute(MESSAGE_DIGEST, + new OCTET_STRING(messageDigest) ); + authenticatedAttributes.addElement(attrib); + } + + digestEncryptionAlgorithm = new AlgorithmIdentifier( + signingAlg.getRawAlg().toOID(),null ); + + + if( authenticatedAttributes != null ) + { + Assert.assert( authenticatedAttributes.size() >= 2 ); + this.authenticatedAttributes = authenticatedAttributes; + } + + ////////////////////////////////////////////////// + // create encrypted digest (signature) + ////////////////////////////////////////////////// + + // compute the digest + byte[] digest=null; + DigestAlgorithm digestAlg = signingAlg.getDigestAlg(); + if( authenticatedAttributes == null ) { + // just use the message digest of the content + digest = messageDigest; + } else { + // digest the contents octets of the authenticated attributes + byte[] enc = ASN1Util.encode(authenticatedAttributes); + MessageDigest md = + MessageDigest.getInstance(digestAlg.toString()); + digest = md.digest( enc ); + } + + // put the digest in a DigestInfo + SEQUENCE digestInfo = new SEQUENCE(); + AlgorithmIdentifier digestAlgId = + new AlgorithmIdentifier( digestAlg.toOID(),null ); + digestInfo.addElement( digestAlgId ); + digestInfo.addElement( new OCTET_STRING( digest ) ); + byte[] toBeSigned = ASN1Util.encode(digestInfo); + + // encrypt the DER-encoded DigestInfo with the private key + CryptoToken token = signingKey.getOwningToken(); + Signature sig; + sig = token.getSignatureContext( signingAlg.getRawAlg() ); + sig.initSign(signingKey); + sig.update(toBeSigned); + encryptedDigest = new OCTET_STRING(sig.sign()); + + if( unauthenticatedAttributes != null ) + { + this.unauthenticatedAttributes = unauthenticatedAttributes; + } + } + + /** + * A constructor for creating a new SignerInfo from its decoding. + */ + SignerInfo( INTEGER version, + IssuerAndSerialNumber issuerAndSerialNumber, + AlgorithmIdentifier digestAlgorithm, + SET authenticatedAttributes, + AlgorithmIdentifier digestEncryptionAlgorithm, + byte[] encryptedDigest, + SET unauthenticatedAttributes) + { + this.version = version; + this.issuerAndSerialNumber = issuerAndSerialNumber; + this.digestAlgorithm = digestAlgorithm; + this.authenticatedAttributes = authenticatedAttributes; + this.digestEncryptionAlgorithm = digestEncryptionAlgorithm; + this.encryptedDigest = new OCTET_STRING(encryptedDigest); + this.unauthenticatedAttributes = unauthenticatedAttributes; + } + + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + // Verification + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + + /** + * Verifies that this SignerInfo contains a valid signature of the + * given message digest. If any authenticated attributes are present, + * they are also validated. The verification algorithm is as follows:

    + *

    Note that this does not verify the validity of the + * the certificate itself, only the signature. + * + *

  • If no authenticated attributes are present, the content type is + * verified to be data. Then it is verified that the message + * digest passed + * in, when encrypted with the given public key, matches the encrypted + * digest in the SignerInfo. + * + *
  • If authenticated attributes are present, + * two particular attributes must be present:
      + *
    • PKCS #9 Content-Type, the type of content that is being signed. + * This must match the contentType parameter. + *
    • PKCS #9 Message-Digest, the digest of the content that is being + * signed. This must match the messageDigest parameter. + *
    + * After these two attributes are verified to be both present and correct, + * the encryptedDigest field of the SignerInfo is verified to be the + * signature of the contents octets of the DER encoding of the + * authenticatedAttributes field. + * + *
+ * + * @param messageDigest The hash of the content that is signed by this + * SignerInfo. + * @param contentType The type of the content that is signed by this + * SignerInfo. + * @param pubkey The public key to use to verify the signature. + * @exception NoSuchObjectException If no certificate matching the + * the issuer name and serial number can be found. + */ + public void verify(byte[] messageDigest, OBJECT_IDENTIFIER contentType) + throws CryptoManager.NotInitializedException, NoSuchAlgorithmException, + InvalidKeyException, TokenException, SignatureException, + ObjectNotFoundException + { + CryptoManager cm = CryptoManager.getInstance(); + X509Certificate cert = cm.findCertByIssuerAndSerialNumber( + ASN1Util.encode(issuerAndSerialNumber.getIssuer()), + issuerAndSerialNumber.getSerialNumber() ); + verify(messageDigest, contentType, cert.getPublicKey()); + } + + + /** + * Verifies that this SignerInfo contains a valid signature of the + * given message digest. If any authenticated attributes are present, + * they are also validated. The verification algorithm is as follows:
    + * + *
  • If no authenticated attributes are present, the content type is + * verified to be data. Then it is verified that the message + * digest passed + * in, when encrypted with the given public key, matches the encrypted + * digest in the SignerInfo. + * + *
  • If authenticated attributes are present, + * two particular attributes must be present:
      + *
    • PKCS #9 Content-Type, the type of content that is being signed. + * This must match the contentType parameter. + *
    • PKCS #9 Message-Digest, the digest of the content that is being + * signed. This must match the messageDigest parameter. + *
    + * After these two attributes are verified to be both present and correct, + * the encryptedDigest field of the SignerInfo is verified to be the + * signature of the contents octets of the DER encoding of the + * authenticatedAttributes field. + * + *
+ * + * @param messageDigest The hash of the content that is signed by this + * SignerInfo. + * @param contentType The type of the content that is signed by this + * SignerInfo. + * @param pubkey The public key to use to verify the signature. + */ + public void verify(byte[] messageDigest, OBJECT_IDENTIFIER contentType, + PublicKey pubkey) + throws CryptoManager.NotInitializedException, NoSuchAlgorithmException, + InvalidKeyException, TokenException, SignatureException + { + + if( authenticatedAttributes == null ) { + verifyWithoutAuthenticatedAttributes(messageDigest, contentType, + pubkey); + } else { + verifyWithAuthenticatedAttributes(messageDigest, contentType, + pubkey); + } + } + + /** + * Verifies that the message digest passed in, when encrypted with the + * given public key, matches the encrypted digest in the SignerInfo. + */ + private void verifyWithoutAuthenticatedAttributes + (byte[] messageDigest, OBJECT_IDENTIFIER contentType, + PublicKey pubkey) + throws CryptoManager.NotInitializedException, NoSuchAlgorithmException, + InvalidKeyException, TokenException, SignatureException + { + if( ! contentType.equals(ContentInfo.DATA) ) { + // only data can be signed this way. Everything else has + // to go into authenticatedAttributes. + throw new SignatureException( + "Content-Type is not DATA, but there are"+ + " no authenticated attributes"); + } + + // create DigestInfo structure + SEQUENCE digestInfo = new SEQUENCE(); + digestInfo.addElement( digestAlgorithm.getOID() ); + digestInfo.addElement( new OCTET_STRING(messageDigest) ); + byte[] toBeVerified = ASN1Util.encode(digestInfo); + + CryptoToken token = CryptoManager.getInstance() + .getInternalCryptoToken(); + SignatureAlgorithm sigAlg = + SignatureAlgorithm.fromOID( + digestEncryptionAlgorithm.getOID() + ); + Signature sig = token.getSignatureContext(sigAlg); + sig.initVerify(pubkey); + sig.update(toBeVerified); + if( sig.verify(encryptedDigest.toByteArray()) ) { + return; // success + } else { + throw new SignatureException( + "Encrypted message digest parameter does not "+ + "match encrypted digest in SignerInfo"); + } + } + + + /** + * Verifies a SignerInfo with authenticated attributes. If authenticated + * attributes are present, then two particular attributes must + * be present:
    + *
  • PKCS #9 Content-Type, the type of content that is being signed. + * This must match the contentType parameter. + *
  • PKCS #9 Message-Digest, the digest of the content that is being + * signed. This must match the messageDigest parameter. + *
+ * After these two attributes are verified to be both present and correct, + * the encryptedDigest field of the SignerInfo is verified to be the + * signature of the contents octets of the DER encoding of the + * authenticatedAttributes field. + */ + private void verifyWithAuthenticatedAttributes + (byte[] messageDigest, OBJECT_IDENTIFIER contentType, + PublicKey pubkey) + throws CryptoManager.NotInitializedException, NoSuchAlgorithmException, + InvalidKeyException, TokenException, SignatureException + { + + int numAttrib = authenticatedAttributes.size(); + + if(numAttrib < 2) { + throw new SignatureException( + "At least two authenticated attributes must be present:"+ + " content-type and message-digest"); + } + + // go through the authenticated attributes, verifying the + // interesting ones + boolean foundContentType = false; + boolean foundMessageDigest = false; + for( int i = 0; i < numAttrib; i++ ) { + + if( ! (authenticatedAttributes.elementAt(i) instanceof Attribute)) { + throw new SignatureException( + "Element of authenticatedAttributes is not an Attribute"); + } + + Attribute attrib = (Attribute) + authenticatedAttributes.elementAt(i); + + if( attrib.getType().equals(CONTENT_TYPE) ) { + // content-type. Compare with what was passed in. + + SET vals = attrib.getValues(); + if( vals.size() != 1 ) { + throw new SignatureException( + "Content-Type attribute "+ + " does not have exactly one value"); + } + + ASN1Value val = vals.elementAt(0); + OBJECT_IDENTIFIER ctype; + try { + if( val instanceof OBJECT_IDENTIFIER ) { + ctype = (OBJECT_IDENTIFIER) val; + } else if( val instanceof ANY ) { + ctype = (OBJECT_IDENTIFIER) ((ANY)val).decodeWith( + OBJECT_IDENTIFIER.getTemplate() ); + } else { + // what the heck is it? not what it's supposed to be + throw new InvalidBERException( + "Content-Type authenticated attribute has unexpected"+ + " content type"); + } + } catch( InvalidBERException e ) { + throw new SignatureException( + "Content-Type authenticated attribute does not have "+ + "OBJECT IDENTIFIER value"); + } + + // compare the content type in the attribute to the + // contentType parameter + if( ! ctype.equals( contentType ) ) { + throw new SignatureException( + "Content-type in authenticated attributes does not "+ + "match content-type being verified"); + } + + // content type is A-OK + foundContentType = true; + + } else if( attrib.getType().equals(MESSAGE_DIGEST) ) { + + SET vals = attrib.getValues(); + if( vals.size() != 1 ) { + throw new SignatureException( + "Message-digest attribute does not have"+ + " exactly one value"); + } + + ASN1Value val = vals.elementAt(0); + byte[] mdigest; + try { + if( val instanceof OCTET_STRING ) { + mdigest = ((OCTET_STRING)val).toByteArray(); + } else if( val instanceof ANY ) { + OCTET_STRING os; + os = (OCTET_STRING) ((ANY)val).decodeWith( + OCTET_STRING.getTemplate() ); + mdigest = os.toByteArray(); + } else { + // what the heck is it? not what it's supposed to be + throw new InvalidBERException( + "Content-Type authenticated attribute has unexpected"+ + " content type"); + } + } catch( InvalidBERException e ) { + throw new SignatureException( + "Message-digest attribute does not"+ + " have OCTET STRING value"); + } + + // compare the message digest in the attribute to the + // message digest being verified + if( ! byteArraysAreSame(mdigest, messageDigest) ) { + throw new SignatureException( + "Message-digest attribute does not"+ + " match message digest being verified"); + } + + // message digest is A-OK + foundMessageDigest = true; + } + + // we don't care about other attributes + + } + + if( !foundContentType ) { + throw new SignatureException( + "Authenticated attributes does not contain"+ + " PKCS #9 content-type attribute"); + } + + if( !foundMessageDigest ) { + throw new SignatureException( + "Authenticate attributes does not contain"+ + " PKCS #9 message-digest attribute"); + } + + // All the authenticated attributes are present and correct. + // Now verify the signature. + CryptoToken token = + CryptoManager.getInstance().getInternalCryptoToken(); + Signature sig = token.getSignatureContext( + SignatureAlgorithm.fromOID( + digestEncryptionAlgorithm.getOID() ) + ); + sig.initVerify(pubkey); + + // verify the contents octets of the DER encoded authenticated attribs + byte[] toBeDigested; + try { + byte[] encodedAuthAttrib = ASN1Util.encode(authenticatedAttributes); + ANY any = (ANY) + ASN1Util.decode( ANY.getTemplate(), encodedAuthAttrib ); + toBeDigested = any.getContents(); + } catch(InvalidBERException e ) { + Assert.notReached("Unable to decode authenticated attributes"); + toBeDigested = null; + } + + MessageDigest md = MessageDigest.getInstance( + DigestAlgorithm.fromOID(digestAlgorithm.getOID()).toString() ); + byte[] digest = md.digest(toBeDigested); + + + // create DigestInfo structure + SEQUENCE digestInfo = new SEQUENCE(); + digestInfo.addElement( digestAlgorithm.getOID() ); + digestInfo.addElement( new OCTET_STRING(digest) ); + byte[] toBeVerified = ASN1Util.encode(digestInfo); + + sig.update( toBeVerified ); + + if( ! sig.verify(encryptedDigest.toByteArray()) ) { + // signature is invalid + throw new SignatureException("encryptedDigest was not the correct"+ + " signature of the contents octets of the DER-encoded"+ + " authenticated attributes"); + } + + // SUCCESSFULLY VERIFIED + + } + + /** + * Compares two non-null byte arrays. Returns true if they are identical, + * false otherwise. + */ + private static boolean byteArraysAreSame(byte[] left, byte[] right) { + + Assert.assert(left!=null && right!=null); + + if( left.length != right.length ) { + return false; + } + + for(int i = 0 ; i < left.length ; i++ ) { + if( left[i] != right[i] ) { + return false; + } + } + + return true; + } + + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + // DER-encoding + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + + private static final Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + encode(getTag(),ostream); + } + + public void encode(Tag tag, OutputStream ostream) throws IOException { + SEQUENCE sequence = new SEQUENCE(); + + sequence.addElement( version ); + sequence.addElement( issuerAndSerialNumber ); + sequence.addElement( digestAlgorithm ); + if( authenticatedAttributes != null ) { + sequence.addElement( new Tag(0), authenticatedAttributes ); + } + sequence.addElement( digestEncryptionAlgorithm ); + sequence.addElement( encryptedDigest ); + if( unauthenticatedAttributes != null ) { + sequence.addElement( new Tag(1), unauthenticatedAttributes ); + } + + sequence.encode(tag,ostream); + } + + public static Template getTemplate() { + return templateInstance; + } + private static Template templateInstance = new Template(); + + /** + * A template for decoding a SignerInfo blob + * + */ + public static class Template implements ASN1Template { + + SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + + // serial number + seqt.addElement(INTEGER.getTemplate()); // vn + + // issuerAndSerialNumber + seqt.addElement(IssuerAndSerialNumber.getTemplate()); // issuer + sernum + + // digestAlgorithm + seqt.addElement(AlgorithmIdentifier.getTemplate()); // digest alg + + // authenticatedAttributes + seqt.addOptionalElement( + new Tag(0), + new SET.OF_Template(Attribute.getTemplate())); + + // digestEncryptionAlgorithm + seqt.addElement(AlgorithmIdentifier.getTemplate()); // dig encr alg + + // encryptedDigest + seqt.addElement(OCTET_STRING.getTemplate()); // encr digest + + // unauthenticated attributes + seqt.addOptionalElement( + new Tag(1), + new SET.OF_Template(Attribute.getTemplate())); + + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + return decode(TAG,istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws IOException, InvalidBERException + { + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag,istream); + Assert.assert(seq.size() == 7); + + return new SignerInfo( + (INTEGER) seq.elementAt(0), + (IssuerAndSerialNumber) seq.elementAt(1), + (AlgorithmIdentifier) seq.elementAt(2), + (SET) seq.elementAt(3), + (AlgorithmIdentifier) seq.elementAt(4), + ((OCTET_STRING) seq.elementAt(5)).toByteArray(), + (SET) seq.elementAt(6) + ); + } + } // end of template + +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs7/manifest.mn b/mozilla/security/jss/org/mozilla/jss/pkcs7/manifest.mn new file mode 100644 index 00000000000..fafd69d65d3 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs7/manifest.mn @@ -0,0 +1,72 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +CORE_DEPTH = ../../../../.. + +MODULE = ninja + +NS_USE_JDK = 1 + + +PACKAGE = com/netscape/jss/pkcs7 + + +CLASSES = \ + ContentInfo \ + DigestedData \ + DigestInfo \ + EncryptedContentInfo \ + EncryptedData \ + EnvelopedData \ + IssuerAndSerialNumber \ + RecipientInfo \ + SignedAndEnvelopedData \ + SignedData \ + SignerInfo \ + $(NULL) + + + +JSRCS = \ + ContentInfo.java \ + DigestedData.java \ + DigestInfo.java \ + EncryptedContentInfo.java \ + EncryptedData.java \ + EnvelopedData.java \ + IssuerAndSerialNumber.java \ + RecipientInfo.java \ + SignedAndEnvelopedData.java \ + SignedData.java \ + SignerInfo.java \ + $(NULL) diff --git a/mozilla/security/jss/org/mozilla/jss/pkcs7/package.html b/mozilla/security/jss/org/mozilla/jss/pkcs7/package.html new file mode 100644 index 00000000000..e08adfc82eb --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkcs7/package.html @@ -0,0 +1,37 @@ + + + +Creating and interpeting PKCS #7 blobs. + + diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/Makefile b/mozilla/security/jss/org/mozilla/jss/pkix/Makefile new file mode 100644 index 00000000000..5ad58e0eda2 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/Makefile @@ -0,0 +1,76 @@ +#! gmake +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +####################################################################### +# (1) Include initial platform-independent assignments (MANDATORY). # +####################################################################### + +include manifest.mn + +####################################################################### +# (2) Include "global" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/config.mk + +####################################################################### +# (3) Include "component" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/$(MODULE)/config/config.mk + +####################################################################### +# (4) Include "local" platform-dependent assignments (OPTIONAL). # +####################################################################### + +#include config.mk + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### + + + diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cert/Certificate.java b/mozilla/security/jss/org/mozilla/jss/pkix/cert/Certificate.java new file mode 100644 index 00000000000..499a29fcc28 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cert/Certificate.java @@ -0,0 +1,354 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkix.cert; + +import com.netscape.jss.asn1.*; +import com.netscape.jss.pkix.primitive.*; +import com.netscape.jss.crypto.*; +import com.netscape.jss.CryptoManager; +import java.security.cert.CertificateException; +import java.security.NoSuchAlgorithmException; +import java.security.InvalidKeyException; +import java.security.SignatureException; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; +import java.security.PublicKey; +import java.security.KeyPair; +import java.util.Date; +import java.util.Calendar; + +import java.io.BufferedInputStream; +import java.io.FileInputStream; + +/** + * An X.509 signed certificate. + */ +public class Certificate implements ASN1Value { + + private CertificateInfo info; + private byte[] infoEncoding; + private byte[] signature; + private AlgorithmIdentifier algId; + SEQUENCE sequence; + + private Certificate() { } + + Certificate(CertificateInfo info, byte[] infoEncoding, + AlgorithmIdentifier algId, byte[] signature) throws IOException + { + this.info = info; + this.infoEncoding = infoEncoding; + this.algId = algId; + this.signature = signature; + + // bundle everything into a SEQUENCE + sequence = new SEQUENCE(); + sequence.addElement( info ); + sequence.addElement( algId ); + sequence.addElement( new BIT_STRING( signature, 0 ) ); + } + + /** + * Creates and signs an X.509 Certificate. + * @param info A CertificateInfo (TBSCertificate), which specifies + * the actual information of the certificate. + * @param privKey The private key with which to sign the certificat. + * @param signingAlg The algorithm to use to sign the certificate. + * It must match the algorithm specified in the CertificateInfo. + * @exception IOException If an error occurred while encoding the + * certificate. + * @exception CryptoManager.NotInitializedException Because this + * operation involves cryptography (signing), CryptoManager must + * be initialized before calling it. + * @exception TokenException If an error occurs on a PKCS #11 token. + * @exception NoSuchAlgorithmException If the OID for the signing algorithm + * cannot be located. + * @exception CertificateException If the signing algorithm specified + * as a parameter does not match the one in the certificate info. + * @exception InvalidKeyException If the key does not match the signing + * algorithm. + * @exception SignatureException If an error occurs while signing the + * certificate. + */ + public Certificate(CertificateInfo info, java.security.PrivateKey privKey, + SignatureAlgorithm signingAlg) + throws IOException, CryptoManager.NotInitializedException, + TokenException, NoSuchAlgorithmException, CertificateException, + InvalidKeyException, SignatureException + { + // make sure key is a Ninja private key + if( !(privKey instanceof PrivateKey) ) { + throw new InvalidKeyException("Private Key is does not belong to"+ + " this provider"); + } + PrivateKey priv = (PrivateKey)privKey; + + // create algId and compare to the one in the cert info + if(signingAlg.getSigningAlg() == SignatureAlgorithm.RSASignature) { + algId = new AlgorithmIdentifier( signingAlg.toOID(), null ); + } else { + algId = new AlgorithmIdentifier( signingAlg.toOID() ); + } + if( ! info.getSignatureAlgId().getOID().equals(algId.getOID()) ) { + throw new CertificateException("Signing Algorithm does not match"+ + " the one specified in the CertificateInfo"); + } + + // encode the cert info + this.info = info; + infoEncoding = ASN1Util.encode(info); + + // sign the info encoding + CryptoManager cm = CryptoManager.getInstance(); + CryptoToken token = priv.getOwningToken(); + Signature sig = token.getSignatureContext(signingAlg); + sig.initSign(priv); + sig.update(infoEncoding); + signature = sig.sign(); + + // bundle everything into a SEQUENCE + sequence = new SEQUENCE(); + sequence.addElement( info ); + sequence.addElement( algId ); + sequence.addElement( new BIT_STRING( signature, 0 ) ); + } + + /** + * Verifies the signature on this certificate. Does not indicate + * that the certificate is valid at any specific time. + */ + public void verify() + throws InvalidKeyException, CryptoManager.NotInitializedException, + NoSuchAlgorithmException, CertificateException, TokenException, + SignatureException, InvalidKeyFormatException + { + verify( info.getSubjectPublicKeyInfo().toPublicKey() ); + } + + /** + * Verifies the signature on this certificate, using the given public key. + * Does not indicate the certificate is valid at any specific time. + */ + public void verify(PublicKey key) + throws InvalidKeyException, CryptoManager.NotInitializedException, + NoSuchAlgorithmException, CertificateException, TokenException, + SignatureException + { + CryptoManager cm = CryptoManager.getInstance(); + verify(key, cm.getInternalCryptoToken()); + } + + /** + * Verifies the signature on this certificate, using the given public + * key and CryptoToken. Does not indicate the certificate is valid at + * any specific time. + */ + public void verify(PublicKey key, CryptoToken token) + throws NoSuchAlgorithmException, CertificateException, TokenException, + SignatureException, InvalidKeyException + { + Signature sig = token.getSignatureContext( + SignatureAlgorithm.fromOID( info.getSignatureAlgId().getOID() ) ); + + sig.initVerify(key); + sig.update(infoEncoding); + if( ! sig.verify(signature) ) { + throw new CertificateException("Signature is invalid"); + } + } + + + /** + * Returns the information (TBSCertificate) contained in this certificate. + */ + public CertificateInfo getInfo() { + return info; + } + + private static final Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + encode(TAG, ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + sequence.encode(implicitTag, ostream); + } + + private static final Template templateInstance = new Template(); + public static Template getTemplate() { + return templateInstance; + } + + public static class Template implements ASN1Template { + + private SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + //seqt.addElement( CertificateInfo.getTemplate() ); + seqt.addElement( new ANY.Template() ); + seqt.addElement( AlgorithmIdentifier.getTemplate() ); + seqt.addElement( BIT_STRING.getTemplate() ); + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws InvalidBERException, IOException + { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws InvalidBERException, IOException + { + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); + + ANY infoAny = (ANY)seq.elementAt(0); + byte[] infoEncoding = infoAny.getEncoded(); + CertificateInfo info = (CertificateInfo) infoAny.decodeWith( + CertificateInfo.getTemplate() ); + + // although signature is a bit string, all algorithms we use + // will produce an octet string. + BIT_STRING bs = (BIT_STRING) seq.elementAt(2); + if( bs.getPadCount() != 0 ) { + throw new InvalidBERException("signature does not fall into"+ + " an integral number of bytes"); + } + byte[] signature = bs.getBits(); + + return new Certificate( info, + infoEncoding, + (AlgorithmIdentifier) seq.elementAt(1), + signature + ); + } + } + + public static void main(String argv[]) { + + try { + + if(argv.length > 2 || argv.length < 1) { + System.out.println("Usage: Certificate []"); + System.exit(0); + } + + CryptoManager.initialize( argv[0]+"/secmod.db", argv[0]+"/key3.db", + argv[0]+"/cert7.db"); + CryptoManager cm = CryptoManager.getInstance(); + + // read in a cert + BufferedInputStream bis = new BufferedInputStream( + new FileInputStream(argv[1]) ); + + Certificate cert = (Certificate) + Certificate.getTemplate().decode(bis); + + CertificateInfo info = cert.getInfo(); + + info.print(System.out); + + //X509Certificate hardcore = cm.findCertByNickname("Hardcore"); + //PublicKey key = hardcore.getPublicKey(); + + cert.verify(); + System.out.println("verified"); + + FileOutputStream fos = new FileOutputStream("certinfo.der"); + info.encode(fos); + fos.close(); + + // make a new public key + CryptoToken token = cm.getInternalKeyStorageToken(); + KeyPairGenerator kpg = token.getKeyPairGenerator(KeyPairAlgorithm.RSA); + kpg.initialize(512); + System.out.println("Generating a new key pair..."); + KeyPair kp = kpg.genKeyPair(); + System.out.println("Generated key pair"); + + // set the certificate's public key + info.setSubjectPublicKeyInfo(kp.getPublic()); + + // increment serial number + int newSerial = info.getSerialNumber().intValue() + 1; + info.setSerialNumber( new INTEGER(newSerial) ); + + // make new Name + Name name = new Name(); + name.addCommonName("Stra\u00dfenverk\u00e4ufer 'R' Us"); + name.addCountryName("US"); + name.addOrganizationName("Some Corporation"); + name.addOrganizationalUnitName("some org unit?"); + name.addLocalityName("Silicon Valley"); + name.addStateOrProvinceName("California"); + info.setIssuer(name); + info.setSubject(name); + + // set validity + Calendar cal = Calendar.getInstance(); + cal.set(1997, Calendar.APRIL, 1); + info.setNotBefore( cal.getTime() ); + cal.set(2010, Calendar.APRIL, 1); + info.setNotAfter( cal.getTime() ); + + System.out.println("About to create a new cert..."); + // create a new cert from this certinfo + Certificate genCert = new Certificate(info, kp.getPrivate(), + SignatureAlgorithm.RSASignatureWithMD5Digest); + System.out.println("Created new cert"); + + genCert.verify(); + System.out.println("Cert verifies!"); + + fos = new FileOutputStream("gencert.der"); + genCert.encode(fos); + fos.close(); + + } catch( Exception e ) { + e.printStackTrace(); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cert/CertificateInfo.java b/mozilla/security/jss/org/mozilla/jss/pkix/cert/CertificateInfo.java new file mode 100644 index 00000000000..dee25dd145f --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cert/CertificateInfo.java @@ -0,0 +1,485 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkix.cert; + +import com.netscape.jss.asn1.*; +import com.netscape.jss.pkix.primitive.*; +import com.netscape.jss.util.*; +import java.security.cert.CertificateException; +import java.security.PublicKey; +import java.util.Calendar; +import java.util.Date; +import java.util.TimeZone; +import java.io.InputStream; +import java.io.PrintStream; +import java.io.OutputStream; +import java.io.IOException; + +/** + * A TBSCertificate (to-be-signed certificate), the actual information in + * a certificate apart from the signature. + */ +public class CertificateInfo implements ASN1Value { + + /** + * An X.509 Certificate version. + */ + public static class Version { + private Version() { } + private Version(int vers, String string) { + versionNumber = vers; + this.string = string; + } + + int versionNumber; + String string; + + public boolean equals(Object obj) { + if(obj == null || !(obj instanceof Version)) { + return false; + } + return ((Version)obj).versionNumber == versionNumber; + } + + public int getNumber() { + return versionNumber; + } + + /** + * Creates a version number from its numeric encoding. + */ + public static Version fromInt(int versionNum) + throws InvalidBERException + { + if( versionNum == 0 ) { + return v1; + } else if( versionNum == 1) { + return v2; + } else if( versionNum == 2) { + return v3; + } else { + throw new InvalidBERException("Unrecognized version number"); + } + } + + public String toString() { + return string; + } + + public static final Version v1 = new Version(0, "v1"); + public static final Version v2 = new Version(1, "v2"); + public static final Version v3 = new Version(2, "v3"); + } + public static final Version v1 = Version.v1; + public static final Version v2 = Version.v2; + public static final Version v3 = Version.v3; + + // the last year for using UTCTime + static final int UTCTIME_CUTOFF_YEAR = 2049; + + private Version version = v1; + private INTEGER serialNumber; + private AlgorithmIdentifier signatureAlgId; + private Name issuer; + private Date notBefore; + private Date notAfter; + private Name subject; + private SubjectPublicKeyInfo subjectPublicKeyInfo; + private BIT_STRING issuerUniqueIdentifier; // may be null + private BIT_STRING subjectUniqueIdentifier; // may be null + private SEQUENCE extensions; // if no extensions, size() == 0. Never null. + + + /** + * Creates a CertificateInfo with the required fields. + */ + public CertificateInfo(Version version, INTEGER serialNumber, + AlgorithmIdentifier signatureAlgId, Name issuer, Date notBefore, + Date notAfter, Name subject, SubjectPublicKeyInfo subjectPublicKeyInfo) + { + setVersion(version); + setSerialNumber(serialNumber); + setSignatureAlgId(signatureAlgId); + setIssuer(issuer); + setNotBefore(notBefore); + setNotAfter(notAfter); + setSubject(subject); + setSubjectPublicKeyInfo(subjectPublicKeyInfo); + extensions = new SEQUENCE(); + } + + public void setVersion(Version version) { + verifyNotNull(version); + this.version = version; + } + public Version getVersion() { + return version; + } + + public void setSerialNumber(INTEGER serialNumber) { + verifyNotNull(serialNumber); + this.serialNumber = serialNumber; + } + public INTEGER getSerialNumber() { + return serialNumber; + } + + public void setSignatureAlgId(AlgorithmIdentifier signatureAlgId) { + verifyNotNull(signatureAlgId); + this.signatureAlgId = signatureAlgId; + } + public AlgorithmIdentifier getSignatureAlgId() { + return signatureAlgId; + } + + public void setIssuer(Name issuer) { + verifyNotNull(issuer); + this.issuer = issuer; + } + public Name getIssuer() { + return issuer; + } + + public void setNotBefore(Date notBefore) { + verifyNotNull(notBefore); + this.notBefore = notBefore; + } + public Date getNotBefore() { + return notBefore; + } + + public void setNotAfter(Date notAfter) { + verifyNotNull(notAfter); + this.notAfter = notAfter; + } + public Date getNotAfter() { + return notAfter; + } + + public void setSubject(Name subject) { + verifyNotNull(subject); + this.subject = subject; + } + public Name getSubject() { + return subject; + } + + public void setSubjectPublicKeyInfo( + SubjectPublicKeyInfo subjectPublicKeyInfo) + { + verifyNotNull(subjectPublicKeyInfo); + this.subjectPublicKeyInfo = subjectPublicKeyInfo; + } + /** + * Extracts the SubjectPublicKeyInfo from the given public key and + * stores it in the CertificateInfo. + * + * @exception InvalidBERException If an error occurs decoding the + * the information extracted from the public key. + */ + public void setSubjectPublicKeyInfo( PublicKey pubk ) + throws InvalidBERException, IOException + { + verifyNotNull(pubk); + setSubjectPublicKeyInfo( new SubjectPublicKeyInfo(pubk) ); + } + public SubjectPublicKeyInfo getSubjectPublicKeyInfo() { + return subjectPublicKeyInfo; + } + + /** + * @exception CertificateException If the certificate is a v1 certificate. + */ + public void setIssuerUniqueIdentifier(BIT_STRING issuerUniqueIdentifier) + throws CertificateException + { + if(version==v1) { + throw new CertificateException("issuerUniqueIdentifier cannot"+ + " be specified for v1 certificate"); + } + verifyNotNull(issuerUniqueIdentifier); + this.issuerUniqueIdentifier = issuerUniqueIdentifier; + } + public boolean hasIssuerUniqueIdentifier() { + return (issuerUniqueIdentifier!=null); + } + /** + * Should only be called if this field is present. + */ + public BIT_STRING getIssuerUniqueIdentifier() { + Assert.assert(issuerUniqueIdentifier != null); + return issuerUniqueIdentifier; + } + + /** + * @exception CertificateException If the certificate is a v1 certificate. + */ + public void setSubjectUniqueIdentifier(BIT_STRING subjectUniqueIdentifier) + throws CertificateException + { + if(version==v1) { + throw new CertificateException("subjectUniqueIdentifier cannot"+ + " be specified for v1 certificate"); + } + verifyNotNull(subjectUniqueIdentifier); + this.subjectUniqueIdentifier = subjectUniqueIdentifier; + } + public boolean hasSubjectUniqueIdentifier() { + return (subjectUniqueIdentifier!=null); + } + public BIT_STRING getSubjectUniqueIdentifier() { + Assert.assert(subjectUniqueIdentifier != null); + return subjectUniqueIdentifier; + } + + public boolean hasExtensions() { + return extensions.size() > 0; + } + /** + * Returns the extensions of this certificate. The sequence may be + * empty, but this method will never return null. + */ + public SEQUENCE getExtensions() { + return extensions; + } + + /** + * @exception CertificateException If the certificate is not a v3 + * certificate. + */ + public void setExtensions(SEQUENCE extensions) throws CertificateException { + if(version != v3) { + throw new CertificateException("extensions can only be added to"+ + " v3 certificates"); + } + if( Debug.DEBUG ) { + int size = extensions.size(); + for(int i=0; i < size; i++) { + Assert.assert(extensions.elementAt(i) instanceof Extension); + } + } + verifyNotNull(extensions); + this.extensions = extensions; + } + + /** + * @exception CertificateException If the certificate is not a v3 + * certificate. + */ + public void addExtension(Extension extension) throws CertificateException { + if(version != v3) { + throw new CertificateException("extensions can only be added to"+ + " v3 certificates"); + } + extensions.addElement(extension); + } + + private void verifyNotNull(Object obj) { + if( obj == null ) { + throw new NullPointerException(); + } + } + + static final Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + encode(TAG, ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + SEQUENCE seq = new SEQUENCE(); + + if( version != v1 ) { + // v1 is the default + seq.addElement(new EXPLICIT( new Tag(0), + new INTEGER(version.getNumber()) ) ); + } + seq.addElement(serialNumber); + seq.addElement(signatureAlgId); + seq.addElement(issuer); + + SEQUENCE validity = new SEQUENCE(); + validity.addElement( encodeValidityDate(notBefore) ); + validity.addElement( encodeValidityDate(notAfter) ); + seq.addElement(validity); + + seq.addElement(subject); + seq.addElement(subjectPublicKeyInfo); + + if( issuerUniqueIdentifier != null ) { + seq.addElement(new Tag(1), issuerUniqueIdentifier); + } + + if( subjectUniqueIdentifier != null ) { + seq.addElement(new Tag(2), subjectUniqueIdentifier); + } + + if( extensions.size() > 0 ) { + seq.addElement(new EXPLICIT(new Tag(3), extensions) ); + } + + seq.encode(implicitTag, ostream); + } + + /** + * Returns the correct ASN1Value (UTCTime or GeneralizedTime) to represent + * the given certificate validity date. + */ + private static ASN1Value encodeValidityDate(Date d) { + Calendar cal = Calendar.getInstance( TimeZone.getTimeZone("GMT") ); + cal.setTime(d); + if( cal.get(Calendar.YEAR) <= UTCTIME_CUTOFF_YEAR) { + return new UTCTime(d); + } else { + return new GeneralizedTime(d); + } + } + + private static final Template templateInstance = new Template(); + public static Template getTemplate() { + return templateInstance; + } + + public void print(PrintStream ps) throws IOException, InvalidBERException { + ps.println("CertificateInfo:"); + ps.println("Version: "+version); + ps.println("Serial Number: "+serialNumber); + ps.println("Sig OID: "+signatureAlgId.getOID()); + ps.println("Issuer: "+issuer.getRFC1485()); + ps.println("Not Before: "+notBefore); + ps.println("Not After: "+notAfter); + ps.println("Subject: "+subject.getRFC1485()); + } + + /** + * Template class for decoding a CertificateInfo. + */ + public static class Template implements ASN1Template { + + SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + + EXPLICIT.Template versionTemp = EXPLICIT.getTemplate( new Tag(0), + INTEGER.getTemplate() ); + EXPLICIT defVersion = + new EXPLICIT(new Tag(0), new INTEGER(v1.getNumber()) ); + seqt.addElement( versionTemp, defVersion ); + seqt.addElement(INTEGER.getTemplate()); //serial number + seqt.addElement(AlgorithmIdentifier.getTemplate()); //signatureAlgId + seqt.addElement(Name.getTemplate()); // issuer + + // deal with validity + SEQUENCE.Template validity = new SEQUENCE.Template(); + CHOICE.Template timeChoice = CHOICE.getTemplate(); + timeChoice.addElement( UTCTime.getTemplate() ); + timeChoice.addElement( GeneralizedTime.getTemplate() ); + validity.addElement( timeChoice ); // notBefore + validity.addElement( timeChoice ); // notAfter + + seqt.addElement(validity); + seqt.addElement(Name.getTemplate()); //subject + seqt.addElement(SubjectPublicKeyInfo.getTemplate()); + seqt.addOptionalElement( new Tag(1), BIT_STRING.getTemplate() ); + seqt.addOptionalElement( new Tag(2), BIT_STRING.getTemplate() ); + + // deal with extensions + SEQUENCE.OF_Template extnTemp = + new SEQUENCE.OF_Template( Extension.getTemplate() ); + seqt.addOptionalElement( new EXPLICIT.Template( + new Tag(3), extnTemp) ); + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws InvalidBERException, IOException + { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws InvalidBERException, IOException + { + try { + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); + + EXPLICIT exp = (EXPLICIT) seq.elementAt(0); + Version version = Version.fromInt( + ((INTEGER)exp.getContent()).intValue() ); + + SEQUENCE validity = (SEQUENCE) seq.elementAt(4); + CHOICE choice = (CHOICE)validity.elementAt(0); + Date notBefore = ((TimeBase)choice.getValue()).toDate(); + choice = (CHOICE)validity.elementAt(1); + Date notAfter = ((TimeBase)choice.getValue()).toDate(); + + CertificateInfo cinfo = new CertificateInfo( + version, + (INTEGER) seq.elementAt(1), // serial num + (AlgorithmIdentifier) seq.elementAt(2), //sigAlgId + (Name) seq.elementAt(3), // issuer + notBefore, + notAfter, + (Name) seq.elementAt(5), // subject + (SubjectPublicKeyInfo) seq.elementAt(6) + ); + + if( seq.elementAt(7) != null ) { + cinfo.setIssuerUniqueIdentifier( (BIT_STRING)seq.elementAt(7) ); + } + if( seq.elementAt(8) != null ) { + cinfo.setSubjectUniqueIdentifier( (BIT_STRING)seq.elementAt(8)); + } + if( seq.elementAt(9) != null ) { + exp = (EXPLICIT)seq.elementAt(9); + cinfo.setExtensions( (SEQUENCE) exp.getContent() ); + } + + return cinfo; + + } catch( CertificateException e ) { + throw new InvalidBERException(e.getMessage()); + } + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cert/Extension.java b/mozilla/security/jss/org/mozilla/jss/pkix/cert/Extension.java new file mode 100644 index 00000000000..5890325c24c --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cert/Extension.java @@ -0,0 +1,131 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkix.cert; + +import com.netscape.jss.asn1.*; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; +import com.netscape.jss.util.Assert; + +public class Extension implements ASN1Value { + public static final Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + private OBJECT_IDENTIFIER extnId; + /** + * Returns the extension identifier. + */ + public OBJECT_IDENTIFIER getExtnId() { + return extnId; + } + + private boolean critical; + public boolean getCritical() { + return critical; + } + + private OCTET_STRING extnValue; + public OCTET_STRING getExtnValue() { + return extnValue; + } + + private Extension() { } + + public Extension( OBJECT_IDENTIFIER extnId, boolean critical, + OCTET_STRING extnValue ) + { + this.extnId = extnId; + this.critical = critical; + this.extnValue = extnValue; + } + + public void encode(OutputStream ostream) throws IOException { + encode(TAG, ostream); + } + + public void encode(Tag implicit, OutputStream ostream) throws IOException { + SEQUENCE seq = new SEQUENCE(); + + seq.addElement( extnId ); + if( critical == true ) { + // false is default, so we only code true + seq.addElement( new BOOLEAN(true) ); + } + seq.addElement( extnValue ); + + seq.encode(implicit, ostream); + } + + private static final Template templateInstance = new Template(); + public static Template getTemplate() { + return templateInstance; + } + + public static class Template implements ASN1Template { + + private SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + seqt.addElement( OBJECT_IDENTIFIER.getTemplate() ); + seqt.addElement( BOOLEAN.getTemplate(), new BOOLEAN(false) ); + seqt.addElement( OCTET_STRING.getTemplate() ); + } + + public boolean tagMatch(Tag t) { + return TAG.equals(t); + } + + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicit, InputStream istream) + throws IOException, InvalidBERException + { + SEQUENCE seq = (SEQUENCE) seqt.decode(implicit, istream); + + return new Extension( + (OBJECT_IDENTIFIER) seq.elementAt(0), + ((BOOLEAN) seq.elementAt(1)).toBoolean(), + (OCTET_STRING) seq.elementAt(2) + ); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cert/Makefile b/mozilla/security/jss/org/mozilla/jss/pkix/cert/Makefile new file mode 100644 index 00000000000..8e7b071acaf --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cert/Makefile @@ -0,0 +1,75 @@ +#! gmake +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +####################################################################### +# (1) Include initial platform-independent assignments (MANDATORY). # +####################################################################### + +include manifest.mn + +####################################################################### +# (2) Include "global" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/config.mk + +####################################################################### +# (3) Include "component" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/$(MODULE)/config/config.mk + + +####################################################################### +# (4) Include "local" platform-dependent assignments (OPTIONAL). # +####################################################################### +#include config.mk + + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### +#include rules.mk diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cert/SubjectKeyIdentifier.java b/mozilla/security/jss/org/mozilla/jss/pkix/cert/SubjectKeyIdentifier.java new file mode 100644 index 00000000000..60d22b644f0 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cert/SubjectKeyIdentifier.java @@ -0,0 +1,121 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkix.cert; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import com.netscape.jss.asn1.*; +import com.netscape.jss.util.Assert; + +/** + * Represent the Subject Key Identifier Extension. + * + * This extension, if present, provides a means of identifying the particular + * public key used in an application. This extension by default is marked + * non-critical. + * + *

Extensions are addiitonal attributes which can be inserted in a X509 + * v3 certificate. For example a "Driving License Certificate" could have + * the driving license number as a extension. + * + *

Extensions are represented as a sequence of the extension identifier + * (Object Identifier), a boolean flag stating whether the extension is to + * be treated as being critical and the extension value itself (this is again + * a DER encoding of the extension value). + * + * @author Michelle Zhao + * @version 1.0 + * @see Extension + */ +public class SubjectKeyIdentifier extends Extension { + + /////////////////////////////////////////////////////////////////////// + // Members + /////////////////////////////////////////////////////////////////////// + private OCTET_STRING keyIdentifier; + private static OBJECT_IDENTIFIER OID = new + OBJECT_IDENTIFIER("2.5.29.14"); + + /////////////////////////////////////////////////////////////////////// + // Construction + /////////////////////////////////////////////////////////////////////// + + /** + * Constructs an SubjectKeyIdentifier from its components. + * + * @param keyIdentifier must not be null. + */ + public SubjectKeyIdentifier(OCTET_STRING keyIdentifier) { + super(OID,false,keyIdentifier); + } + + public SubjectKeyIdentifier(boolean critical, OCTET_STRING keyIdentifier) { + super(OID,critical,keyIdentifier); + } + + public static class Template implements ASN1Template { + + private SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + seqt.addElement( OBJECT_IDENTIFIER.getTemplate() ); + seqt.addElement( BOOLEAN.getTemplate(), new BOOLEAN(false) ); + seqt.addElement( OCTET_STRING.getTemplate() ); + } + + public boolean tagMatch(Tag t) { + return TAG.equals(t); + } + + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicit, InputStream istream) + throws IOException, InvalidBERException + { + SEQUENCE seq = (SEQUENCE) seqt.decode(implicit, istream); + Assert.assert( ((OBJECT_IDENTIFIER) seq.elementAt(0)).equals(OID) ); + + return new SubjectKeyIdentifier( + ((BOOLEAN) seq.elementAt(1)).toBoolean(), + (OCTET_STRING) seq.elementAt(2) + ); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cert/manifest.mn b/mozilla/security/jss/org/mozilla/jss/pkix/cert/manifest.mn new file mode 100644 index 00000000000..3ccaf51f0c0 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cert/manifest.mn @@ -0,0 +1,71 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +CORE_DEPTH = ../../../../../.. + +MODULE = ninja + +NS_USE_JDK = 1 + +PACKAGE = com/netscape/jss/pkix/cert + +# These are meant to be used within Ninja only. +PRIVATE_EXPORTS = \ + $(NULL) + +JNI_GEN = \ + $(NULL) + +CLASSES = \ + Certificate \ + CertificateInfo \ + Extension \ + SubjectKeyIdentifier \ + $(NULL) + +PRIVATE_CLASSES = \ + $(NULL) + + +JSRCS = \ + Certificate.java \ + CertificateInfo.java \ + Extension.java \ + SubjectKeyIdentifier.java \ + $(NULL) + +PRIVATE_JSRCS = + + +CSRCS = \ + $(NULL) diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cert/package.html b/mozilla/security/jss/org/mozilla/jss/pkix/cert/package.html new file mode 100644 index 00000000000..8a81bb4598f --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cert/package.html @@ -0,0 +1,37 @@ + + + +Encoding and decoding X.509 certificates and certificate extensions. + + diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cmc/CMCStatusInfo.java b/mozilla/security/jss/org/mozilla/jss/pkix/cmc/CMCStatusInfo.java new file mode 100644 index 00000000000..c809394653b --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cmc/CMCStatusInfo.java @@ -0,0 +1,252 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + + +package com.netscape.jss.pkix.cmc; + +import com.netscape.jss.util.Assert; +import com.netscape.jss.asn1.*; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.BitSet; + +/** + * CMC CMCStatusInfo: + *

+ *     CMCStatusInfo ::= SEQUENCE { 
+ *          cMCStatus           CMCStatus, 
+ *          bodyList            SEQUENCE SIZE (1..MAX) OF BodyPartID, 
+ *          statusString        UTF8String OPTIONAL, 
+ *          otherInfo           CHOICE { 
+ *            failInfo            CMCFailInfo, 
+ *            pendInfo            PendInfo } OPTIONAL 
+ *     } 
+ *     PendInfo ::= SEQUENCE { 
+ *          pendToken           OCTET STRING, 
+ *          pendTime            GeneralizedTime 
+ *     }
+ * 
+ */ +public class CMCStatusInfo implements ASN1Value { + public static final INTEGER BODYIDMAX = new INTEGER("4294967295"); + + /////////////////////////////////////////////////////////////////////// + // Members + /////////////////////////////////////////////////////////////////////// + private INTEGER status; + private SEQUENCE bodyList; + private UTF8String statusString; + private OtherInfo otherInfo; + + // CMCStatus constants + public static final int SUCCESS = 0; + public static final int RESERVED = 1; + public static final int FAILED = 2; + public static final int PENDING = 3; + public static final int NOSUPPORT = 4; + public static final int CONFIRM_REQUIRED = 5; + + public static final String[] STATUS = {"success", + "reserved", + "failed", + "pending", + "not supported", + "confirm required"}; + + /////////////////////////////////////////////////////////////////////// + // Constructors + /////////////////////////////////////////////////////////////////////// + + private CMCStatusInfo() { } + + /** + * @param status A CMCStatus constant. + * @param bodyList The sequence of bodyPartID. + */ + public CMCStatusInfo(int status, SEQUENCE bodyList) { + this.status = new INTEGER(status); + this.bodyList = bodyList; + this.statusString = null; + this.otherInfo = null; + } + + /** + * @param status A CMCStatus constant. + * @param bodyList The sequence of bodyPartID. + * @param statusString A String. + * @param OtherInfo The OtherInfo choice. + */ + public CMCStatusInfo(int status, SEQUENCE bodyList, String + statusString, OtherInfo otherInfo) { + this.status = new INTEGER(status); + this.bodyList = bodyList; + if (statusString != null){ + try{ + this.statusString = new UTF8String(statusString); + }catch (Exception e){} + }else + this.statusString = null; + this.otherInfo = otherInfo; + } + + /** + * Create a CMCStatusInfo from decoding. + * @param status A CMCStatus constant. + * @param bodyList The sequence of bodyPartID. + * @param statusString A UTF8String. + * @param otherInfo A CHOICE. + */ + public CMCStatusInfo(INTEGER status, SEQUENCE bodyList, UTF8String + statusString, OtherInfo otherInfo) { + this.status = status; + this.bodyList = bodyList; + this.statusString = statusString; + this.otherInfo = otherInfo; + } + + /** + * Sets the statusString field. May be null, since this + * field is optional. + */ + public void setStatusString(String statusString) { + if (statusString != null){ + try{ + this.statusString = new UTF8String(statusString); + }catch (Exception e){} + }else{ + this.statusString = null; + } + } + + /** + * Adds a BodyPartID to the bodyList SEQUENCE. + */ + public void addBodyPartID(int id) { + INTEGER id1 = new INTEGER(id); + Assert.assert(id1.compareTo(BODYIDMAX) <= 0); + bodyList.addElement( id1 ); + } + + /////////////////////////////////////////////////////////////////////// + // member access + /////////////////////////////////////////////////////////////////////// + public int getStatus() { + return status.intValue(); + } + + public SEQUENCE getBodyList() { + return bodyList; + } + + public String getStatusString() { + return statusString.toString(); + } + + public OtherInfo getOtherInfo() { + return otherInfo; + } + + /////////////////////////////////////////////////////////////////////// + // decoding/encoding + /////////////////////////////////////////////////////////////////////// + + public static final Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + encode(TAG, ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + SEQUENCE seq = new SEQUENCE(); + + seq.addElement(status); + seq.addElement(bodyList); + if( statusString != null ) { + seq.addElement( statusString ); + } + + if ( otherInfo != null) { + seq.addElement( otherInfo ); + } + + seq.encode(implicitTag, ostream); + } + + private static final Template templateInstance = new Template(); + public static Template getTemplate() { + return templateInstance; + } + + + public static class Template implements ASN1Template { + + private SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + seqt.addElement( INTEGER.getTemplate() ); + seqt.addElement( new SEQUENCE.OF_Template(INTEGER.getTemplate()) ); + seqt.addOptionalElement( UTF8String.getTemplate()); + + seqt.addOptionalElement( OtherInfo.getTemplate() ); + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws InvalidBERException, IOException { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws InvalidBERException, IOException { + + CMCStatusInfo psi; + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); + + return new CMCStatusInfo((INTEGER)seq.elementAt(0), + (SEQUENCE)seq.elementAt(1), + (UTF8String)seq.elementAt(2), + (OtherInfo)seq.elementAt(3)); + } + } +} + diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cmc/Makefile b/mozilla/security/jss/org/mozilla/jss/pkix/cmc/Makefile new file mode 100644 index 00000000000..bb06c14abbb --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cmc/Makefile @@ -0,0 +1,74 @@ +#! gmake +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +####################################################################### +# (1) Include initial platform-independent assignments (MANDATORY). # +####################################################################### + +include manifest.mn + +####################################################################### +# (2) Include "global" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/config.mk + +####################################################################### +# (3) Include "component" configuration information. (OPTIONAL) # +####################################################################### +include $(CORE_DEPTH)/$(MODULE)/config/config.mk + + +####################################################################### +# (4) Include "local" platform-dependent assignments (OPTIONAL). # +####################################################################### + + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### + + diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cmc/OtherInfo.java b/mozilla/security/jss/org/mozilla/jss/pkix/cmc/OtherInfo.java new file mode 100644 index 00000000000..1f7f9d4bcfb --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cmc/OtherInfo.java @@ -0,0 +1,218 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkix.cmc; + +import com.netscape.jss.asn1.*; +import java.io.*; +import com.netscape.jss.util.Assert; + +/** + * CMCStatusInfo OtherInfo: + *
+ *   OtherInfo ::= CHOICE { 
+ *       failInfo INTEGER, 
+ *       pendInfo PendInfo 
+ *   } 
+ * 
+ */ +public class OtherInfo implements ASN1Value { + // CMCFailInfo constants + public static final int BAD_ALG = 0; + public static final int BAD_MESSAGE_CHECK = 1; + public static final int BAD_REQUEST = 2; + public static final int BAD_TIME = 3; + public static final int BAD_CERT_ID = 4; + public static final int UNSUPORTED_EXT = 5; + public static final int MUST_ARCHIVE_KEYS = 6; + public static final int BAD_IDENTITY = 7; + public static final int POP_REQUIRED = 8; + public static final int POP_FAILED = 9; + public static final int NO_KEY_REUSE = 10; + public static final int INTERNAL_CA_ERROR = 11; + public static final int TRY_LATER = 12; + + public static final String[] FAIL_INFO = {"bad algorithm", + "bad message check", + "bad request", + "bad time", + "bad certificate id", + "unsupported extensions", + "must archive keys", + "bad identity", + "POP required", + "POP failed", + "no key reuse", + "internal ca error", + "try later"}; + /** + * The type of OtherInfo. + */ + public static class Type { + private Type() { } + + static Type FAIL = new Type(); + static Type PEND = new Type(); + } + public static Type FAIL = Type.FAIL; + public static Type PEND = Type.PEND; + + /////////////////////////////////////////////////////////////////////// + // members and member access + /////////////////////////////////////////////////////////////////////// + + private Type type; + private INTEGER failInfo; // if type == FAIL + private PendInfo pendInfo; // if type == PEND + + /////////////////////////////////////////////////////////////////////// + // Constructors + /////////////////////////////////////////////////////////////////////// + + // no default constructor + public OtherInfo() { } + + /** + * Constructs a OtherInfo from its components. + * + * @param type The type of the otherInfo. + * @param failInfo the CMCFailInfo code. + * @param pendInfo the pending information. + */ + public OtherInfo(Type type, INTEGER failInfo, PendInfo pendInfo) { + this.type = type; + this.failInfo = failInfo; + this.pendInfo = pendInfo; + } + + /////////////////////////////////////////////////////////////////////// + // accessors + /////////////////////////////////////////////////////////////////////// + + /** + * Returns the type of OtherInfo:
    + *
  • FAIL + *
  • PEND + *
+ */ + public Type getType() { + return type; + } + + /** + * If type == FAIL, returns the failInfo field. Otherwise, + * returns null. + */ + public INTEGER getFailInfo() { + return failInfo; + } + + /** + * If type == PEND, returns the pendInfo field. Otherwise, + * returns null. + */ + public PendInfo getPendInfo() { + return pendInfo; + } + + /////////////////////////////////////////////////////////////////////// + // DER decoding/encoding + /////////////////////////////////////////////////////////////////////// + + public Tag getTag() { + // return the subType's tag + if( type == FAIL ) { + return INTEGER.TAG; + } else { + Assert.assert( type == PEND ); + return PendInfo.TAG; + } + } + + public void encode(OutputStream ostream) throws IOException { + + if( type == FAIL ) { + failInfo.encode(ostream); + } else { + Assert.assert( type == PEND ); + pendInfo.encode(ostream); + } + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException { + //Assert.notReached("A CHOICE cannot be implicitly tagged " +implicitTag.getNum()); + encode(ostream); + } + + private static final Template templateInstance = new Template(); + public static Template getTemplate() { + return templateInstance; + } + + /** + * A Template for decoding a OtherInfo. + */ + public static class Template implements ASN1Template { + + private CHOICE.Template choicet; + + public Template() { + choicet = new CHOICE.Template(); + choicet.addElement( INTEGER.getTemplate() ); + choicet.addElement( PendInfo.getTemplate() ); + } + + public boolean tagMatch(Tag tag) { + return choicet.tagMatch(tag); + } + + public ASN1Value decode(InputStream istream) + throws InvalidBERException, IOException { + CHOICE c = (CHOICE) choicet.decode(istream); + + if( c.getTag().equals(INTEGER.TAG) ) { + return new OtherInfo(FAIL, (INTEGER) c.getValue() , null); + } else { + Assert.assert( c.getTag().equals(PendInfo.TAG) ); + return new OtherInfo(PEND, null, (PendInfo) c.getValue()); + } + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws InvalidBERException, IOException { + //Assert.notReached("A CHOICE cannot be implicitly tagged"); + return decode(istream); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cmc/PKIData.java b/mozilla/security/jss/org/mozilla/jss/pkix/cmc/PKIData.java new file mode 100644 index 00000000000..18c411fe08d --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cmc/PKIData.java @@ -0,0 +1,175 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkix.cmc; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; +import com.netscape.jss.asn1.*; +import com.netscape.jss.pkix.primitive.*; +import com.netscape.jss.util.Assert; + +/** + * A PKIData for CMC full enrollment request. + * PKIData ::= SEQUENCE { + * controlSequence SEQUENCE SIZE(0..MAX) OF TaggedAttribute, + * reqSequence SEQUENCE SIZE(0..MAX) OF TaggedRequest, + * cmsSequence SEQUENCE SIZE(0..MAX) OF TaggedContentInfo, + * otherMsgSequence SEQUENCE SIZE(0..MAX) OF OtherMsg + * } + */ +public class PKIData implements ASN1Value { + + /////////////////////////////////////////////////////////////////////// + // Members + /////////////////////////////////////////////////////////////////////// + private SEQUENCE sequence; + private SEQUENCE controlSequence; + private SEQUENCE reqSequence; + private SEQUENCE cmsSequence; + private SEQUENCE otherMsgSequence; + + /////////////////////////////////////////////////////////////////////// + // Construction + /////////////////////////////////////////////////////////////////////// + + // no default constructor + private PKIData() { } + + /** + * Constructs a PKIData from its components. + * + * @param controlSequence Sequence of TagggedAttribute. + * @param reqSequence Sequence of TagggedRequest. + * @param cmsSequence Sequence of TagggedContentInfo. + * @param otherMsgSequence Sequence of OtherMsg. + */ + public PKIData(SEQUENCE controlSequence, SEQUENCE reqSequence, SEQUENCE + cmsSequence, SEQUENCE otherMsgSequence) { + sequence = new SEQUENCE(); + this.controlSequence = controlSequence; + sequence.addElement(controlSequence); + this.reqSequence = reqSequence; + sequence.addElement(reqSequence); + this.cmsSequence = cmsSequence; + sequence.addElement(cmsSequence); + this.otherMsgSequence = otherMsgSequence; + sequence.addElement(otherMsgSequence); + } + + + /////////////////////////////////////////////////////////////////////// + // accessors + /////////////////////////////////////////////////////////////////////// + + public SEQUENCE getControlSequence() { + return controlSequence; + } + + public SEQUENCE getReqSequence() { + return reqSequence; + } + + public SEQUENCE getCmsSequence() { + return cmsSequence; + } + + public SEQUENCE getOtherMsgSequence() { + return otherMsgSequence; + } + + + /////////////////////////////////////////////////////////////////////// + // DER encoding/decoding + /////////////////////////////////////////////////////////////////////// + static Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + encode(TAG, ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + sequence.encode(implicitTag, ostream); + } + + private static final Template templateInstance = new Template(); + public static Template getTemplate() { + return templateInstance; + } + + /** + * A template for decoding an PKIData from its BER encoding. + */ + public static class Template implements ASN1Template { + private SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + seqt.addElement(new SEQUENCE.OF_Template(TaggedAttribute.getTemplate()) ); + seqt.addElement( new SEQUENCE.OF_Template(TaggedRequest.getTemplate()) ); + seqt.addElement( new SEQUENCE.OF_Template(new ANY.Template()) ); + seqt.addElement( new SEQUENCE.OF_Template(new ANY.Template()) ); + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws InvalidBERException, IOException + { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws InvalidBERException, IOException + { + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); + + Assert.assert(seq.size() == 4); + + return new PKIData( + (SEQUENCE) seq.elementAt(0), + (SEQUENCE) seq.elementAt(1), + (SEQUENCE) seq.elementAt(2), + (SEQUENCE) seq.elementAt(3)); + } + } +} + diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cmc/PendInfo.java b/mozilla/security/jss/org/mozilla/jss/pkix/cmc/PendInfo.java new file mode 100644 index 00000000000..9327fa21059 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cmc/PendInfo.java @@ -0,0 +1,161 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkix.cmc; + +import com.netscape.jss.asn1.*; +import java.io.*; +import com.netscape.jss.util.Assert; +import java.util.Date; + +/** + * CMC PendInfo: + *
+ *   PendInfo ::= SEQUENCE { 
+ *       pendToken            OCTET STRING, 
+ *       pendTime             GeneralizedTime 
+ *   } 
+ * 
+ */ +public class PendInfo implements ASN1Value { + /////////////////////////////////////////////////////////////////////// + // Members + /////////////////////////////////////////////////////////////////////// + private SEQUENCE sequence; + private OCTET_STRING pendToken; + private GeneralizedTime pendTime; + + /////////////////////////////////////////////////////////////////////// + // Construction + /////////////////////////////////////////////////////////////////////// + + // no default constructor + private PendInfo() { } + + /** + * Constructs a PendInfo from its components. + * + * @param pendToken the identifier. + * @param pendTime the suggested time for the client to query the status. + */ + public PendInfo(OCTET_STRING pendToken, GeneralizedTime pendTime) { + sequence = new SEQUENCE(); + this.pendToken = pendToken; + sequence.addElement(pendToken); + this.pendTime = pendTime; + sequence.addElement(pendTime); + } + + /** + * Constructs a PendInfo from requestId and date. + * + * @param reqId the request Id + * @param date the suggested time for the client to query the status. + */ + public PendInfo(String reqId, Date date) { + sequence = new SEQUENCE(); + this.pendToken = new OCTET_STRING(reqId.getBytes()); + sequence.addElement(new OCTET_STRING(reqId.getBytes())); + this.pendTime = new GeneralizedTime(date); + sequence.addElement(new GeneralizedTime(date)); + } + /////////////////////////////////////////////////////////////////////// + // accessors + /////////////////////////////////////////////////////////////////////// + + public GeneralizedTime getPendTime() { + return pendTime; + } + + public OCTET_STRING getPendToken() { + return pendToken; + } + + /////////////////////////////////////////////////////////////////////// + // DER encoding/decoding + /////////////////////////////////////////////////////////////////////// + public static final Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + encode(TAG, ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + sequence.encode(implicitTag, ostream); + } + + private static final Template templateInstance = new Template(); + public static Template getTemplate() { + return templateInstance; + } + + /** + * A template for decoding an PendInfo from its BER encoding. + */ + public static class Template implements ASN1Template { + private SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + seqt.addElement( OCTET_STRING.getTemplate() ); + seqt.addElement( GeneralizedTime.getTemplate() ); + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws InvalidBERException, IOException + { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws InvalidBERException, IOException + { + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); + + Assert.assert(seq.size() == 2); + + return new PendInfo( + (OCTET_STRING) seq.elementAt(0), + (GeneralizedTime) seq.elementAt(1)); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cmc/ResponseBody.java b/mozilla/security/jss/org/mozilla/jss/pkix/cmc/ResponseBody.java new file mode 100644 index 00000000000..925d4c80d92 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cmc/ResponseBody.java @@ -0,0 +1,164 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkix.cmc; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; +import com.netscape.jss.asn1.*; +import com.netscape.jss.pkix.primitive.*; +import com.netscape.jss.util.Assert; + +/** + * A ResponseBody for CMC full enrollment request. + * ResponseBody ::= SEQUENCE { + * controlSequence SEQUENCE SIZE(0..MAX) OF TaggedAttribute, + * cmsSequence SEQUENCE SIZE(0..MAX) OF TaggedContentInfo, + * otherMsgSequence SEQUENCE SIZE(0..MAX) OF OtherMsg + * } + */ +public class ResponseBody implements ASN1Value { + + /////////////////////////////////////////////////////////////////////// + // Members + /////////////////////////////////////////////////////////////////////// + private SEQUENCE sequence; + private SEQUENCE controlSequence; + private SEQUENCE cmsSequence; + private SEQUENCE otherMsgSequence; + + /////////////////////////////////////////////////////////////////////// + // Construction + /////////////////////////////////////////////////////////////////////// + + // no default constructor + private ResponseBody() { } + + /** + * Constructs a ResponseBody from its components. + * + * @param controlSequence Sequence of TagggedAttribute. + * @param cmsSequence Sequence of TagggedContentInfo. + * @param otherMsgSequence Sequence of OtherMsg. + */ + public ResponseBody(SEQUENCE controlSequence, SEQUENCE + cmsSequence, SEQUENCE otherMsgSequence) { + sequence = new SEQUENCE(); + this.controlSequence = controlSequence; + sequence.addElement(controlSequence); + this.cmsSequence = cmsSequence; + sequence.addElement(cmsSequence); + this.otherMsgSequence = otherMsgSequence; + sequence.addElement(otherMsgSequence); + } + + + /////////////////////////////////////////////////////////////////////// + // accessors + /////////////////////////////////////////////////////////////////////// + + public SEQUENCE getControlSequence() { + return controlSequence; + } + + public SEQUENCE getCmsSequence() { + return cmsSequence; + } + + public SEQUENCE getOtherMsgSequence() { + return otherMsgSequence; + } + + + /////////////////////////////////////////////////////////////////////// + // DER encoding/decoding + /////////////////////////////////////////////////////////////////////// + static Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + encode(TAG, ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + sequence.encode(implicitTag, ostream); + } + + private static final Template templateInstance = new Template(); + public static Template getTemplate() { + return templateInstance; + } + + /** + * A template for decoding an ResponseBody from its BER encoding. + */ + public static class Template implements ASN1Template { + private SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + seqt.addElement(new SEQUENCE.OF_Template(TaggedAttribute.getTemplate()) ); + seqt.addElement(new SEQUENCE.OF_Template(ANY.getTemplate()) ); + seqt.addElement(new SEQUENCE.OF_Template(ANY.getTemplate()) ); + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws InvalidBERException, IOException + { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws InvalidBERException, IOException + { + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); + + Assert.assert(seq.size() == 3); + + return new ResponseBody( + (SEQUENCE) seq.elementAt(0), + (SEQUENCE) seq.elementAt(1), + (SEQUENCE) seq.elementAt(2)); + } + } +} + diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cmc/TaggedAttribute.java b/mozilla/security/jss/org/mozilla/jss/pkix/cmc/TaggedAttribute.java new file mode 100644 index 00000000000..39cd5cceb9f --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cmc/TaggedAttribute.java @@ -0,0 +1,181 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkix.cmc; + +import com.netscape.jss.asn1.*; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; +import com.netscape.jss.util.Assert; + +/** + * A tagged attribute, which has the following ASN.1 + * definition : + *
+ *   TaggedAttribute ::= SEQUENCE {
+ *      bodyPartID         BodyPartId, 
+ *      attrType           OBJECT IDENTIFIER, 
+ *      attrValues         SET OF AttributeValue 
+ *   bodyIdMax INTEGER ::= 4294967295
+ *
+ *   BodyPartID ::= INTEGER(0..bodyIdMax)
+ * 
+ */ +public class TaggedAttribute implements ASN1Value { + public static final INTEGER BODYIDMAX = new INTEGER("4294967295"); + + /////////////////////////////////////////////////////////////////////// + // Members + /////////////////////////////////////////////////////////////////////// + + private SEQUENCE sequence; + private INTEGER bodyPartID; + private OBJECT_IDENTIFIER type; + private SET values; + + /////////////////////////////////////////////////////////////////////// + // Construction + /////////////////////////////////////////////////////////////////////// + + private TaggedAttribute() { } + + public TaggedAttribute(INTEGER bodyPartID, OBJECT_IDENTIFIER type, SET values) { + sequence = new SEQUENCE(); + Assert.assert(bodyPartID.compareTo(BODYIDMAX) <= 0); + this.bodyPartID = bodyPartID; + sequence.addElement(bodyPartID); + this.type = type; + sequence.addElement(type); + this.values = values; + sequence.addElement(values); + } + + public TaggedAttribute(INTEGER bodyPartID, OBJECT_IDENTIFIER type, ASN1Value value) { + sequence = new SEQUENCE(); + Assert.assert(bodyPartID.compareTo(BODYIDMAX) <= 0); + this.bodyPartID = bodyPartID; + sequence.addElement(bodyPartID); + this.type = type; + sequence.addElement(type); + this.values = new SET(); + values.addElement(value); + sequence.addElement(values); + } + + /////////////////////////////////////////////////////////////////////// + // accessors + /////////////////////////////////////////////////////////////////////// + + public INTEGER getBodyPartID() { + return bodyPartID; + } + + public OBJECT_IDENTIFIER getType() { + return type; + } + + /** + * If this AVA was constructed, returns the SET of ASN1Values passed to the + * constructor. If this Atrribute was decoded with an Attribute.Template, + * returns a SET of ANYs. + */ + public SET getValues() { + return values; + } + + /////////////////////////////////////////////////////////////////////// + // DER encoding/decoding + /////////////////////////////////////////////////////////////////////// + public static final Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + encode(TAG, ostream); + } + + public void encode(Tag implicit, OutputStream ostream) + throws IOException + { + sequence.encode(implicit, ostream); + } + + public static Template getTemplate() { + return templateInstance; + } + private static Template templateInstance = new Template(); + + /** + * A Template for decoding an Attribute. + */ + public static class Template implements ASN1Template { + private SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + seqt.addElement( INTEGER.getTemplate() ); + seqt.addElement( new OBJECT_IDENTIFIER.Template() ); + seqt.addElement( new SET.OF_Template(new ANY.Template())); + } + + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicit, InputStream istream) + throws IOException, InvalidBERException + { + SEQUENCE seq = (SEQUENCE) seqt.decode(implicit, istream); + + // The template should have enforced this + Assert.assert(seq.size() == 3); + + return new TaggedAttribute( + (INTEGER) seq.elementAt(0), + (OBJECT_IDENTIFIER) seq.elementAt(1), + (SET) seq.elementAt(2)); + } + } +} + + + diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cmc/TaggedCertificationRequest.java b/mozilla/security/jss/org/mozilla/jss/pkix/cmc/TaggedCertificationRequest.java new file mode 100644 index 00000000000..6da304eadf2 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cmc/TaggedCertificationRequest.java @@ -0,0 +1,154 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkix.cmc; + +import com.netscape.jss.asn1.*; +import java.io.*; +import com.netscape.jss.util.Assert; +import com.netscape.jss.pkcs10.*; + +/** + * CMC TaggedCertificationRequest: + *
+ *   TaggedCertificationRequest ::= SEQUENCE { 
+ *       bodyPartID            BodyPartID, 
+ *       certificationRequest  CertificationRequest 
+ *   } 
+ *   bodyIdMax INTEGER ::= 4294967295
+ *
+ *   BodyPartID ::= INTEGER(0..bodyIdMax)
+ * 
+ */ +public class TaggedCertificationRequest implements ASN1Value { + public static final INTEGER BODYIDMAX = new INTEGER("4294967295"); + + /////////////////////////////////////////////////////////////////////// + // Members + /////////////////////////////////////////////////////////////////////// + private SEQUENCE sequence; + private INTEGER bodyPartID; + private CertificationRequest certificationRequest; + + /////////////////////////////////////////////////////////////////////// + // Construction + /////////////////////////////////////////////////////////////////////// + + // no default constructor + private TaggedCertificationRequest() { } + + /** + * Constructs a TaggedCertificationRequest from its components. + * + * @param bodyPartID the identifier. + * @param certificationRequest the pkcs10 request. + */ + public TaggedCertificationRequest(INTEGER bodyPartID, CertificationRequest certificationRequest) { + sequence = new SEQUENCE(); + Assert.assert(bodyPartID.compareTo(BODYIDMAX) <= 0); + this.bodyPartID = bodyPartID; + sequence.addElement(bodyPartID); + this.certificationRequest = certificationRequest; + sequence.addElement(certificationRequest); + } + + /////////////////////////////////////////////////////////////////////// + // accessors + /////////////////////////////////////////////////////////////////////// + + public CertificationRequest getCertificationRequest() { + return certificationRequest; + } + + public INTEGER getBodyPartID() { + return bodyPartID; + } + + /////////////////////////////////////////////////////////////////////// + // DER encoding/decoding + /////////////////////////////////////////////////////////////////////// + public static final Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + encode(TAG, ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + sequence.encode(implicitTag, ostream); + } + + private static final Template templateInstance = new Template(); + public static Template getTemplate() { + return templateInstance; + } + + /** + * A template for decoding an TaggedCertificationRequest from its BER encoding. + */ + public static class Template implements ASN1Template { + private SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + seqt.addElement( INTEGER.getTemplate() ); + seqt.addElement( CertificationRequest.getTemplate() ); + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws InvalidBERException, IOException + { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws InvalidBERException, IOException + { + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); + + Assert.assert(seq.size() == 2); + + return new TaggedCertificationRequest( + (INTEGER) seq.elementAt(0), + (CertificationRequest) seq.elementAt(1)); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cmc/TaggedRequest.java b/mozilla/security/jss/org/mozilla/jss/pkix/cmc/TaggedRequest.java new file mode 100644 index 00000000000..185975a1c67 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cmc/TaggedRequest.java @@ -0,0 +1,214 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkix.cmc; + +import com.netscape.jss.asn1.*; +import com.netscape.jss.pkix.crmf.*; +import java.io.*; +import com.netscape.jss.util.Assert; + +/** + * CMC TaggedRequest: + *
+ *   TaggedRequest ::= CHOICE { 
+ *       tcr               [0] TaggedCertificationRequest, 
+ *       crm               [1] CertReqMsg 
+ *   } 
+ * 
+ */ +public class TaggedRequest implements ASN1Value { + /** + * The type of TaggedRequest. + */ + public static class Type { + private Type() { } + + static Type PKCS10 = new Type(); + static Type CRMF = new Type(); + } + public static Type PKCS10 = Type.PKCS10; + public static Type CRMF = Type.CRMF; + + /////////////////////////////////////////////////////////////////////// + // members and member access + /////////////////////////////////////////////////////////////////////// + + private Type type; + private TaggedCertificationRequest tcr; // if type == PKCS10 + private CertReqMsg crm; // if type == CRMF + + /////////////////////////////////////////////////////////////////////// + // Constructors + /////////////////////////////////////////////////////////////////////// + + // no default constructor + public TaggedRequest() { } + + /** + * Constructs a TaggedRequest from its components. + * + * @param type The type of the request. + * @param tcr Tagged pkcs10 request. + * @param crm CRMF request. + */ + public TaggedRequest(Type type, TaggedCertificationRequest tcr, CertReqMsg crm) { + this.type = type; + this.tcr = tcr; + this.crm = crm; + } + + /////////////////////////////////////////////////////////////////////// + // accessors + /////////////////////////////////////////////////////////////////////// + + /** + * Returns the type of TaggedRequest:
    + *
  • PKCS10 + *
  • CRMF + *
+ */ + public Type getType() { + return type; + } + + /** + * If type == PKCS10, returns the tcr field. Otherwise, + * returns null. + */ + public TaggedCertificationRequest getTcr() { + return tcr; + } + + /** + * If type == CRMF, returns the crm field. Otherwise, + * returns null. + */ + public CertReqMsg getCrm() { + return crm; + } + + /////////////////////////////////////////////////////////////////////// + // DER decoding/encoding + /////////////////////////////////////////////////////////////////////// + + public Tag getTag() { + if( type == PKCS10 ) { + return Tag.get(0); + } else { + Assert.assert( type == CRMF ); + return Tag.get(1); + } + } + + public void encode(OutputStream ostream) throws IOException { + + if( type == PKCS10 ) { + tcr.encode(Tag.get(0), ostream); + // a CHOICE must be explicitly tagged + //EXPLICIT e = new EXPLICIT( Tag.get(0), tcr ); + //e.encode(ostream); + } else { + Assert.assert( type == CRMF ); + crm.encode(Tag.get(1), ostream); + // a CHOICE must be explicitly tagged + //EXPLICIT e = new EXPLICIT( Tag.get(1), crm ); + //e.encode(ostream); + } + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException { + //Assert.notReached("A CHOICE cannot be implicitly tagged " +implicitTag.getNum()); + //tagAt() of SET.java actually returns the underlying type + encode(ostream); + } + + private static final Template templateInstance = new Template(); + public static Template getTemplate() { + return templateInstance; + } + + /** + * A Template for decoding a ProofOfPossession. + */ + public static class Template implements ASN1Template { + + private CHOICE.Template choicet; + + public Template() { + choicet = new CHOICE.Template(); + + //EXPLICIT.Template et = new EXPLICIT.Template( + // Tag.get(0), TaggedCertificationRequest.getTemplate() ); + //choicet.addElement( et ); + choicet.addElement( Tag.get(0), TaggedCertificationRequest.getTemplate() ); + //et = new EXPLICIT.Template( + // Tag.get(1), CertReqMsg.getTemplate() ); + //choicet.addElement( et ); + choicet.addElement( Tag.get(1), CertReqMsg.getTemplate() ); + } + + public boolean tagMatch(Tag tag) { + return choicet.tagMatch(tag); + } + + public ASN1Value decode(InputStream istream) + throws InvalidBERException, IOException { + CHOICE c = (CHOICE) choicet.decode(istream); + + if( c.getTag().equals(Tag.get(0)) ) { + //EXPLICIT e = (EXPLICIT) c.getValue(); + //return new TaggedRequest(PKCS10, + // (TaggedCertificationRequest) + // e.getContent(), null ); + return new TaggedRequest(PKCS10, (TaggedCertificationRequest) c.getValue() , null); + } else { + Assert.assert( c.getTag().equals(Tag.get(1)) ); + //EXPLICIT e = (EXPLICIT) c.getValue(); + //return new TaggedRequest(CRMF, null, + // (CertReqMsg) e.getContent() ); + return new TaggedRequest(CRMF, null, (CertReqMsg) c.getValue()); + } + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws InvalidBERException, IOException { + //Assert.notReached("A CHOICE cannot be implicitly tagged"); + return decode(istream); + } + } +} + + + diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cmc/manifest.mn b/mozilla/security/jss/org/mozilla/jss/pkix/cmc/manifest.mn new file mode 100644 index 00000000000..4b8ba219287 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cmc/manifest.mn @@ -0,0 +1,66 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +CORE_DEPTH = ../../../../../.. + +MODULE = ninja + +NS_USE_JDK = 1 + + +PACKAGE = com/netscape/jss/pkix/cmc + + +CLASSES = \ + PKIData \ + TaggedCertificationRequest \ + TaggedRequest \ + ResponseBody \ + TaggedAttribute \ + CMCStatusInfo \ + PendInfo \ + OtherInfo \ + $(NULL) + + + +JSRCS = \ + PKIData.java \ + TaggedCertificationRequest.java \ + TaggedRequest.java \ + ResponseBody.java \ + TaggedAttribute.java \ + CMCStatusInfo.java \ + PendInfo.java \ + OtherInfo.java \ + $(NULL) diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cmc/package.html b/mozilla/security/jss/org/mozilla/jss/pkix/cmc/package.html new file mode 100644 index 00000000000..581aeaa93bf --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cmc/package.html @@ -0,0 +1,37 @@ + + + +Creating and interpeting CMC blobs. + + diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cmmf/CertOrEncCert.java b/mozilla/security/jss/org/mozilla/jss/pkix/cmmf/CertOrEncCert.java new file mode 100644 index 00000000000..cb5d8bcd609 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cmmf/CertOrEncCert.java @@ -0,0 +1,79 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkix.cmmf; + +import com.netscape.jss.asn1.*; +import java.io.OutputStream; +import java.io.IOException; +import com.netscape.jss.util.Assert; +import java.io.ByteArrayOutputStream; + +public class CertOrEncCert implements ASN1Value { + + private ANY certificate; + byte[] encoding; + + /** + * @exception InvalidBERException If the certificate is not a valid + * BER-encoding. + */ + public CertOrEncCert(byte[] encodedCert) throws IOException, + InvalidBERException + { + certificate = new ANY( new Tag(0), encodedCert ); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + certificate.encodeWithAlternateTag(new Tag(0), bos); + encoding = bos.toByteArray(); + } + + public static final Tag TAG = new Tag(0); + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + ostream.write(encoding); + } + + /** + * @param implicitTag This parameter is ignored, because a CHOICE + * cannot have an implicit tag. + */ + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + Assert.assert( implicitTag.equals(TAG) ); + ostream.write(encoding); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cmmf/CertRepContent.java b/mozilla/security/jss/org/mozilla/jss/pkix/cmmf/CertRepContent.java new file mode 100644 index 00000000000..53c78ea5017 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cmmf/CertRepContent.java @@ -0,0 +1,186 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkix.cmmf; + +import com.netscape.jss.asn1.*; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.FileOutputStream; +import java.io.ByteArrayInputStream; +import java.io.FileInputStream; + +/** + * A CMMF CertRepContent. + *
+ * CertRepContent ::= SEQUENCE {
+ *      caPubs      [1] SEQUENCE SIZE (1..MAX) OF Certificate OPTIONAL,
+ *      response    SEQUENCE of CertResponse }
+ * 
+ * @see com.netscape.jss.pkix.cmmf.CertResponse + */ +public class CertRepContent implements ASN1Value { + + private byte[][] caPubs; // may be null + private SEQUENCE response; + + private CertRepContent() { } + + /** + * Creates a new CertRepContent. + * + * @param caPubs An array of DER-encoded X.509 Certificates. It may be + * null if the caPubs field is to be omitted. + * @param response A SEQUENCE of CertResponse objects. + * Must not be null. + */ + public CertRepContent(byte[][] caPubs, SEQUENCE response) { + this.caPubs = caPubs; + this.response = response; + } + + /** + * Creates a new CertRepContent. The responses can be + * added later with addCertResponse. + * + * @param caPubs An array of DER-encoded X.509 Certificates, must not + * be null and must have at least one element. + */ + public CertRepContent(byte[][] caPubs) { + this.caPubs = caPubs; + response = new SEQUENCE(); + } + + /** + * Creates a new CertRepContent + * + * @param response A SEQUENCE of CertResponse objects. + * Must not be null. + */ + public CertRepContent(SEQUENCE response) { + this.caPubs = null; + this.response = response; + } + + /** + * Adds another CertResponse. + */ + public void addCertResponse(CertResponse resp) { + response.addElement(resp); + } + + /** + * Returns the caPubs field, which is an array of + * DER-encoded X.509 Certificates. May return null if the + * field is not present. + */ + public byte[][] getCaPubs() { + return caPubs; + } + + /** + * Returns the response field, which is a SEQUENCE + * of CertResponse + */ + public SEQUENCE getResponse() { + return response; + } + + public static final Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + encode(TAG, ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + SEQUENCE encoding = new SEQUENCE(); + + // create sequence of certificates + if(caPubs != null) { + SEQUENCE certs = new SEQUENCE(); + for(int i = 0; i < caPubs.length; i++) { + certs.addElement( new ANY( SEQUENCE.TAG, caPubs[i] ) ); + } + encoding.addElement( new Tag(1), certs ); + } + + encoding.addElement( response ); + + encoding.encode(implicitTag, ostream); + } + + public static void main(String argv[]) { + + try { + + if(argv.length != 2) { + System.out.println("Usage: CertRepContent "); + System.out.println("certfile should contain a DER-encoded X.509 "+ + "certificate"); + System.exit(-1); + } + FileInputStream certfile = new FileInputStream(argv[0]); + FileOutputStream fos = new FileOutputStream(argv[1]); + + byte[][] certs = new byte[2][]; + certs[0] = new byte[ certfile.available() ]; + certfile.read(certs[0]); + certs[1] = certs[0]; + + PKIStatusInfo status = new PKIStatusInfo(PKIStatusInfo.rejection, + PKIStatusInfo.badRequest | PKIStatusInfo.badTime ); + + status.addFreeText("And your mother dresses you funny"); + status.addFreeText("so there"); + + CertifiedKeyPair ckp = new CertifiedKeyPair( + new CertOrEncCert( certs[0] ) ); + CertResponse resp = new CertResponse( new INTEGER(54), status, ckp); + + CertRepContent content = new CertRepContent(certs); + content.addCertResponse(resp); + + content.encode(fos); + System.out.println("Success!"); + + } catch( Exception e ) { + e.printStackTrace(); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cmmf/CertResponse.java b/mozilla/security/jss/org/mozilla/jss/pkix/cmmf/CertResponse.java new file mode 100644 index 00000000000..335aa17d0d9 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cmmf/CertResponse.java @@ -0,0 +1,107 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkix.cmmf; + +import com.netscape.jss.asn1.*; +import com.netscape.jss.util.Assert; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +public class CertResponse implements ASN1Value { + + private INTEGER certReqId; + private PKIStatusInfo status; + private CertifiedKeyPair certifiedKeyPair; + + private CertResponse() { } + + public CertResponse(INTEGER certReqId, PKIStatusInfo status) { + this.certReqId = certReqId; + this.status = status; + } + + public CertResponse(INTEGER certReqId, PKIStatusInfo status, + CertifiedKeyPair certifiedKeyPair) + { + this(certReqId, status); + this.certifiedKeyPair = certifiedKeyPair; + } + + public INTEGER getCertReqId() { + return certReqId; + } + + public PKIStatusInfo getPKIStatusInfo() { + return status; + } + + /** + * Returns true if the certifiedKeyPair field is present. + */ + public boolean hasCertifiedKeyPair() { + return (certifiedKeyPair != null); + } + + /** + * Returns the optional certified key pair. Should only be called if + * the certifiedKeyPair field is present. + */ + public CertifiedKeyPair getCertifiedKeyPair() { + Assert.assert(certifiedKeyPair!=null); + return certifiedKeyPair; + } + + public static final Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + encode(TAG, ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + SEQUENCE seq = new SEQUENCE(); + seq.addElement( certReqId ); + seq.addElement( status ); + if( certifiedKeyPair != null ) { + seq.addElement( certifiedKeyPair ); + } + + seq.encode(implicitTag, ostream); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cmmf/CertifiedKeyPair.java b/mozilla/security/jss/org/mozilla/jss/pkix/cmmf/CertifiedKeyPair.java new file mode 100644 index 00000000000..1594b1ea3ac --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cmmf/CertifiedKeyPair.java @@ -0,0 +1,65 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkix.cmmf; + +import com.netscape.jss.asn1.*; +import java.io.OutputStream; +import java.io.IOException; +import com.netscape.jss.util.Assert; + +public class CertifiedKeyPair implements ASN1Value { + + private CertOrEncCert certOrEncCert; + + public CertifiedKeyPair(CertOrEncCert certOrEncCert) { + this.certOrEncCert = certOrEncCert; + } + + public static final Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + encode(TAG, ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + SEQUENCE seq = new SEQUENCE(); + seq.addElement( certOrEncCert ); + seq.encode(implicitTag, ostream); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cmmf/GetCRL.java b/mozilla/security/jss/org/mozilla/jss/pkix/cmmf/GetCRL.java new file mode 100644 index 00000000000..e45e410bcff --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cmmf/GetCRL.java @@ -0,0 +1,218 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkix.cmmf; + +import com.netscape.jss.asn1.*; +import java.io.*; + +/** + * CMMF GetCRL. + *
+ * GetCRL ::= SEQUENCE {
+ *      issuerName      Name,
+ *      cRLName         GeneralName OPTIONAL,
+ *      time            GeneralizedTime OPTIONAL,
+ *      reasons         ReasonFlags OPTIONAL }
+ * 
+ */ +public class GetCRL implements ASN1Value { + + /////////////////////////////////////////////////////////////////////// + // constants + /////////////////////////////////////////////////////////////////////// + /** + * A bit position in a ReasonFlags bit string. + */ + public static final int unused = 0; + /** + * A bit position in a ReasonFlags bit string. + */ + public static final int keyCompromise = 1; + /** + * A bit position in a ReasonFlags bit string. + */ + public static final int cACompromise = 2; + /** + * A bit position in a ReasonFlags bit string. + */ + public static final int affiliationChanged = 3; + /** + * A bit position in a ReasonFlags bit string. + */ + public static final int superseded = 4; + /** + * A bit position in a ReasonFlags bit string. + */ + public static final int cessationOfOperation = 5; + /** + * A bit position in a ReasonFlags bit string. + */ + public static final int certificateHold = 6; + + /////////////////////////////////////////////////////////////////////// + // members and member access + /////////////////////////////////////////////////////////////////////// + private ANY issuerName; + private ANY cRLName; // may be null + private GeneralizedTime time; // may be null + private BIT_STRING reasons; // may be null + private SEQUENCE sequence; + + /** + * Returns the issuerName field. + */ + public ANY getIssuerName() { + return issuerName; + } + + /** + * Returns the cRLName field, which may be null. + */ + public ANY getCRLName() { + return cRLName; + } + + /** + * Returns the time field, which may be null. + */ + public GeneralizedTime getTime() { + return time; + } + + /** + * Returns the reasons field, which may be null. + */ + public BIT_STRING getReasons() { + return reasons; + } + + /////////////////////////////////////////////////////////////////////// + // Constructors + /////////////////////////////////////////////////////////////////////// + + private GetCRL() { } + + /** + * Constructs a GetCRL from its components. + * + * @param issuerName The issuer name of the CRL. This should be an ASN.1 + * Name. + * @param cRLName The name of the CRL, which may be null. + * This should be an ASN.1 GeneralName. + * @param time The time of the CRL, which may be null. + * @param reasons Can be used to specify from among CRLs partitioned + * by revocation reason. The BIT_STRING can be created from a + * Java BitSet. The positions in the BitSet should be set or cleared + * using the constants provided in this class. + */ + public GetCRL( ANY issuerName, ANY cRLName, GeneralizedTime time, + BIT_STRING reasons ) { + if( issuerName == null ) { + throw new IllegalArgumentException( + "issuerName parameter to GetCRL constructor is null"); + } + + sequence = new SEQUENCE(); + + this.issuerName = issuerName; + sequence.addElement(issuerName); + this.cRLName = cRLName; + sequence.addElement(cRLName); + this.time = time; + sequence.addElement(time); + this.reasons = reasons; + sequence.addElement(reasons); + } + + /////////////////////////////////////////////////////////////////////// + // encoding / decoding + /////////////////////////////////////////////////////////////////////// + + private static final Tag TAG = SEQUENCE.TAG; + + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + sequence.encode(ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException { + sequence.encode(implicitTag, ostream); + } + + private static final Template templateInstance = new Template(); + public static Template getTemplate() { + return templateInstance; + } + + /** + * A Template for decoding a GetCRL. + */ + public static class Template implements ASN1Template { + + private SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + + seqt.addElement( ANY.getTemplate() ); + seqt.addOptionalElement( ANY.getTemplate() ); + seqt.addOptionalElement( GeneralizedTime.getTemplate() ); + seqt.addOptionalElement( BIT_STRING.getTemplate() ); + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws InvalidBERException, IOException { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws InvalidBERException, IOException { + + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); + + return new GetCRL( (ANY) seq.elementAt(0), + (ANY) seq.elementAt(1), + (GeneralizedTime) seq.elementAt(2), + (BIT_STRING) seq.elementAt(3) ); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cmmf/IssuerAndSubject.java b/mozilla/security/jss/org/mozilla/jss/pkix/cmmf/IssuerAndSubject.java new file mode 100644 index 00000000000..6e2b313a893 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cmmf/IssuerAndSubject.java @@ -0,0 +1,160 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkix.cmmf; + +import com.netscape.jss.asn1.*; +import java.io.*; + +/** + * CMMF IssuerAndSubject. + *
+ * IssuerAndSubject ::= SEQUENCE {
+ *      issuer          Name,
+ *      subject         Name,
+ *      certReqId       INTEGER OPTIONAL }
+ * 
+ */ +public class IssuerAndSubject implements ASN1Value { + + /////////////////////////////////////////////////////////////////////// + // members and member access + /////////////////////////////////////////////////////////////////////// + private ANY issuer; + private ANY subject; + private INTEGER certReqId; // may be null + private SEQUENCE sequence; + + /** + * Returns the issuer field. + */ + public ANY getIssuer() { + return issuer; + } + + /** + * Returns the subject field. + */ + public ANY getSubject() { + return subject; + } + + /** + * Returns the certReqId field, which may be null. + */ + public INTEGER getCertReqId() { + return certReqId; + } + + /////////////////////////////////////////////////////////////////////// + // Constructors + /////////////////////////////////////////////////////////////////////// + + private IssuerAndSubject() { } + + public IssuerAndSubject(ANY issuer, ANY subject, INTEGER certReqId) { + if( issuer==null || subject==null ) { + throw new IllegalArgumentException( + "parameter to IssuerAndSubject constructor is null"); + } + + sequence = new SEQUENCE(); + + this.issuer = issuer; + sequence.addElement(issuer); + this.subject = subject; + sequence.addElement(subject); + this.certReqId = certReqId; + sequence.addElement(certReqId); + } + + + /////////////////////////////////////////////////////////////////////// + // encoding/decoding + /////////////////////////////////////////////////////////////////////// + + private static final Tag TAG = SEQUENCE.TAG; + + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + sequence.encode(ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException { + sequence.encode(implicitTag, ostream); + } + + private static final Template templateInstance = new Template(); + public static Template getTemplate() { + return templateInstance; + } + + /** + * A Template for decoding an IssuerAndSubject. + */ + public static class Template implements ASN1Template { + + private SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + + seqt.addElement( ANY.getTemplate() ); + seqt.addElement( ANY.getTemplate() ); + seqt.addOptionalElement( INTEGER.getTemplate() ); + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws InvalidBERException, IOException { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws InvalidBERException, IOException { + + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); + + return new IssuerAndSubject( (ANY) seq.elementAt(0), + (ANY) seq.elementAt(1), + (INTEGER) seq.elementAt(2) ); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cmmf/Makefile b/mozilla/security/jss/org/mozilla/jss/pkix/cmmf/Makefile new file mode 100644 index 00000000000..8e7b071acaf --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cmmf/Makefile @@ -0,0 +1,75 @@ +#! gmake +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +####################################################################### +# (1) Include initial platform-independent assignments (MANDATORY). # +####################################################################### + +include manifest.mn + +####################################################################### +# (2) Include "global" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/config.mk + +####################################################################### +# (3) Include "component" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/$(MODULE)/config/config.mk + + +####################################################################### +# (4) Include "local" platform-dependent assignments (OPTIONAL). # +####################################################################### +#include config.mk + + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### +#include rules.mk diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cmmf/PKIStatusInfo.java b/mozilla/security/jss/org/mozilla/jss/pkix/cmmf/PKIStatusInfo.java new file mode 100644 index 00000000000..6b9722e0655 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cmmf/PKIStatusInfo.java @@ -0,0 +1,207 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkix.cmmf; + +import com.netscape.jss.util.Assert; +import com.netscape.jss.asn1.*; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.BitSet; + +public class PKIStatusInfo implements ASN1Value { + + private INTEGER status; + private SEQUENCE statusString; + private int failInfo; // bitwise AND + private boolean hasFailInfo; + + + // PKIStatus constants + public static final int granted = 0; + public static final int grantedWithMods = 1; + public static final int rejection = 2; + public static final int waiting = 3; + public static final int revocationWarning = 4; + public static final int revocationNotification = 5; + public static final int keyUpdateWarning = 6; + + // PKIFailureInfo constants + // The bit string encoded in four bytes, big-endian, bit 0 is MSB. + public static final int badAlg = 0x80000000; + public static final int badMessageCheck = 0x40000000; + public static final int badRequest = 0x20000000; + public static final int badTime = 0x10000000; + public static final int badCertId = 0x08000000; + public static final int badDataFormat = 0x04000000; + public static final int wrongAuthority = 0x02000000; + public static final int incorrectData = 0x01000000; + public static final int missingTimeStamp = 0x00800000; + + private PKIStatusInfo() { } + + /** + * @param status A PKIStatus constant. + * @param failInfo The bitwise AND of the PKIFailureInfo constants. + */ + public PKIStatusInfo(int status, int failInfo) { + this.status = new INTEGER(status); + statusString = new SEQUENCE(); + this.failInfo = failInfo; + hasFailInfo = true; + } + + /** + * Create a PKIStatusInfo with no failure info. + * @param status A PKIStatus constant. + * @param failInfo The bitwise AND of the PKIFailureInfo constants. + */ + public PKIStatusInfo(int status) { + this.status = new INTEGER(status); + statusString = new SEQUENCE(); + hasFailInfo = false; + } + + /** + * Sets the statusString field. May be null, since this + * field is optional. + */ + public void setStatusString(SEQUENCE statusString) { + this.statusString = statusString; + } + + /** + * Adds a string to the statusString SEQUENCE. + */ + public void addFreeText(String s) { + try { + statusString.addElement( new UTF8String(s) ); + } catch( java.io.CharConversionException e ) { + Assert.notReached("Error encoding to UTF8"); + } + } + + /** + * Adds a UTF8String to the statusString SEQUENCE. + */ + public void addFreeText(UTF8String s) { + statusString.addElement( s ); + } + + public static final Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + encode(TAG, ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + SEQUENCE seq = new SEQUENCE(); + + seq.addElement(status); + if( statusString.size() > 0 ) { + seq.addElement( statusString ); + } + + if(hasFailInfo) { + // convert failInfo to BIT_STRING + byte[] bytes = new byte[2]; + bytes[0] = (byte) ((failInfo & 0xff000000) >>> 24); + bytes[1] = (byte) ((failInfo & 0x00ff0000) >>> 16); + int padCount = 7; // 7 unused bits + BIT_STRING bs = new BIT_STRING(bytes, padCount); + seq.addElement( bs ); + } + + seq.encode(implicitTag, ostream); + } + + private static final Template templateInstance = new Template(); + public static Template getTemplate() { + return templateInstance; + } + + + public static class Template implements ASN1Template { + + private SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + seqt.addElement( INTEGER.getTemplate() ); + seqt.addElement(new SEQUENCE.OF_Template(UTF8String.getTemplate())); + seqt.addElement( BIT_STRING.getTemplate() ); + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws InvalidBERException, IOException { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws InvalidBERException, IOException { + + PKIStatusInfo psi; + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); + + BIT_STRING failInfo = (BIT_STRING) seq.elementAt(2); + + if( failInfo == null ) { + psi = new PKIStatusInfo(((INTEGER)seq.elementAt(0)).intValue()); + } else { + BitSet bs = failInfo.toBitSet(); + int failinfo = 0; + for(int i = 0, bit = 0x80000000; bit > 0; i++, bit >>>= 1 ) { + if( bs.get(i) ) { + failinfo |= bit; + } + } + psi = new PKIStatusInfo(((INTEGER)seq.elementAt(0)).intValue(), + failinfo); + } + + psi.setStatusString( (SEQUENCE) seq.elementAt(1) ); + + return psi; + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cmmf/RevRepContent.java b/mozilla/security/jss/org/mozilla/jss/pkix/cmmf/RevRepContent.java new file mode 100644 index 00000000000..6bf01b615d4 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cmmf/RevRepContent.java @@ -0,0 +1,176 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.pkix.cmmf; + +import com.netscape.jss.asn1.*; +import java.io.*; +import com.netscape.jss.pkix.crmf.CertId; + +/** + * CMMF RevRepContent. + *
+ * RevRepContent ::= SEQUENCE {
+ *    status          SEQUENCE SIZE (1..MAX) OF PKIStatusInfo,
+ *      -- in same order as was sent in RevReqContent
+ *    revCerts        [0] SEQUENCE SIZE (1..MAX) OF CertId OPTIONAL,
+ *      -- IDs for which revocation was requested (same order as status)
+ *    crls            [1] SEQUENCE SIZE (1..MAX) OF CertificateList OPTIONAL
+ *      -- the resulting CRLs (there may be more than one) }
+ * 
+ */ +public class RevRepContent implements ASN1Value { + + /////////////////////////////////////////////////////////////////////// + // members and member access + /////////////////////////////////////////////////////////////////////// + private SEQUENCE status; + private SEQUENCE revCerts; // may be null + private SEQUENCE crls; // may be null + private SEQUENCE sequence; // for encoding + + /** + * The status field, which is a SEQUENCE + * of PKIStatusInfo. + * + * @see com.netscape.jss.pkix.cmmf.PKIStatusInfo + */ + public SEQUENCE getStatus() { + return status; + } + + /** + * The revCerts field, which is a SEQUENCE + * of CertId. Returns null if this + * field is not present. + * + * @see com.netscape.jss.pkix.crmf.CertId + */ + public SEQUENCE getRevCerts() { + return revCerts; + } + + /** + * The crls field, which is a SEQUENCE of + * ANY. Returns null if this field + * is not present. + */ + public SEQUENCE getCrls() { + return crls; + } + + /////////////////////////////////////////////////////////////////////// + // Constructors + /////////////////////////////////////////////////////////////////////// + + private RevRepContent() { } + + /** + * Creates a new RevRepContent from its components. + * + * @param status A SEQUENCE of PKIStatusInfo. + * @param revCerts A SEQUENCE of CertId. This + * field is optional, so null may be used. + * @param crls A SEQUENCE of ANY. This field + * is optional, so null may be used. + * @see com.netscape.jss.pkix.cmmf.PKIStatusInfo + */ + public RevRepContent(SEQUENCE status, SEQUENCE revCerts, SEQUENCE crls) { + + sequence = new SEQUENCE(); + + this.status = status; + sequence.addElement(status); + + this.revCerts = revCerts; + sequence.addElement(Tag.get(0), revCerts); + + this.crls = crls; + sequence.addElement(Tag.get(1), crls); + + } + + /////////////////////////////////////////////////////////////////////// + // encoding/decoding + /////////////////////////////////////////////////////////////////////// + + private static final Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + sequence.encode(ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException { + sequence.encode(implicitTag, ostream); + } + + + /** + * A Template for decoding a RevRepContent. + */ + public static class Template implements ASN1Template { + private SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + seqt.addElement( new SEQUENCE.OF_Template( + PKIStatusInfo.getTemplate() ) ); + seqt.addOptionalElement( new SEQUENCE.OF_Template( + CertId.getTemplate() ) ); + seqt.addOptionalElement( new SEQUENCE.OF_Template( + ANY.getTemplate() ) ); + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws InvalidBERException, IOException { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws InvalidBERException, IOException { + + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); + + return new RevRepContent( (SEQUENCE) seq.elementAt(0), + (SEQUENCE) seq.elementAt(1), + (SEQUENCE) seq.elementAt(2) ); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cmmf/RevRequest.java b/mozilla/security/jss/org/mozilla/jss/pkix/cmmf/RevRequest.java new file mode 100644 index 00000000000..44555da0cbc --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cmmf/RevRequest.java @@ -0,0 +1,261 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkix.cmmf; + +import com.netscape.jss.asn1.*; +import java.io.*; + +/** + * CMMF RevRequest. + *
+ * RevRequest ::= SEQUENCE {
+ *      issuerName      Name,
+ *      serialNumber    INTEGER,
+ *      reason          CRLReason,
+ *      passphrase      OCTET STRING OPTIONAL,
+ *      comment         UTF8String OPTIONAL }
+ * 
+ */ +public class RevRequest implements ASN1Value { + + /////////////////////////////////////////////////////////////////////// + // Constants + /////////////////////////////////////////////////////////////////////// + + /** + * A CRLReason, which can be used in the reason + * field. + */ + public static final ENUMERATED unspecified = new ENUMERATED(0); + /** + * A CRLReason, which can be used in the reason + * field. + */ + public static final ENUMERATED keyCompromise = new ENUMERATED(1); + /** + * A CRLReason, which can be used in the reason + * field. + */ + public static final ENUMERATED cACompromise = new ENUMERATED(2); + /** + * A CRLReason, which can be used in the reason + * field. + */ + public static final ENUMERATED affiliationChanged = new ENUMERATED(3); + /** + * A CRLReason, which can be used in the reason + * field. + */ + public static final ENUMERATED superseded = new ENUMERATED(4); + /** + * A CRLReason, which can be used in the reason + * field. + */ + public static final ENUMERATED cessationOfOperation = new ENUMERATED(5); + /** + * A CRLReason, which can be used in the reason + * field. + */ + public static final ENUMERATED certificateHold = new ENUMERATED(6); + /** + * A CRLReason, which can be used in the reason + * field. + */ + public static final ENUMERATED removeFromCRL = new ENUMERATED(8); + + + /////////////////////////////////////////////////////////////////////// + // Members and member access + /////////////////////////////////////////////////////////////////////// + private ANY issuerName; + private INTEGER serialNumber; + private ENUMERATED reason; + private OCTET_STRING passphrase; // may be null + private UTF8String comment; // may be null + private SEQUENCE sequence; + + /** + * Returns the issuerName field as an ANY. + */ + public ANY getIssuerName() { + return issuerName; + } + + /** + * Returns the serialNumber field. + */ + public INTEGER getSerialNumber() { + return serialNumber; + } + + /** + * Returns the reason field, which should indicate the + * reason for the revocation. The currently supported reasons are: + *
+     * CRLReason ::= ENUMERATED {
+     *      unspecified             (0),
+     *      keyCompromise           (1),
+     *      cACompromise            (2),
+     *      affiliationChanged      (3),
+     *      superseded              (4),
+     *      cessationOfOperation    (5),
+     *      certificateHold         (6),
+     *      removeFromCRL           (8) }
+     * 
+ * These are all defined as constants in this class. + */ + public ENUMERATED getReason() { + return reason; + } + + /** + * Returns the passphrase field. Returns + * null if the field is not present. + */ + public OCTET_STRING getPassphrase() { + return passphrase; + } + + /** + * Returns the comment field. Returns null + * if the field is not present. + */ + public UTF8String getComment() { + return comment; + } + + /////////////////////////////////////////////////////////////////////// + // Constructors + /////////////////////////////////////////////////////////////////////// + + private RevRequest() { } + + + /** + * Constructs a new RevRequest from its components. + * + * @param issuerName The issuerName field. + * @param serialNumber The serialNumber field. + * @param reason The reason field. The constants defined + * in this class may be used. + * @param passphrase The passphrase field. This field is + * optional, so null may be used. + * @param comment The comment field. This field is optional, + * so null may be used. + */ + public RevRequest(ANY issuerName, INTEGER serialNumber, + ENUMERATED reason, OCTET_STRING passphrase, + UTF8String comment) { + if( issuerName==null || serialNumber==null || reason==null ) { + throw new IllegalArgumentException( + "parameter to RevRequest constructor is null"); + } + sequence = new SEQUENCE(); + + this.issuerName = issuerName; + sequence.addElement(issuerName); + + this.serialNumber = serialNumber; + sequence.addElement(serialNumber); + + this.reason = reason; + sequence.addElement(reason); + + this.passphrase = passphrase; + sequence.addElement(passphrase); + + this.comment = comment; + sequence.addElement(comment); + } + + + /////////////////////////////////////////////////////////////////////// + // encoding/decoding + /////////////////////////////////////////////////////////////////////// + + private static final Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + sequence.encode(ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException { + sequence.encode(implicitTag, ostream); + } + + + + /** + * A Template class for decoding a RevRequest. + */ + public static class Template implements ASN1Template { + + private SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + seqt.addElement(ANY.getTemplate()); + seqt.addElement(INTEGER.getTemplate()); + seqt.addElement(ENUMERATED.getTemplate()); + seqt.addOptionalElement(OCTET_STRING.getTemplate()); + seqt.addOptionalElement(UTF8String.getTemplate()); + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws InvalidBERException, IOException { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws InvalidBERException, IOException { + + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); + + return new RevRequest( (ANY) seq.elementAt(0), + (INTEGER) seq.elementAt(1), + (ENUMERATED) seq.elementAt(2), + (OCTET_STRING) seq.elementAt(3), + (UTF8String) seq.elementAt(4) ); + + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cmmf/manifest.mn b/mozilla/security/jss/org/mozilla/jss/pkix/cmmf/manifest.mn new file mode 100644 index 00000000000..43182055224 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cmmf/manifest.mn @@ -0,0 +1,77 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +CORE_DEPTH = ../../../../../.. + +MODULE = ninja + +NS_USE_JDK = 1 + +PACKAGE = com/netscape/jss/pkix/cmmf + +# These are meant to be used within Ninja only. +PRIVATE_EXPORTS = \ + $(NULL) + +JNI_GEN = \ + $(NULL) + +CLASSES = \ + CertifiedKeyPair \ + CertOrEncCert \ + CertRepContent \ + CertResponse \ + GetCRL \ + IssuerAndSubject \ + PKIStatusInfo \ + RevRepContent \ + RevRequest \ + $(NULL) + +PRIVATE_CLASSES = \ + $(NULL) + + +JSRCS = \ + CertifiedKeyPair.java \ + CertOrEncCert.java \ + CertRepContent.java \ + CertResponse.java \ + GetCRL.java \ + IssuerAndSubject.java \ + PKIStatusInfo.java \ + RevRepContent.java \ + RevRequest.java \ + $(NULL) + +PRIVATE_JSRCS = diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cmmf/package.html b/mozilla/security/jss/org/mozilla/jss/pkix/cmmf/package.html new file mode 100644 index 00000000000..b4185864055 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cmmf/package.html @@ -0,0 +1,37 @@ + + + +The PKIX CMMF protocol. + + diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cms/ContentInfo.java b/mozilla/security/jss/org/mozilla/jss/pkix/cms/ContentInfo.java new file mode 100644 index 00000000000..9e76732cfa7 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cms/ContentInfo.java @@ -0,0 +1,267 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.pkix.cms; + +import java.io.*; +import com.netscape.jss.asn1.*; +import java.util.Vector; +import com.netscape.jss.util.Assert; +import java.math.BigInteger; +import java.io.ByteArrayInputStream; + +/** + * A PKCS #7 ContentInfo structure. + */ +public class ContentInfo implements ASN1Value { + + public static final Tag TAG = SEQUENCE.TAG; // XXX is this right? + + + public static OBJECT_IDENTIFIER DATA = + new OBJECT_IDENTIFIER(new long[] { 1, 2, 840, 113549, 1, 7, 1 }); + public static OBJECT_IDENTIFIER SIGNED_DATA = + new OBJECT_IDENTIFIER(new long[] { 1, 2, 840, 113549, 1, 7, 2 }); + public static OBJECT_IDENTIFIER ENVELOPED_DATA = + new OBJECT_IDENTIFIER(new long[] { 1, 2, 840, 113549, 1, 7, 3 }); + public static OBJECT_IDENTIFIER SIGNED_AND_ENVELOPED_DATA = + new OBJECT_IDENTIFIER(new long[] { 1, 2, 840, 113549, 1, 7, 4 }); + public static OBJECT_IDENTIFIER DIGESTED_DATA = + new OBJECT_IDENTIFIER(new long[] { 1, 2, 840, 113549, 1, 7, 5 }); + public static OBJECT_IDENTIFIER ENCRYPTED_DATA = + new OBJECT_IDENTIFIER(new long[] { 1, 2, 840, 113549, 1, 7, 6 }); + + + + + + private OBJECT_IDENTIFIER contentType; + private ANY content; + private SEQUENCE sequence = new SEQUENCE(); + + private ContentInfo() {} + + /** + * Creates a ContentInfo with the given type and content. + * + * @param contentType The contentType of the ContentInfo. + * @param content The content of the ContentInfo. May be null + * to signify that the optional content field is not present. + */ + public ContentInfo(OBJECT_IDENTIFIER contentType, ASN1Value content) { + this.contentType = contentType; + sequence.addElement(contentType); + if (content != null) { + if( content instanceof ANY ) { + this.content = (ANY) content; + } else { + // convert content to ANY + try { + this.content = (ANY) ASN1Util.decode(ANY.getTemplate(), + ASN1Util.encode(content) ); + } catch(InvalidBERException e) { + Assert.notReached("InvalidBERException while converting"+ + "ASN1Value to ANY"); + } + } + sequence.addElement(new EXPLICIT(new Tag(0),content) ); + } + } + + /** + * Creates a ContentInfo of type data. + */ + public ContentInfo(byte[] data) { + this( DATA, new OCTET_STRING(data) ); + } + + /** + * Creates a ContentInfo of type signedData. + */ + public ContentInfo(SignedData sd) { + this( SIGNED_DATA, sd); + } + + /** + * Creates a ContentInfo of type envelopedData. + */ + public ContentInfo(EnvelopedData ed) { + this( ENVELOPED_DATA, ed ); + } + + /** + * Creates a ContentInfo of type signedAndEnvelopedData. + */ + public ContentInfo(SignedAndEnvelopedData sed) { + this( SIGNED_AND_ENVELOPED_DATA, sed ); + } + + /** + * Creates a ContentInfo of type digestedData. + */ + public ContentInfo(DigestedData dd) { + this( DIGESTED_DATA, dd ); + } + + /** + * Creates a ContentInfo of type encryptedData. + */ + public ContentInfo(EncryptedData ed) { + this( ENCRYPTED_DATA, ed ); + } + + /** + * Returns the contentType field, which determines what kind of content + * is contained in this ContentInfo. It will usually be one of the six + * predefined types, but may also be a user-defined type. + */ + public OBJECT_IDENTIFIER getContentType() { + return contentType; + } + + /** + * Returns true if the content field is present. + */ + public boolean hasContent() { + return (content != null); + } + + /** + * Returns the content, interpreted based on its type. If there is no + * content, null is returned. + *

If the contentType is + * one of the six standard types, the returned object will be of that + * type. For example, if the ContentInfo has contentType signedData, + * a SignedData object will be returned. If the contentType is data, + * an OCTET_STRING will be returned. + *

If the contentType is not one of the six standard types, + * the returned object will be an ANY. + * + */ + public ASN1Value getInterpretedContent() throws InvalidBERException { + if(contentType.equals(DATA)) { + return content.decodeWith( new OCTET_STRING.Template() ); + } else if( contentType.equals(SIGNED_DATA) ) { + return content.decodeWith( new SignedData.Template() ); + } else if( contentType.equals(ENVELOPED_DATA) ) { + return content.decodeWith( new EnvelopedData.Template()); + } else if( contentType.equals(SIGNED_AND_ENVELOPED_DATA) ) { + return content.decodeWith( + new SignedAndEnvelopedData.Template() ); + } else if( contentType.equals(DIGESTED_DATA) ) { + return content.decodeWith( new DigestedData.Template() ); + } else if( contentType.equals(ENCRYPTED_DATA) ) { + return content.decodeWith( new EncryptedData.Template()); + } else { + // unknown type + return content; + } + } + + /** + * Returns the content encoded as an ANY. If there is no content, + * null is returned. + */ + public ANY getContent() { + return content; + } + + public void encode(OutputStream ostream) throws IOException { + encode(getTag(),ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + sequence.encode(implicitTag,ostream); + } + + public Tag getTag() { + return ContentInfo.TAG; + } + + /** + * Returns a singleton instance of a decoding template for ContentInfo. + */ + public static Template getTemplate() { + return templateInstance; + } + private static Template templateInstance = new Template(); + + /** + * A template for decoding a ContentInfo blob + * + */ + public static class Template implements ASN1Template { + public boolean tagMatch(Tag tag) { + return (tag.equals(ContentInfo.TAG)); + } + + private SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + seqt.addElement(new OBJECT_IDENTIFIER.Template()); + seqt.addOptionalElement( + new EXPLICIT.Template( + new Tag(0), new ANY.Template() + )); + } + + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + return decode(ContentInfo.TAG,istream); + } + + + public ASN1Value decode(Tag implicitTag, InputStream istream ) + throws IOException, InvalidBERException + { + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag,istream); + Assert.assert(seq.size() == 2); + ASN1Value content; + + if( seq.elementAt(1) == null ) { + content = null; + } else { + content = ((EXPLICIT)seq.elementAt(1)).getContent(); + } + + return new ContentInfo( + (OBJECT_IDENTIFIER) seq.elementAt(0), + content + ); + } + } // end of template + +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cms/DigestInfo.java b/mozilla/security/jss/org/mozilla/jss/pkix/cms/DigestInfo.java new file mode 100644 index 00000000000..aa2d1df3691 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cms/DigestInfo.java @@ -0,0 +1,153 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkix.cms; + +import com.netscape.jss.asn1.*; +import com.netscape.jss.pkix.primitive.*; +import java.io.*; +import com.netscape.jss.util.Assert; + +public class DigestInfo implements ASN1Value { + + private AlgorithmIdentifier digestAlgorithm; + private OCTET_STRING digest; + private SEQUENCE sequence; + + private DigestInfo() { } + + public DigestInfo(AlgorithmIdentifier digestAlgorithm, OCTET_STRING digest){ + if( digestAlgorithm==null || digest==null ) { + throw new IllegalArgumentException(); + } + sequence = new SEQUENCE(); + this.digestAlgorithm = digestAlgorithm; + sequence.addElement(digestAlgorithm); + this.digest = digest; + sequence.addElement(digest); + } + + public AlgorithmIdentifier + getDigestAlgorithm() { + return digestAlgorithm; + } + + public OCTET_STRING + getDigest() { + return digest; + } + + private static final Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + public boolean equals(Object obj) { + if( obj==null || !(obj instanceof DigestInfo)) { + return false; + } + DigestInfo di = (DigestInfo)obj; + + return byteArraysAreSame(di.digest.toByteArray(), digest.toByteArray()); + } + + /** + * Compares two non-null byte arrays. Returns true if they are identical, + * false otherwise. + */ + private static boolean byteArraysAreSame(byte[] left, byte[] right) { + + Assert.assert(left!=null && right!=null); + + if( left.length != right.length ) { + return false; + } + + for(int i = 0 ; i < left.length ; i++ ) { + if( left[i] != right[i] ) { + return false; + } + } + + return true; + } + + public void encode(OutputStream ostream) throws IOException { + sequence.encode(ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + sequence.encode(implicitTag, ostream); + } + + private static final Template templateInstance = new Template(); + public static Template getTemplate() { + return templateInstance; + } + + /** + * A class for decoding the BER encoding of a DigestInfo. + */ + public static class Template implements ASN1Template { + + private SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + seqt.addElement( AlgorithmIdentifier.getTemplate()); + seqt.addElement( OCTET_STRING.getTemplate() ); + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream ostream) + throws InvalidBERException, IOException + { + return decode(TAG, ostream); + } + + public ASN1Value decode(Tag implicitTag, InputStream ostream) + throws InvalidBERException, IOException + { + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, ostream); + + return new DigestInfo( + (AlgorithmIdentifier) seq.elementAt(0), + (OCTET_STRING) seq.elementAt(1) ); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cms/DigestedData.java b/mozilla/security/jss/org/mozilla/jss/pkix/cms/DigestedData.java new file mode 100644 index 00000000000..ef94944f83a --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cms/DigestedData.java @@ -0,0 +1,149 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkix.cms; + +import com.netscape.jss.asn1.*; +import com.netscape.jss.pkix.primitive.*; +import java.io.*; + +public class DigestedData implements ASN1Value { + + /////////////////////////////////////////////////////////////////////// + // members and member access + /////////////////////////////////////////////////////////////////////// + private INTEGER version; + private AlgorithmIdentifier digestAlgorithm; + private ContentInfo contentInfo; + private OCTET_STRING digest; + private SEQUENCE sequence; // for DER encoding + + public INTEGER getVersion() { + return version; + } + + public AlgorithmIdentifier getDigestAlgorithm() { + return digestAlgorithm; + } + + public ContentInfo getContentInfo() { + return contentInfo; + } + + public OCTET_STRING getDigest() { + return digest; + } + + /////////////////////////////////////////////////////////////////////// + // constructors + /////////////////////////////////////////////////////////////////////// + private DigestedData() { } + + public DigestedData(INTEGER version, AlgorithmIdentifier digestAlgorithm, + ContentInfo contentInfo, OCTET_STRING digest) + { + if( version==null || digestAlgorithm==null || contentInfo==null || + digest==null ) { + throw new IllegalArgumentException("DigestedData constructor" + +" parameter is null"); + } + + this.version = version; + this.digestAlgorithm = digestAlgorithm; + this.contentInfo = contentInfo; + this.digest = digest; + + sequence = new SEQUENCE(); + sequence.addElement(version); + sequence.addElement(digestAlgorithm); + sequence.addElement(contentInfo); + sequence.addElement(digest); + } + + /////////////////////////////////////////////////////////////////////// + // DER encoding + /////////////////////////////////////////////////////////////////////// + + private static final Tag TAG = SEQUENCE.TAG; + + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + sequence.encode(ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException { + sequence.encode(implicitTag, ostream); + } + + /** + * A Template for decoding BER-encoded DigestData items. + */ + public static class Template implements ASN1Template { + + private SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + + seqt.addElement( INTEGER.getTemplate() ); + seqt.addElement( AlgorithmIdentifier.getTemplate() ); + seqt.addElement( ContentInfo.getTemplate() ); + seqt.addElement( OCTET_STRING.getTemplate() ); + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws InvalidBERException, IOException { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws InvalidBERException, IOException { + + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); + + return new DigestedData( + (INTEGER) seq.elementAt(0), + (AlgorithmIdentifier) seq.elementAt(1), + (ContentInfo) seq.elementAt(2), + (OCTET_STRING) seq.elementAt(3) ); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cms/EncapsulatedContentInfo.java b/mozilla/security/jss/org/mozilla/jss/pkix/cms/EncapsulatedContentInfo.java new file mode 100644 index 00000000000..dd46f906b5c --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cms/EncapsulatedContentInfo.java @@ -0,0 +1,173 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.pkix.cms; + +import java.io.*; +import com.netscape.jss.asn1.*; +import java.util.Vector; +import com.netscape.jss.util.Assert; +import java.math.BigInteger; +import java.io.ByteArrayInputStream; + +/** + * A CMS EncapsulatedContentInfo structure. + */ +public class EncapsulatedContentInfo implements ASN1Value { + + public static final Tag TAG = SEQUENCE.TAG; // XXX is this right? + + + private OBJECT_IDENTIFIER contentType; + private OCTET_STRING content; + private SEQUENCE sequence = new SEQUENCE(); + + private EncapsulatedContentInfo() {} + + /** + * Creates a EncapsulatedContentInfo with the given type and content. + * + * @param contentType The contentType of the EncapsulatedContentInfo. + * @param content The content of the EncapsulatedContentInfo. May be null + * to signify that the optional content field is not present. + */ + public EncapsulatedContentInfo(OBJECT_IDENTIFIER contentType, ASN1Value content) { + this.contentType = contentType; + sequence.addElement(contentType); + if (content != null) { + if( content instanceof OCTET_STRING) { + this.content = (OCTET_STRING) content; + } else { + // convert content to OCTET_STRING + this.content = (OCTET_STRING) new OCTET_STRING( + ASN1Util.encode(content) ); + } + sequence.addElement(new EXPLICIT(new Tag(0), this.content) ); + } + } + + /** + * Returns the contentType field, which determines what kind of content + * is contained in this EncapsulatedContentInfo. + */ + public OBJECT_IDENTIFIER getContentType() { + return contentType; + } + + /** + * Returns true if the content field is present. + */ + public boolean hasContent() { + return (content != null); + } + + /** + * Returns the content encoded as an OCTET_STRING. If there is no content, + * null is returned. + */ + public OCTET_STRING getContent() { + return content; + } + + public void encode(OutputStream ostream) throws IOException { + encode(getTag(),ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + sequence.encode(implicitTag,ostream); + } + + public Tag getTag() { + return EncapsulatedContentInfo.TAG; + } + + /** + * Returns a singleton instance of a decoding template for EncapsulatedContentInfo. + */ + public static Template getTemplate() { + return templateInstance; + } + private static Template templateInstance = new Template(); + + /** + * A template for decoding a EncapsulatedContentInfo blob + * + */ + public static class Template implements ASN1Template { + public boolean tagMatch(Tag tag) { + return (tag.equals(EncapsulatedContentInfo.TAG)); + } + + private SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + seqt.addElement(new OBJECT_IDENTIFIER.Template()); + seqt.addOptionalElement( + new EXPLICIT.Template( + new Tag(0), new OCTET_STRING.Template() + )); + } + + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + return decode(EncapsulatedContentInfo.TAG,istream); + } + + + public ASN1Value decode(Tag implicitTag, InputStream istream ) + throws IOException, InvalidBERException + { + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag,istream); + Assert.assert(seq.size() == 2); + ASN1Value content; + + if( seq.elementAt(1) == null ) { + content = null; + } else { + content = ((EXPLICIT)seq.elementAt(1)).getContent(); + } + + return new EncapsulatedContentInfo( + (OBJECT_IDENTIFIER) seq.elementAt(0), + content + ); + } + } // end of template + +} + + + diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cms/EncryptedContentInfo.java b/mozilla/security/jss/org/mozilla/jss/pkix/cms/EncryptedContentInfo.java new file mode 100644 index 00000000000..cd66256c200 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cms/EncryptedContentInfo.java @@ -0,0 +1,352 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.pkix.cms; + +import com.netscape.jss.pkix.primitive.*; + +import java.io.*; +import com.netscape.jss.asn1.*; +import java.util.Vector; +import com.netscape.jss.util.Assert; +import java.math.BigInteger; +import java.io.ByteArrayInputStream; +import com.netscape.jss.crypto.*; +import java.security.*; +import java.security.spec.AlgorithmParameterSpec; +import com.netscape.jss.util.Password; +import com.netscape.jss.CryptoManager; + +/** + * The PKCS #7 type EncryptedContentInfo, which encapsulates + * encrypted data. + */ +public class EncryptedContentInfo implements ASN1Value { + + /////////////////////////////////////////////////////////////////////// + // members and member access + /////////////////////////////////////////////////////////////////////// + private OBJECT_IDENTIFIER contentType; + private AlgorithmIdentifier contentEncryptionAlgorithm; + private OCTET_STRING encryptedContent; // may be null + + private SEQUENCE sequence = new SEQUENCE(); + + public OBJECT_IDENTIFIER getContentType() { + return contentType; + } + + public AlgorithmIdentifier getContentEncryptionAlgorithm() { + return contentEncryptionAlgorithm; + } + + public OCTET_STRING getEncryptedContent() { + return encryptedContent; + } + + public boolean hasEncryptedContent() { + return (encryptedContent!=null); + } + + /////////////////////////////////////////////////////////////////////// + // Constructors + /////////////////////////////////////////////////////////////////////// + private EncryptedContentInfo() { + } + + /** + * Create a EnvelopedData ASN1 object. + */ + public EncryptedContentInfo( + OBJECT_IDENTIFIER contentType, + AlgorithmIdentifier contentEncryptionAlgorithm, + OCTET_STRING encryptedContent) + { + this(contentType, + contentEncryptionAlgorithm, + encryptedContent, + false); + + } + + public EncryptedContentInfo( + OBJECT_IDENTIFIER contentType, + AlgorithmIdentifier contentEncryptionAlgorithm, + OCTET_STRING encryptedContent, + boolean createHackedCRSCompatibleECI) + { + this.contentType = contentType; + this.contentEncryptionAlgorithm = contentEncryptionAlgorithm; + this.encryptedContent = encryptedContent; + + sequence.addElement(contentType); + sequence.addElement(contentEncryptionAlgorithm); + if(encryptedContent != null) { + if (createHackedCRSCompatibleECI) { + sequence.addElement(new EXPLICIT(new Tag(0), encryptedContent)); + } + else { + sequence.addElement(new Tag(0), encryptedContent); + } + } + } + + public static EncryptedContentInfo createCRSCompatibleEncryptedContentInfo(OBJECT_IDENTIFIER contentType, + AlgorithmIdentifier contentEncryptionAlgorithm, + OCTET_STRING encryptedContent) + { + return new EncryptedContentInfo(contentType, + contentEncryptionAlgorithm, + encryptedContent, + true); + } + + + /////////////////////////////////////////////////////////////////////// + // Crypto shortcuts + /////////////////////////////////////////////////////////////////////// + + /** + * Creates a new EncryptedContentInfo, where the data is encrypted + * with a password-based key. + * + * @param keyGenAlg The algorithm for generating a symmetric key from + * a password, salt, and iteration count. + * @param password The password to use in generating the key. + * @param salt The salt to use in generating the key. + * @param iterationCount The number of hashing iterations to perform + * while generating the key. + * @param charToByteConverter The mechanism for converting the characters + * in the password into bytes. If null, the default mechanism + * will be used, which is UTF8. + * @param toBeEncrypted The bytes to be encrypted and stored in the + * EncryptedContentInfo. Before they are encrypted, they will be + * padded using PKCS padding. + */ + public static EncryptedContentInfo + createPBE(PBEAlgorithm keyGenAlg, Password password, byte[] salt, + int iterationCount, + KeyGenerator.CharToByteConverter charToByteConverter, + byte[] toBeEncrypted) + throws CryptoManager.NotInitializedException, NoSuchAlgorithmException, + InvalidKeyException, InvalidAlgorithmParameterException, TokenException, + CharConversionException + { + + try { + + // check key gen algorithm + if( ! (keyGenAlg instanceof PBEAlgorithm) ) { + throw new NoSuchAlgorithmException("Key generation algorithm"+ + " is not a PBE algorithm"); + } + PBEAlgorithm pbeAlg = (PBEAlgorithm) keyGenAlg; + + CryptoManager cman = CryptoManager.getInstance(); + + // generate key + CryptoToken token = cman.getInternalCryptoToken(); + KeyGenerator kg = token.getKeyGenerator( keyGenAlg ); + PBEKeyGenParams pbekgParams = new PBEKeyGenParams( + password, salt, iterationCount); + if( charToByteConverter != null ) { + kg.setCharToByteConverter( charToByteConverter ); + } + kg.initialize(pbekgParams); + SymmetricKey key = kg.generate(); + + // generate IV + EncryptionAlgorithm encAlg = pbeAlg.getEncryptionAlg(); + AlgorithmParameterSpec params=null; + if( encAlg.getParameterClass().equals( IVParameterSpec.class ) ) { + params = new IVParameterSpec( kg.generatePBE_IV() ); + } + + // perform encryption + Cipher cipher = token.getCipherContext( encAlg ); + cipher.initEncrypt( key, params ); + byte[] encrypted = cipher.doFinal( Cipher.pad( + toBeEncrypted, encAlg.getBlockSize()) ); + + // make encryption algorithm identifier + PBEParameter pbeParam = new PBEParameter( salt, iterationCount ); + AlgorithmIdentifier encAlgID = new AlgorithmIdentifier( + keyGenAlg.toOID(), pbeParam); + + // create EncryptedContentInfo + EncryptedContentInfo encCI = new EncryptedContentInfo( + ContentInfo.DATA, + encAlgID, + new OCTET_STRING(encrypted) ); + + return encCI; + + } catch( IllegalBlockSizeException e ) { + Assert.notReached("IllegalBlockSizeException in EncryptedContentInfo" + +".createPBE"); + } catch( BadPaddingException e ) { + Assert.notReached("BadPaddingException in EncryptedContentInfo" + +".createPBE"); + } + return null; + } + + /** + * Decrypts the content of an EncryptedContentInfo encrypted with a + * PBE key. + * + * @param pass The password to use in generating the PBE decryption key. + * @param charToByteConverter The converter for converting the password + * characters into bytes. May be null to use the default. + * @return The decrypted contents of the EncryptedContentInfo. The contents + * are first unpadded using the PKCS padding mechanism. + */ + public byte[] + decrypt(Password pass, KeyGenerator.CharToByteConverter charToByteConverter) + throws IllegalStateException,CryptoManager.NotInitializedException, + NoSuchAlgorithmException, InvalidBERException, IOException, + InvalidKeyException, InvalidAlgorithmParameterException, TokenException, + IllegalBlockSizeException, BadPaddingException + { + if( encryptedContent == null ) { + return null; + } + + // get the key gen parameters + AlgorithmIdentifier algid = contentEncryptionAlgorithm; + KeyGenAlgorithm kgAlg = KeyGenAlgorithm.fromOID( algid.getOID() ); + if( !(kgAlg instanceof PBEAlgorithm) ) { + throw new NoSuchAlgorithmException("KeyGenAlgorithm is not a"+ + " PBE algorithm"); + } + ASN1Value params = algid.getParameters(); + if( params == null ) { + throw new InvalidAlgorithmParameterException( + "PBE algorithms require parameters"); + } + PBEParameter pbeParams; + if( params instanceof PBEParameter) { + pbeParams = (PBEParameter) params; + } else { + byte[] encodedParams = ASN1Util.encode(params); + pbeParams = (PBEParameter) + ASN1Util.decode( PBEParameter.getTemplate(), encodedParams ); + } + PBEKeyGenParams kgp = new PBEKeyGenParams(pass, + pbeParams.getSalt(), pbeParams.getIterations() ); + + + // compute the key and IV + CryptoToken token = + CryptoManager.getInstance().getInternalCryptoToken(); + KeyGenerator kg = token.getKeyGenerator( kgAlg ); + if( charToByteConverter != null ) { + kg.setCharToByteConverter( charToByteConverter ); + } + kg.initialize( kgp ); + SymmetricKey key = kg.generate(); + + // compute algorithm parameters + EncryptionAlgorithm encAlg = ((PBEAlgorithm)kgAlg).getEncryptionAlg(); + AlgorithmParameterSpec algParams; + if( encAlg.getParameterClass().equals( IVParameterSpec.class ) ) { + algParams = new IVParameterSpec( kg.generatePBE_IV() ); + } else { + algParams = null; + } + + // perform the decryption + Cipher cipher = token.getCipherContext( encAlg ); + cipher.initDecrypt(key, algParams); + return Cipher.unPad(cipher.doFinal( encryptedContent.toByteArray() )); + } + + + /////////////////////////////////////////////////////////////////////// + // DER encoding + /////////////////////////////////////////////////////////////////////// + + private static final Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + encode(getTag(),ostream); + } + + public void encode(Tag tag, OutputStream ostream) throws IOException { + sequence.encode(tag,ostream); + } + + public static Template getTemplate() { + return templateInstance; + } + private static final Template templateInstance = new Template(); + + /** + * A template file for decoding a EnvelopedData blob + * + */ + + public static class Template implements ASN1Template { + + public boolean tagMatch(Tag tag) { + return (tag.equals(EncryptedContentInfo.TAG)); + } + + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + return decode(TAG,istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws IOException, InvalidBERException + { + SEQUENCE.Template seqt = new SEQUENCE.Template(); + seqt.addElement(new OBJECT_IDENTIFIER.Template()); + seqt.addElement(new AlgorithmIdentifier.Template()); + seqt.addOptionalElement(new Tag(0), new OCTET_STRING.Template()); + + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag,istream); + Assert.assert(seq.size() ==3); + + return new EncryptedContentInfo( + (OBJECT_IDENTIFIER) seq.elementAt(0), + (AlgorithmIdentifier) seq.elementAt(1), + (OCTET_STRING) seq.elementAt(2) + ); + } + } // end of template + +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cms/EncryptedData.java b/mozilla/security/jss/org/mozilla/jss/pkix/cms/EncryptedData.java new file mode 100644 index 00000000000..0926f69d9b9 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cms/EncryptedData.java @@ -0,0 +1,160 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkix.cms; + +import com.netscape.jss.asn1.*; +import java.io.*; + +/** + * The PKCS #7 structure EncryptedData. + */ +public class EncryptedData implements ASN1Value { + + /////////////////////////////////////////////////////////////////////// + // Members + /////////////////////////////////////////////////////////////////////// + private INTEGER version; + private EncryptedContentInfo encryptedContentInfo; + private SEQUENCE sequence; + + /** + * The default version number. This should always be used unless + * you really know what you are doing. + */ + public static final INTEGER DEFAULT_VERSION = new INTEGER(0); + + /////////////////////////////////////////////////////////////////////// + // Constructors + /////////////////////////////////////////////////////////////////////// + private EncryptedData() { } + + /** + * Creates a new EncryptedData. + * + * @param version Should usually be DEFAULT_VERSION unless you are being + * very clever. + */ + public EncryptedData( INTEGER version, + EncryptedContentInfo encryptedContentInfo ) + { + if( version == null || encryptedContentInfo == null ) { + throw new IllegalArgumentException("null parameter"); + } + + sequence = new SEQUENCE(); + + this.version = version; + sequence.addElement(version); + this.encryptedContentInfo = encryptedContentInfo; + sequence.addElement(encryptedContentInfo); + } + + /** + * Creates an EncryptedData with the default version. + */ + public EncryptedData( EncryptedContentInfo encryptedContentInfo ) { + this( DEFAULT_VERSION, encryptedContentInfo ); + } + + /////////////////////////////////////////////////////////////////////// + // Accessor Methods + /////////////////////////////////////////////////////////////////////// + public INTEGER getVersion() { + return version; + } + + public EncryptedContentInfo getEncryptedContentInfo() { + return encryptedContentInfo; + } + + + /////////////////////////////////////////////////////////////////////// + // DER encoding + /////////////////////////////////////////////////////////////////////// + + private static final Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + sequence.encode(ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + sequence.encode(implicitTag, ostream); + } + + public static Template getTemplate() { + return templateInstance; + } + private static final Template templateInstance = new Template(); + + /** + * A Template for decoding EncryptedData items. + */ + public static class Template implements ASN1Template { + + private SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + seqt.addElement( INTEGER.getTemplate() ); + seqt.addElement( EncryptedContentInfo.getTemplate() ); + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws InvalidBERException, IOException + { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws InvalidBERException, IOException + { + + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); + + return new EncryptedData( + (INTEGER) seq.elementAt(0), + (EncryptedContentInfo) seq.elementAt(1) ); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cms/EnvelopedData.java b/mozilla/security/jss/org/mozilla/jss/pkix/cms/EnvelopedData.java new file mode 100644 index 00000000000..ac04bbdb702 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cms/EnvelopedData.java @@ -0,0 +1,133 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.pkix.cms; + +import java.io.*; +import com.netscape.jss.asn1.*; +import java.util.Vector; +import com.netscape.jss.util.Assert; +import java.math.BigInteger; +import java.io.ByteArrayInputStream; + +public class EnvelopedData implements ASN1Value { + public static final Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + private INTEGER version; + private SET recipientInfos; + private EncryptedContentInfo encryptedContentInfo; + + private SEQUENCE sequence = new SEQUENCE(); + + public INTEGER getVersion() { + return version; + } + public SET getRecipientInfos() { + return recipientInfos; + } + public EncryptedContentInfo getEncryptedContentInfo() { + return encryptedContentInfo; + } + + + + private EnvelopedData() { + } + + /** + * Create a EnvelopedData ASN1 object. + */ + + public EnvelopedData( INTEGER version, SET recipientInfos, + EncryptedContentInfo encryptedContentInfo) { + + this.version = version; + this.recipientInfos = recipientInfos; + this.encryptedContentInfo = encryptedContentInfo; + + sequence.addElement(version); + sequence.addElement(recipientInfos); + sequence.addElement(encryptedContentInfo); + } + + public void encode(OutputStream ostream) throws IOException { + encode(getTag(),ostream); + } + + public void encode(Tag tag, OutputStream ostream) throws IOException { + sequence.encode(tag,ostream); + } + + + /** + * A template file for decoding a EnvelopedData blob + * + */ + + public static class Template implements ASN1Template { + public Tag getTag() { + return EnvelopedData.TAG; + } + + public boolean tagMatch(Tag tag) { + return (tag.equals(EnvelopedData.TAG)); + } + + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + return decode(getTag(),istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws IOException, InvalidBERException + { + SEQUENCE.Template seqt = new SEQUENCE.Template(); + seqt.addElement(new INTEGER.Template()); + seqt.addElement(new SET.OF_Template(new RecipientInfo.Template())); + seqt.addElement(new EncryptedContentInfo.Template()); + + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag,istream); + Assert.assert(seq.size() ==3); + + return new EnvelopedData( + (INTEGER) seq.elementAt(0), + (SET) seq.elementAt(1), + (EncryptedContentInfo) seq.elementAt(2) + ); + } + } // end of template + +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cms/IssuerAndSerialNumber.java b/mozilla/security/jss/org/mozilla/jss/pkix/cms/IssuerAndSerialNumber.java new file mode 100644 index 00000000000..baf2c922163 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cms/IssuerAndSerialNumber.java @@ -0,0 +1,150 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkix.cms; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; +import com.netscape.jss.asn1.*; +import com.netscape.jss.pkix.primitive.*; +import com.netscape.jss.util.Assert; + +/** + * An issuer name and serial number, used to uniquely identify a certificate. + */ +public class IssuerAndSerialNumber implements ASN1Value { + + /////////////////////////////////////////////////////////////////////// + // Members + /////////////////////////////////////////////////////////////////////// + private Name issuer; + private INTEGER serialNumber; + private SEQUENCE sequence; + + /////////////////////////////////////////////////////////////////////// + // Construction + /////////////////////////////////////////////////////////////////////// + + // no default constructor + private IssuerAndSerialNumber() { } + + /** + * Constructs an IssuerAndSerialNumber from its components. + * + * @param issuer Must not be null. + * @param serialNumber must not be null. + */ + public IssuerAndSerialNumber(Name issuer, INTEGER serialNumber) { + if(issuer==null || serialNumber==null) { + throw new IllegalArgumentException(); + } + sequence = new SEQUENCE(); + this.issuer = issuer; + sequence.addElement(issuer); + this.serialNumber = serialNumber; + sequence.addElement(serialNumber); + } + + /////////////////////////////////////////////////////////////////////// + // accessors + /////////////////////////////////////////////////////////////////////// + public Name getIssuer() { + return issuer; + } + + public INTEGER getSerialNumber() { + return serialNumber; + } + + /////////////////////////////////////////////////////////////////////// + // DER encoding + /////////////////////////////////////////////////////////////////////// + static Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + encode(TAG, ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + sequence.encode(implicitTag, ostream); + } + + /** + * Returns a singleton template instance. + */ + public static Template getTemplate() { + return templateInstance; + } + private static Template templateInstance = new Template(); + + /** + * A template for decoding an IssuerAndSerialNumber from its BER encoding. + */ + public static class Template implements ASN1Template { + private SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + seqt.addElement( Name.getTemplate() ); + seqt.addElement( INTEGER.getTemplate() ); + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws InvalidBERException, IOException + { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws InvalidBERException, IOException + { + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); + + Assert.assert(seq.size() == 2); + + return new IssuerAndSerialNumber( + (Name) seq.elementAt(0), + (INTEGER) seq.elementAt(1) ); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cms/Makefile b/mozilla/security/jss/org/mozilla/jss/pkix/cms/Makefile new file mode 100644 index 00000000000..bb06c14abbb --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cms/Makefile @@ -0,0 +1,74 @@ +#! gmake +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +####################################################################### +# (1) Include initial platform-independent assignments (MANDATORY). # +####################################################################### + +include manifest.mn + +####################################################################### +# (2) Include "global" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/config.mk + +####################################################################### +# (3) Include "component" configuration information. (OPTIONAL) # +####################################################################### +include $(CORE_DEPTH)/$(MODULE)/config/config.mk + + +####################################################################### +# (4) Include "local" platform-dependent assignments (OPTIONAL). # +####################################################################### + + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### + + diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cms/RecipientInfo.java b/mozilla/security/jss/org/mozilla/jss/pkix/cms/RecipientInfo.java new file mode 100644 index 00000000000..df7d31c4041 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cms/RecipientInfo.java @@ -0,0 +1,160 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.pkix.cms; + +import com.netscape.jss.pkix.primitive.*; + +import java.io.*; +import com.netscape.jss.asn1.*; +import java.util.Vector; +import com.netscape.jss.util.Assert; +import java.math.BigInteger; +import java.io.ByteArrayInputStream; + +public class RecipientInfo implements ASN1Value { + + public static final Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + private INTEGER version; + private IssuerAndSerialNumber issuerAndSerialNumber; + private AlgorithmIdentifier keyEncryptionAlgorithmID; + private OCTET_STRING encryptedKey; + + private SEQUENCE sequence = new SEQUENCE(); + + public INTEGER getVersion() { + return version; + } + public IssuerAndSerialNumber getissuerAndSerialNumber() { + return issuerAndSerialNumber; + } + public AlgorithmIdentifier getKeyEncryptionAlgorithmID() { + return keyEncryptionAlgorithmID; + } + public OCTET_STRING getEncryptedKey() { + return encryptedKey; + } + + + private static final Template templateInstance = new Template(); + + public static Template getTemplate() { + return templateInstance; + } + + + private RecipientInfo() { + } + + /** + * Create a RecipientInfo ASN1 object. + */ + + public RecipientInfo( INTEGER version, + IssuerAndSerialNumber issuerAndSerialNumber, + AlgorithmIdentifier keyEncryptionAlgorithmID, + OCTET_STRING encryptedKey) { + + Assert.assert(issuerAndSerialNumber != null); + Assert.assert(keyEncryptionAlgorithmID != null); + Assert.assert(encryptedKey != null); + + + this.version = version; + this.issuerAndSerialNumber = issuerAndSerialNumber; + this.keyEncryptionAlgorithmID = keyEncryptionAlgorithmID; + this.encryptedKey = encryptedKey; + + + sequence.addElement(version); + sequence.addElement(issuerAndSerialNumber); + sequence.addElement(keyEncryptionAlgorithmID); + sequence.addElement(encryptedKey); + + } + + public void encode(OutputStream ostream) throws IOException { + encode(getTag(),ostream); + } + + public void encode(Tag tag, OutputStream ostream) throws IOException { + sequence.encode(tag,ostream); + } + + + /** + * A template file for decoding a RecipientInfo blob + * + */ + + public static class Template implements ASN1Template { + public Tag getTag() { + return RecipientInfo.TAG; + } + + public boolean tagMatch(Tag tag) { + return (tag.equals(RecipientInfo.TAG)); + } + + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + return decode(getTag(),istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws IOException, InvalidBERException + { + SEQUENCE.Template seqt = new SEQUENCE.Template(); + seqt.addElement(new INTEGER.Template()); + seqt.addElement(new IssuerAndSerialNumber.Template()); + seqt.addElement(new AlgorithmIdentifier.Template()); + seqt.addElement(new OCTET_STRING.Template()); + + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag,istream); + Assert.assert(seq.size() ==4); + + return new RecipientInfo( + (INTEGER) seq.elementAt(0), + (IssuerAndSerialNumber) seq.elementAt(1), + (AlgorithmIdentifier) seq.elementAt(2), + (OCTET_STRING) seq.elementAt(3) + + ); + } + } // end of template + +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cms/SignedAndEnvelopedData.java b/mozilla/security/jss/org/mozilla/jss/pkix/cms/SignedAndEnvelopedData.java new file mode 100644 index 00000000000..be81cc9376c --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cms/SignedAndEnvelopedData.java @@ -0,0 +1,216 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkix.cms; + +import com.netscape.jss.asn1.*; +import com.netscape.jss.pkix.primitive.*; +import java.io.*; + +public class SignedAndEnvelopedData implements ASN1Value { + + /////////////////////////////////////////////////////////////////////// + // members and member access + /////////////////////////////////////////////////////////////////////// + private INTEGER version; + private SET recipientInfos; + private SET digestAlgorithms; + private EncryptedContentInfo encryptedContentInfo; + private SET certificates; // may be null + private SET crls; // may be null + private SET signerInfos; + private SEQUENCE sequence; // for encoding + + /** + * Returns the version number. The current version is 1. + */ + public INTEGER getVersion() { + return version; + } + + /** + * Returns a SET of RecipientInfo. + */ + public SET getRecipientInfos() { + return recipientInfos; + } + + /** + * Returns a SET of AlgorithmIdentifier. + */ + public SET getDigestAlgorithms() { + return digestAlgorithms; + } + + /** + * Returns the encrypted content. + */ + public EncryptedContentInfo getEncryptedContentInfo() { + return encryptedContentInfo; + } + + /** + * Returns a SET of ANYs. May return null if the + * certificates field is not present. + */ + public SET getCertificates() { + return certificates; + } + + /** + * Returns a SET of ANYs. May return null if the crls + * field is not present. + */ + public SET getCrls() { + return crls; + } + + /** + * Returns a SET of SignerInfo. + */ + public SET getSignerInfos() { + return signerInfos; + } + + /////////////////////////////////////////////////////////////////////// + // Constructors + /////////////////////////////////////////////////////////////////////// + + private SignedAndEnvelopedData() { } + + public SignedAndEnvelopedData( + INTEGER version, + SET recipientInfos, + SET digestAlgorithms, + EncryptedContentInfo encryptedContentInfo, + SET certificates, + SET crls, + SET signerInfos) + { + if( version==null || recipientInfos==null || digestAlgorithms==null + || encryptedContentInfo==null || signerInfos==null ) { + throw new IllegalArgumentException( + "SignedAndEnvelopedData constructor parameter is null"); + } + + this.version = version; + this.recipientInfos = recipientInfos; + this.digestAlgorithms = digestAlgorithms; + this.encryptedContentInfo = encryptedContentInfo; + this.certificates = certificates; + this.crls = crls; + this.signerInfos = signerInfos; + + sequence = new SEQUENCE(); + sequence.addElement(version); + sequence.addElement(recipientInfos); + sequence.addElement(digestAlgorithms); + sequence.addElement(encryptedContentInfo); + if( certificates!=null ) { + sequence.addElement(certificates); + } + if( crls!=null ) { + sequence.addElement(crls); + } + sequence.addElement( signerInfos ); + } + + /////////////////////////////////////////////////////////////////////// + // DER encoding + /////////////////////////////////////////////////////////////////////// + + private static final Tag TAG = SEQUENCE.TAG; + + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + sequence.encode(ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + sequence.encode(implicitTag, ostream); + } + + + /** + * A Template class for decoding BER-encoded SignedAndEnvelopedData items. + */ + public static class Template implements ASN1Template { + + private SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + + seqt.addElement(INTEGER.getTemplate()); + seqt.addElement(new SET.OF_Template(RecipientInfo.getTemplate())); + seqt.addElement(new SET.OF_Template( + AlgorithmIdentifier.getTemplate()) ); + seqt.addElement(EncryptedContentInfo.getTemplate()); + seqt.addOptionalElement(new Tag(0), + new SET.OF_Template(ANY.getTemplate())); + seqt.addOptionalElement(new Tag(1), + new SET.OF_Template(ANY.getTemplate())); + seqt.addElement(new SET.OF_Template(SignerInfo.getTemplate())); + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws InvalidBERException, IOException + { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws InvalidBERException, IOException + { + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); + + return new SignedAndEnvelopedData( + (INTEGER) seq.elementAt(0), + (SET) seq.elementAt(1), + (SET) seq.elementAt(2), + (EncryptedContentInfo) seq.elementAt(3), + (SET) seq.elementAt(4), + (SET) seq.elementAt(5), + (SET) seq.elementAt(6) ); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cms/SignedData.java b/mozilla/security/jss/org/mozilla/jss/pkix/cms/SignedData.java new file mode 100644 index 00000000000..bf12199268c --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cms/SignedData.java @@ -0,0 +1,430 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.pkix.cms; + +import java.io.*; +import java.util.Vector; +import com.netscape.jss.util.Assert; +import java.math.BigInteger; +import java.io.ByteArrayInputStream; +import com.netscape.jss.asn1.*; +import com.netscape.jss.pkix.primitive.*; +import com.netscape.jss.pkix.cert.Certificate; + +/* CUT THIS??? + *

Although all the normal functionality of a SignedData is supported + * with high-level methods, there is a low-level API for setting the + * individual fields of the structure. Using these calls is an unsupported + * way of accomplishing unforeseen tasks. If you have reason to use these + * methods, please notify the authors in case it is something that should + * be added to the high-level interface. + * +*/ + +/** + * A CMS SignedData structure. + *

The certificates field should only contain X.509 certificates. + * PKCS #6 extended certificates will fail to decode properly. + * @author stevep + * @author nicolson + * @author mzhao + */ +public class SignedData implements ASN1Value { + + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + // Members + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + + private INTEGER version; + private SET digestAlgorithms; + private EncapsulatedContentInfo contentInfo; + private SET certificates; // [0] optional, may be null + private SET crls; // [1] optional, may be null + private SET signerInfos; + + // This class implements version 3 of the spec. + private static final INTEGER VERSION = new INTEGER(3); + + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + // Accessor methods + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + + private static void verifyNotNull(Object obj) { + if( obj == null ) { + throw new IllegalArgumentException(); + } + } + + /** + * Returns the version of this SignedData. The current version of the + * spec is version 3. + */ + public INTEGER getVersion() { + return version; + } + + /** + * Low-level function to set the version. + * @param version Must not be null. + public void setVersion(INTEGER version) { + verifyNotNull(version); + this.version = version; + } + */ + + /** + * Returns the digest algorithms used by the signers to digest the + * signed content. There may be more than one, if different signers + * use different digesting algorithms. + */ + public SET getDigestAlgorithmIdentifiers() { + return digestAlgorithms; + } + + /** + * Low-level function to set the digest algorithm identifiers. + * @param digestAlgIds Must not be null. + public void setDigestAlgorithmIdentifiers(SET digestAlgIds) { + verifyNotNull(digestAlgIds); + this.digestAlgorithms = digestAlgIds; + } + */ + + /** + * Returns the EncapsulatedContentInfo containing the signed content. The simple + * case is for the content to be of type data, although any + * content type can be signed. + */ + public EncapsulatedContentInfo getContentInfo() { + return contentInfo; + } + + /** + * Low-level function to set the EncapsulatedcontentInfo. + * @param ci Must not be null. + public void setContentInfo(EncapsulatedContentInfo ci) { + verifyNotNull(ci); + this.contentInfo = ci; + } + */ + + /** + * Returns the certificates field, which is a SET of + * X.509 certificates (com.netscape.jss.pkix.cert.Certificate). + * PKCS #6 Extended Certificates are not supported by this implementation. + * Returns null if this optional field is not present. + * + */ + public SET getCertificates() { + return certificates; + } + + /** + * Low-level function to set the certificates. + * @param certs May be null to signify that the certificates + * field is not present. + public void setCertificates(SET certs) { + this.certificates = certs; + } + */ + + /** + * Returns true if the certificates field is present. + */ + public boolean hasCertificates() { + return (certificates!=null); + } + + /** + * Returns the crls field, which contains a SET of certificate + * revocation lists represented by ANYs (com.netscape.jss.asn1.ANY). + * + */ + public SET getCrls() { + return crls; + } + + /** + * Low-level function to set the crls. + * @param certs May be null to signify that the crls + * field is not present. + public void setCrls(SET crls) { + this.crls = crls; + } + */ + + /** + * Returns true if the crls field is present. + */ + public boolean hasCrls() { + return (crls != null); + } + + /** + * Returns the signerInfos field, which is a SET of + * com.netscape.jss.pkcs7.SignerInfo. + */ + public SET getSignerInfos() { + return signerInfos; + } + + /** + * Low-level function to set the SignerInfos. + * @param signerInfos Must not be null. + public void setSignerInfos(SET signerInfos) { + verifyNotNull(sis); + this.signerInfos = signerInfos; + } + */ + + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + // Constructors + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + + /** + * Low-level constructor that merely initializes all fields to null. + private SignedData() {} + */ + + /** + * Create a SignedData ASN1 object. Both certificates and crls + * are optional. If you pass in a null for either value, that + * parameter will not get written in the sequence. + * + * @param digestAlgorithms A SET of zero or more + * algorithm identifiers. The purpose of this item is to list + * the digest algorithms used by the various signers to digest + * the signed content. This field will also be updated by + * the addSigner method. If all the signers are added + * with addSigner, it is not necessary to list + * the digest algorithms here. + *

If null is passed in, the + * digestAlgorithms field will be initialized + * with an empty SET. + * @param contentInfo The content that is being signed. This parameter + * may not be null. However, the content + * field of the contentInfo may be omitted, in which case the + * signatures contained in the SignerInfo structures + * are presumed to be on externally-supplied data. + * @param certificates A SET of com.netscape.jss.pkix.cert.Certificate, + * the certificates + * containing the public keys used to sign the content. It may + * also contain elements of the CA chain extending from the leaf + * certificates. It is not necessary to include the CA chain, or + * indeed to include any certificates, if the certificates are + * expected to already be possessed by the recipient. The recipient + * can use the issuer and serial number in the SignerInfo structure + * to search for the necessary certificates. If this parameter is + * null, the certificates field will be + * omitted. + * @param crls A SET of ASN1Values, which should encode to the ASN1 type + * CertificateRevocationList. This implementation does + * not interpret crls. If this parameter is null, + * the crls field will be omitted. + * @param signerInfos SignerInfo structures containing signatures + * of the content. Additional signerInfos can be added with + * the addSigner method. If this parameter is + * null, the field will be initialized with an + * empty SET. + */ + public SignedData( SET digestAlgorithms, + EncapsulatedContentInfo contentInfo, SET certificates, + SET crls, SET signerInfos) { + + version = VERSION; + + if(digestAlgorithms == null ) { + this.digestAlgorithms = new SET(); + } else { + this.digestAlgorithms = digestAlgorithms; + } + + verifyNotNull(contentInfo); + this.contentInfo = contentInfo; + + // certificates may be null + this.certificates = certificates; + + // crls may be null + this.crls = crls; + + if(signerInfos == null) { + this.signerInfos = new SET(); + } else { + this.signerInfos = signerInfos; + } + } + + /** + * Constructor for creating a SignedData from its encoding. + */ + SignedData( INTEGER version, + SET digestAlgorithms, + EncapsulatedContentInfo contentInfo, + SET certificates, + SET crls, + SET signerInfos ) + { + + verifyNotNull(version); + this.version = version; + + verifyNotNull(digestAlgorithms); + this.digestAlgorithms = digestAlgorithms; + + verifyNotNull(contentInfo); + this.contentInfo = contentInfo; + + // certificates may be null + this.certificates = certificates; + + // crls may be null + this.crls = crls; + + verifyNotNull(signerInfos); + this.signerInfos = signerInfos; + } + + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + // Cryptographic functions + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + + + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + // DER encoding + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + + static final Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + encode(getTag(),ostream); + } + + public void encode(Tag tag, OutputStream ostream) throws IOException { + SEQUENCE sequence = new SEQUENCE(); + + sequence.addElement(version); + sequence.addElement(digestAlgorithms); + sequence.addElement(contentInfo); + if( certificates != null ) { + sequence.addElement( new Tag(0), certificates ); + } + if( crls != null ) { + sequence.addElement( new Tag(1), crls ); + } + sequence.addElement(signerInfos); + + sequence.encode(tag,ostream); + } + + + private static final Template templateInstance = new Template(); + public static Template getTemplate() { + return templateInstance; + } + + /** + * A template file for decoding a SignedData blob + * + */ + public static class Template implements ASN1Template { + private SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + + // version + seqt.addElement(INTEGER.getTemplate()); + + // digestAlgorithms + seqt.addElement(new SET.OF_Template( + AlgorithmIdentifier.getTemplate())); + + // content info + seqt.addElement(EncapsulatedContentInfo.getTemplate()); + + // [0] IMPLICIT certificates OPTIONAL + seqt.addOptionalElement( + new Tag(0), + new SET.OF_Template(Certificate.getTemplate())); + + // [1] IMPLICIT CertificateRevocationLists OPTIONAL + seqt.addOptionalElement( + new Tag(1), + new SET.OF_Template(ANY.getTemplate())); + + // signerInfos + seqt.addElement(new SET.OF_Template(SignerInfo.getTemplate())); + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws IOException, InvalidBERException + { + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); + Assert.assert(seq.size() == 6); + + return new SignedData( + (INTEGER) seq.elementAt(0), + (SET) seq.elementAt(1), + (EncapsulatedContentInfo) seq.elementAt(2), + (SET) seq.elementAt(3), + (SET) seq.elementAt(4), + (SET) seq.elementAt(5) + ); + } + } // end of template + +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cms/SignerIdentifier.java b/mozilla/security/jss/org/mozilla/jss/pkix/cms/SignerIdentifier.java new file mode 100644 index 00000000000..73134a035db --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cms/SignerIdentifier.java @@ -0,0 +1,212 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkix.cms; + +import com.netscape.jss.asn1.*; +import com.netscape.jss.pkix.cert.*; +import java.io.*; +import com.netscape.jss.util.Assert; + +/** + * CMS SignerIdentifier: + *

+ * SignerIdentifier ::= CHOICE {
+ *      issuerAndSerialNumber IssuerAndSerialNumber,
+ *      subjectKeyIdentifier [0] SubjectKeyIdentifier }
+ * 
+ */ +public class SignerIdentifier implements ASN1Value { + /** + * The type of SignerIdentifier. + */ + public static class Type { + private Type() { } + + static Type ISSUER_AND_SERIALNUMBER = new Type(); + static Type SUBJECT_KEY_IDENTIFIER = new Type(); + } + public static Type ISSUER_AND_SERIALNUMBER = Type.ISSUER_AND_SERIALNUMBER; + public static Type SUBJECT_KEY_IDENTIFIER = Type.SUBJECT_KEY_IDENTIFIER; + + /////////////////////////////////////////////////////////////////////// + // members and member access + /////////////////////////////////////////////////////////////////////// + + private Type type; + private IssuerAndSerialNumber issuerAndSerialNumber = null; // if type == ISSUER_AND_SERIALNUMBER + private OCTET_STRING subjectKeyIdentifier = null; // if type == SUBJECT_KEY_IDENTIFIER + + /** + * Returns the type of SignerIdentifier:
    + *
  • ISSUER_AND_SERIALNUMBER + *
  • SUBJECT_KEY_IDENTIFIER + *
+ */ + public Type getType() { + return type; + } + + /** + * If type == ISSUER_AND_SERIALNUMBER, returns the IssuerAndSerialNumber + * field. Otherwise, returns null. + */ + public IssuerAndSerialNumber getIssuerAndSerialNumber() { + return issuerAndSerialNumber; + } + + /** + * If type == SUBJECT_KEY_IDENTIFIER, returns the SubjectKeyIdentifier + * field. Otherwise, returns null. + */ + public OCTET_STRING getSubjectKeyIdentifier() { + return subjectKeyIdentifier; + } + + /////////////////////////////////////////////////////////////////////// + // Constructors + /////////////////////////////////////////////////////////////////////// + + private SignerIdentifier() { } + + public SignerIdentifier(Type type, IssuerAndSerialNumber + issuerAndSerialNumber, + OCTET_STRING subjectKeyIdentifier) { + this.type = type; + this.issuerAndSerialNumber = issuerAndSerialNumber; + this.subjectKeyIdentifier = subjectKeyIdentifier; + } + + /** + * Creates a new SignerIdentifier with the given IssuerAndSerialNumber field. + */ + public static SignerIdentifier + createIssuerAndSerialNumber(IssuerAndSerialNumber ias) { + return new SignerIdentifier( ISSUER_AND_SERIALNUMBER, ias, null ); + } + + /** + * Creates a new SignerIdentifier with the given SubjectKeyIdentifier field. + */ + public static SignerIdentifier + createSubjectKeyIdentifier(OCTET_STRING ski) { + return new SignerIdentifier(SUBJECT_KEY_IDENTIFIER , null, ski ); + } + + /////////////////////////////////////////////////////////////////////// + // decoding/encoding + /////////////////////////////////////////////////////////////////////// + + + public Tag getTag() { + if( type == SUBJECT_KEY_IDENTIFIER ) { + return Tag.get(0); + } else { + Assert.assert( type == ISSUER_AND_SERIALNUMBER ); + return IssuerAndSerialNumber.TAG; + } + } + + public void encode(OutputStream ostream) throws IOException { + + if( type == SUBJECT_KEY_IDENTIFIER ) { + // a CHOICE must be explicitly tagged + //EXPLICIT e = new EXPLICIT( Tag.get(0), subjectKeyIdentifier ); + //e.encode(ostream); + subjectKeyIdentifier.encode(Tag.get(0), ostream); + } else { + Assert.assert( type == ISSUER_AND_SERIALNUMBER ); + issuerAndSerialNumber.encode(ostream); + } + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException { + //Assert.notReached("A CHOICE cannot be implicitly tagged"); + encode(ostream); + } + + public static Template getTemplate() { + return templateInstance; + } + private static Template templateInstance = new Template(); + + /** + * A Template for decoding a SignerIdentifier. + */ + public static class Template implements ASN1Template { + + private CHOICE.Template choicet; + + public Template() { + choicet = new CHOICE.Template(); + + //EXPLICIT.Template et = new EXPLICIT.Template( + // Tag.get(0), OCTET_STRING.getTemplate() ); + //choicet.addElement( et ); + choicet.addElement( Tag.get(0), OCTET_STRING.getTemplate() ); + choicet.addElement(IssuerAndSerialNumber.getTemplate() ); + } + + public boolean tagMatch(Tag tag) { + return choicet.tagMatch(tag); + } + + public ASN1Value decode(InputStream istream) + throws InvalidBERException, IOException { + CHOICE c = (CHOICE) choicet.decode(istream); + + if( c.getTag() == SEQUENCE.TAG ) { + return createIssuerAndSerialNumber( (IssuerAndSerialNumber) c.getValue() ); + } else { + Assert.assert( c.getTag().equals(Tag.get(0)) ); + //EXPLICIT e = (EXPLICIT) c.getValue(); + //ASN1Value dski = e.getContent(); + //OCTET_STRING ski = (OCTET_STRING) e.getContent(); + OCTET_STRING ski = (OCTET_STRING) c.getValue(); + return createSubjectKeyIdentifier(ski); + } + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws InvalidBERException, IOException { + //Assert.notReached("A CHOICE cannot be implicitly tagged"); + return decode(istream); + } + } +} + + + + + diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cms/SignerInfo.java b/mozilla/security/jss/org/mozilla/jss/pkix/cms/SignerInfo.java new file mode 100644 index 00000000000..1f56bc19b37 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cms/SignerInfo.java @@ -0,0 +1,856 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkix.cms; + +import java.io.*; +import com.netscape.jss.asn1.*; +import com.netscape.jss.util.Assert; +import com.netscape.jss.pkix.primitive.*; +import com.netscape.jss.pkix.cert.*; +import com.netscape.jss.crypto.*; +import java.util.Vector; +import java.math.BigInteger; +import java.io.ByteArrayInputStream; +import java.security.InvalidKeyException; +import java.security.SignatureException; +import java.security.NoSuchAlgorithmException; +import java.security.MessageDigest; +import com.netscape.jss.crypto.*; +import com.netscape.jss.*; +import java.security.PublicKey; + +/* + * The high-level interface takes care of all + * the logic and cryptography. If you need to use the low-level interface, + * please let us know what you are using it for. Perhaps it should be part + * of the high-level interface. + */ + +/** + * A CMS SignerInfo. + */ +public class SignerInfo implements ASN1Value { + + //////////////////////////////////////////////// + // PKCS #9 attributes + //////////////////////////////////////////////// + private static final OBJECT_IDENTIFIER + CONTENT_TYPE = OBJECT_IDENTIFIER.PKCS.subBranch(9).subBranch(3); + private static final OBJECT_IDENTIFIER + MESSAGE_DIGEST = OBJECT_IDENTIFIER.PKCS.subBranch(9).subBranch(4); + + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + // Members + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + + private INTEGER version; + private SignerIdentifier signerIdentifier; + private AlgorithmIdentifier digestAlgorithm; + private SET signedAttributes; // [0] OPTIONAL + private AlgorithmIdentifier digestEncryptionAlgorithm; + private OCTET_STRING encryptedDigest; + private SET unsignedAttributes; // [1] OPTIONAL + + // we only do CMS in RFC 2630 + private static final INTEGER VERSION = new INTEGER(3); + + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + // Accessor methods + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + + /** + * Retrieves the version number of this SignerInfo. + */ + public INTEGER getVersion() { + return version; + } + + /** + * Low-level method to set the version. + * It is not normally necessary to call this. Use it at your own risk. + public void setVersion(INTEGER version) { + this.version = version; + } + */ + + /** + * Retrieves the SignerIdentifier. + */ + public SignerIdentifier getSignerIdentifier() { + return signerIdentifier; + } + + /** + * Low-level method to set the signerIdentifier. + * It is not normally necessary to call this. Use it at your own risk. + public void setSignerIdentifier( SignerIdentifier iasn ) { + this.signerIdentifier = iasn; + } + */ + + /** + * Retrieves the DigestAlgorithm used in this SignerInfo. + * + * @exception NoSuchAlgorithm If the algorithm is not recognized by JSS. + */ + public DigestAlgorithm getDigestAlgorithm() + throws NoSuchAlgorithmException + { + return DigestAlgorithm.fromOID( digestAlgorithm.getOID() ); + } + + + /** + * Retrieves the DigestAlgorithmIdentifier used in this SignerInfo. + */ + public AlgorithmIdentifier getDigestAlgorithmIdentifer() { + return digestAlgorithm; + } + + /** + * Low-level method to set the digest AlgorithmIdentifier. + * It is not normally necessary to call this. Use it at your own risk. + public void setDigestAlgorithmIdentifier(AlgorithmIdentifier algid) { + this.digestAlgorithm = algid; + } + */ + + /** + * Retrieves the signed attributes, if they exist. + * + */ + public SET getSignedAttributes() { + return signedAttributes; + } + + /** + * Returns true if the signedAttributes field is present. + */ + public boolean hasSignedAttributes() { + return (signedAttributes != null); + } + + /** + * Low-level method to set the signedAttributes field. + * It is not normally necessary to call this. Use it at your own risk. + public void setSignedAttributes(SET authAttrib) { + this.signedAttributes = authAttrib; + } + */ + + /** + * Returns the raw signature (digest encryption) algorithm used in this + * SignerInfo. + * + * @exception NoSuchAlgorithmException If the algorithm is not recognized + * by JSS. + */ + public SignatureAlgorithm getDigestEncryptionAlgorithm() + throws NoSuchAlgorithmException + { + return SignatureAlgorithm.fromOID( + digestEncryptionAlgorithm.getOID() ); + } + + /** + * Returns the DigestEncryptionAlgorithmIdentifier used in this SignerInfo. + */ + public AlgorithmIdentifier getDigestEncryptionAlgorithmIdentifier() { + return digestEncryptionAlgorithm; + } + + /** + * Low-level method to set the digestEncryptionAlgorithm field. + * It is not normally necessary to call this. Use it at your own risk. + public void + setDigestEncryptionAlgorithmIdentifier(AlgorithmIdentifier algid) { + this.digestEncryptionAlgorithm= algid; + } + */ + + /** + * Retrieves the encrypted digest. + */ + public byte[] getEncryptedDigest() { + return encryptedDigest.toByteArray(); + } + + /** + * Low-level method to set the encryptedDigest field. + * It is not normally necessary to call this. Use it at your own risk. + public void setEncryptedDigest(byte[] ed) { + this.encryptedDigest = new OCTET_STRING(ed); + } + */ + + /** + * Retrieves the unsigned attributes, if they exist. + * + */ + public SET getUnsignedAttributes() { + return unsignedAttributes; + } + + /** + * Returns true if the unsignedAttributes field is present. + */ + public boolean hasUnsignedAttributes() { + return (unsignedAttributes!=null); + } + + /** + * Low-level method to set the unsignedAttributes field. + * It is not normally necessary to call this. Use it at your own risk. + public void setUnsignedAttributes(SET unauthAttrib) { + this.unsignedAttributes = unauthAttrib; + } + */ + + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + // Constructors + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + + /** + * Low-level default constructor. All fields are initialized to null. + * Before this SignerInfo can be processed or used in any way, all of + * the fields except signedAttributes and + * unsignedAttributes must be non-null. + *

It is not normally necessary to call this constructor.Use it at + * your own risk. + public SignerInfo() { + } + */ + + /** + * A constructor for creating a new SignerInfo from scratch. + * + * @param signerIdentifier The signerIdentifier of the + * certificate from which the public key was extracted to create + * this SignerInfo. + * @param signingAlg The algorithm to be used to sign the content. + * This should be a composite algorithm, such as + * RSASignatureWithMD5Digest, instead of a raw algorithm, such as + * RSASignature. + * Note that the digest portion of this algorithm must be the same + * algorithm as was used to digest the message content. + * @param signedAttributes An optional set of Attributes, which + * will be signed along with the message content. This parameter may + * be null, or the SET may be empty. DO NOT insert + * the PKCS #9 content-type or message-digest attributes. They will + * be added automatically if they are necessary. + * @param unsignedAttributes An optional set of Attributes, which + * will be included in the SignerInfo but not signed. This parameter + * may be null, or the SET may be empty. + * @param messageDigest The digest of the message contents. The digest + * must have been created with the digest algorithm specified by + * the signingAlg parameter. + * @param contentType The type of the ContentInfo that is being signed. + * If it is not data, then the PKCS #9 attributes + * content-type and message-digest will be automatically computed and + * added to the signed attributes. + */ + public SignerInfo( SignerIdentifier signerIdentifier, + SET signedAttributes, + SET unsignedAttributes, + OBJECT_IDENTIFIER contentType, + byte[] messageDigest, + SignatureAlgorithm signingAlg, + PrivateKey signingKey ) + throws InvalidKeyException, NoSuchAlgorithmException, + CryptoManager.NotInitializedException, SignatureException, + TokenException + { + version = VERSION; + this.signerIdentifier = signerIdentifier; + this.digestAlgorithm = + new AlgorithmIdentifier(signingAlg.getDigestAlg().toOID(),null); + + // if content-type is not data, add message-digest and content-type + // to signed attributes. + if( ! contentType.equals(ContentInfo.DATA) ) { + if( signedAttributes == null ) { + signedAttributes = new SET(); + } + Attribute attrib = new Attribute(CONTENT_TYPE, contentType); + signedAttributes.addElement(attrib); + attrib = new Attribute(MESSAGE_DIGEST, + new OCTET_STRING(messageDigest) ); + signedAttributes.addElement(attrib); + } + + digestEncryptionAlgorithm = new AlgorithmIdentifier( + signingAlg.getRawAlg().toOID(),null ); + + + if( signedAttributes != null ) + { + Assert.assert( signedAttributes.size() >= 2 ); + this.signedAttributes = signedAttributes; + } + + ////////////////////////////////////////////////// + // create encrypted digest (signature) + ////////////////////////////////////////////////// + + // compute the digest + byte[] digest=null; + DigestAlgorithm digestAlg = signingAlg.getDigestAlg(); + if( signedAttributes == null ) { + // just use the message digest of the content + digest = messageDigest; + } else { + // digest the contents octets of the signed attributes + byte[] enc = ASN1Util.encode(signedAttributes); + MessageDigest md = + MessageDigest.getInstance(digestAlg.toString()); + digest = md.digest( enc ); + } + + // put the digest in a DigestInfo + SEQUENCE digestInfo = new SEQUENCE(); + AlgorithmIdentifier digestAlgId = + new AlgorithmIdentifier( digestAlg.toOID(),null ); + digestInfo.addElement( digestAlgId ); + digestInfo.addElement( new OCTET_STRING( digest ) ); + byte[] toBeSigned = ASN1Util.encode(digestInfo); + + // encrypt the DER-encoded DigestInfo with the private key + CryptoToken token = signingKey.getOwningToken(); + Signature sig; + sig = token.getSignatureContext( signingAlg.getRawAlg() ); + sig.initSign(signingKey); + sig.update(toBeSigned); + encryptedDigest = new OCTET_STRING(sig.sign()); + + if( unsignedAttributes != null ) + { + this.unsignedAttributes = unsignedAttributes; + } + } + + /** + * A constructor for creating a new SignerInfo from its decoding. + */ + SignerInfo( INTEGER version, + SignerIdentifier signerIdentifier, + AlgorithmIdentifier digestAlgorithm, + SET signedAttributes, + AlgorithmIdentifier digestEncryptionAlgorithm, + byte[] encryptedDigest, + SET unsignedAttributes) + { + this.version = version; + this.signerIdentifier = signerIdentifier; + this.digestAlgorithm = digestAlgorithm; + this.signedAttributes = signedAttributes; + this.digestEncryptionAlgorithm = digestEncryptionAlgorithm; + this.encryptedDigest = new OCTET_STRING(encryptedDigest); + this.unsignedAttributes = unsignedAttributes; + } + + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + // Verification + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + + /** + * Verifies that this SignerInfo contains a valid signature of the + * given message digest. If any signed attributes are present, + * they are also validated. The verification algorithm is as follows:

    + *

    Note that this does not verify the validity of the + * the certificate itself, only the signature. + * + *

  • If no signed attributes are present, the content type is + * verified to be data. Then it is verified that the message + * digest passed + * in, when encrypted with the given public key, matches the encrypted + * digest in the SignerInfo. + * + *
  • If signed attributes are present, + * two particular attributes must be present:
      + *
    • PKCS #9 Content-Type, the type of content that is being signed. + * This must match the contentType parameter. + *
    • PKCS #9 Message-Digest, the digest of the content that is being + * signed. This must match the messageDigest parameter. + *
    + * After these two attributes are verified to be both present and correct, + * the encryptedDigest field of the SignerInfo is verified to be the + * signature of the contents octets of the DER encoding of the + * signedAttributes field. + * + *
+ * + * @param messageDigest The hash of the content that is signed by this + * SignerInfo. + * @param contentType The type of the content that is signed by this + * SignerInfo. + * @exception NoSuchObjectException If no certificate matching the + * the issuer name and serial number can be found. + */ + public void verify(byte[] messageDigest, OBJECT_IDENTIFIER contentType) + throws CryptoManager.NotInitializedException, NoSuchAlgorithmException, + InvalidKeyException, TokenException, SignatureException, + ObjectNotFoundException + { + CryptoManager cm = CryptoManager.getInstance(); + if + (signerIdentifier.getType().equals(SignerIdentifier.ISSUER_AND_SERIALNUMBER)) { + IssuerAndSerialNumber issuerAndSerialNumber = signerIdentifier.getIssuerAndSerialNumber(); + X509Certificate cert = cm.findCertByIssuerAndSerialNumber( + ASN1Util.encode(issuerAndSerialNumber.getIssuer()), + issuerAndSerialNumber.getSerialNumber() ); + verify(messageDigest, contentType, cert.getPublicKey()); + } else { + Assert.assert( + signerIdentifier.getType().equals(SignerIdentifier.SUBJECT_KEY_IDENTIFIER) ); + + // xxxxx Do we have method to get key using keyIdentifier + } + } + + + /** + * Verifies that this SignerInfo contains a valid signature of the + * given message digest. If any signed attributes are present, + * they are also validated. The verification algorithm is as follows:
    + * + *
  • If no signed attributes are present, the content type is + * verified to be data. Then it is verified that the message + * digest passed + * in, when encrypted with the given public key, matches the encrypted + * digest in the SignerInfo. + * + *
  • If signed attributes are present, + * two particular attributes must be present:
      + *
    • PKCS #9 Content-Type, the type of content that is being signed. + * This must match the contentType parameter. + *
    • PKCS #9 Message-Digest, the digest of the content that is being + * signed. This must match the messageDigest parameter. + *
    + * After these two attributes are verified to be both present and correct, + * the encryptedDigest field of the SignerInfo is verified to be the + * signature of the contents octets of the DER encoding of the + * signedAttributes field. + * + *
+ * + * @param messageDigest The hash of the content that is signed by this + * SignerInfo. + * @param contentType The type of the content that is signed by this + * SignerInfo. + * @param pubkey The public key to use to verify the signature. + */ + public void verify(byte[] messageDigest, OBJECT_IDENTIFIER contentType, + PublicKey pubkey) + throws CryptoManager.NotInitializedException, NoSuchAlgorithmException, + InvalidKeyException, TokenException, SignatureException + { + + if( signedAttributes == null ) { + verifyWithoutSignedAttributes(messageDigest, contentType, + pubkey); + } else { + verifyWithSignedAttributes(messageDigest, contentType, + pubkey); + } + } + + /** + * Verifies that the message digest passed in, when encrypted with the + * given public key, matches the encrypted digest in the SignerInfo. + */ + private void verifyWithoutSignedAttributes + (byte[] messageDigest, OBJECT_IDENTIFIER contentType, + PublicKey pubkey) + throws CryptoManager.NotInitializedException, NoSuchAlgorithmException, + InvalidKeyException, TokenException, SignatureException + { + if( ! contentType.equals(ContentInfo.DATA) ) { + // only data can be signed this way. Everything else has + // to go into signedAttributes. + throw new SignatureException( + "Content-Type is not DATA, but there are"+ + " no signed attributes"); + } + + // create DigestInfo structure + SEQUENCE digestInfo = new SEQUENCE(); + digestInfo.addElement( digestAlgorithm.getOID() ); + digestInfo.addElement( new OCTET_STRING(messageDigest) ); + byte[] toBeVerified = ASN1Util.encode(digestInfo); + + CryptoToken token = CryptoManager.getInstance() + .getInternalCryptoToken(); + SignatureAlgorithm sigAlg = + SignatureAlgorithm.fromOID( + digestEncryptionAlgorithm.getOID() + ); + Signature sig = token.getSignatureContext(sigAlg); + sig.initVerify(pubkey); + sig.update(toBeVerified); + if( sig.verify(encryptedDigest.toByteArray()) ) { + return; // success + } else { + throw new SignatureException( + "Encrypted message digest parameter does not "+ + "match encrypted digest in SignerInfo"); + } + } + + + /** + * Verifies a SignerInfo with signed attributes. If signed + * attributes are present, then two particular attributes must + * be present:
    + *
  • PKCS #9 Content-Type, the type of content that is being signed. + * This must match the contentType parameter. + *
  • PKCS #9 Message-Digest, the digest of the content that is being + * signed. This must match the messageDigest parameter. + *
+ * After these two attributes are verified to be both present and correct, + * the encryptedDigest field of the SignerInfo is verified to be the + * signature of the contents octets of the DER encoding of the + * signedAttributes field. + */ + private void verifyWithSignedAttributes + (byte[] messageDigest, OBJECT_IDENTIFIER contentType, + PublicKey pubkey) + throws CryptoManager.NotInitializedException, NoSuchAlgorithmException, + InvalidKeyException, TokenException, SignatureException + { + + int numAttrib = signedAttributes.size(); + + if(numAttrib < 2) { + throw new SignatureException( + "At least two signed attributes must be present:"+ + " content-type and message-digest"); + } + + // go through the signed attributes, verifying the + // interesting ones + boolean foundContentType = false; + boolean foundMessageDigest = false; + for( int i = 0; i < numAttrib; i++ ) { + + if( ! (signedAttributes.elementAt(i) instanceof Attribute)) { + throw new SignatureException( + "Element of signedAttributes is not an Attribute"); + } + + Attribute attrib = (Attribute) + signedAttributes.elementAt(i); + + if( attrib.getType().equals(CONTENT_TYPE) ) { + // content-type. Compare with what was passed in. + + SET vals = attrib.getValues(); + if( vals.size() != 1 ) { + throw new SignatureException( + "Content-Type attribute "+ + " does not have exactly one value"); + } + + ASN1Value val = vals.elementAt(0); + OBJECT_IDENTIFIER ctype; + try { + if( val instanceof OBJECT_IDENTIFIER ) { + ctype = (OBJECT_IDENTIFIER) val; + } else if( val instanceof ANY ) { + ctype = (OBJECT_IDENTIFIER) ((ANY)val).decodeWith( + OBJECT_IDENTIFIER.getTemplate() ); + } else { + // what the heck is it? not what it's supposed to be + throw new InvalidBERException( + "Content-Type signed attribute has unexpected"+ + " content type"); + } + } catch( InvalidBERException e ) { + throw new SignatureException( + "Content-Type signed attribute does not have "+ + "OBJECT IDENTIFIER value"); + } + + // compare the content type in the attribute to the + // contentType parameter + if( ! ctype.equals( contentType ) ) { + throw new SignatureException( + "Content-type in signed attributes does not "+ + "match content-type being verified"); + } + + // content type is A-OK + foundContentType = true; + + } else if( attrib.getType().equals(MESSAGE_DIGEST) ) { + + SET vals = attrib.getValues(); + if( vals.size() != 1 ) { + throw new SignatureException( + "Message-digest attribute does not have"+ + " exactly one value"); + } + + ASN1Value val = vals.elementAt(0); + byte[] mdigest; + try { + if( val instanceof OCTET_STRING ) { + mdigest = ((OCTET_STRING)val).toByteArray(); + } else if( val instanceof ANY ) { + OCTET_STRING os; + os = (OCTET_STRING) ((ANY)val).decodeWith( + OCTET_STRING.getTemplate() ); + mdigest = os.toByteArray(); + } else { + // what the heck is it? not what it's supposed to be + throw new InvalidBERException( + "Content-Type signed attribute has unexpected"+ + " content type"); + } + } catch( InvalidBERException e ) { + throw new SignatureException( + "Message-digest attribute does not"+ + " have OCTET STRING value"); + } + + // compare the message digest in the attribute to the + // message digest being verified + if( ! byteArraysAreSame(mdigest, messageDigest) ) { + throw new SignatureException( + "Message-digest attribute does not"+ + " match message digest being verified"); + } + + // message digest is A-OK + foundMessageDigest = true; + } + + // we don't care about other attributes + + } + + if( !foundContentType ) { + throw new SignatureException( + "Signed attributes does not contain"+ + " PKCS #9 content-type attribute"); + } + + if( !foundMessageDigest ) { + throw new SignatureException( + "Signed attributes does not contain"+ + " PKCS #9 message-digest attribute"); + } + + // All the signed attributes are present and correct. + // Now verify the signature. + CryptoToken token = + CryptoManager.getInstance().getInternalCryptoToken(); + Signature sig = token.getSignatureContext( + SignatureAlgorithm.fromOID( + digestEncryptionAlgorithm.getOID() ) + ); + sig.initVerify(pubkey); + + // verify the contents octets of the DER encoded signed attribs + byte[] toBeDigested; + try { + byte[] encodedSignedAttrib = ASN1Util.encode(signedAttributes); + toBeDigested = encodedSignedAttrib; + + } catch(Exception e ) { + Assert.notReached("Unable to decode signed attributes"); + toBeDigested = null; + } + + MessageDigest md = MessageDigest.getInstance( + DigestAlgorithm.fromOID(digestAlgorithm.getOID()).toString() ); + byte[] digest = md.digest(toBeDigested); + + // create DigestInfo structure + SEQUENCE digestInfo = new SEQUENCE(); + //digestInfo.addElement( digestAlgorithm ); + + AlgorithmIdentifier digestAlgId = + new AlgorithmIdentifier( digestAlgorithm.getOID(),null ); + digestInfo.addElement( digestAlgId ); + + digestInfo.addElement( new OCTET_STRING(digest) ); + byte[] toBeVerified = ASN1Util.encode(digestInfo); + + sig.update( toBeVerified ); + + if( ! sig.verify(encryptedDigest.toByteArray()) ) { + // signature is invalid + throw new SignatureException("encryptedDigest was not the correct"+ + " signature of the contents octets of the DER-encoded"+ + " signed attributes"); + } + + // SUCCESSFULLY VERIFIED + + } + + /** + * Compares two non-null byte arrays. Returns true if they are identical, + * false otherwise. + */ + private static boolean byteArraysAreSame(byte[] left, byte[] right) { + + Assert.assert(left!=null && right!=null); + + if( left.length != right.length ) { + return false; + } + + for(int i = 0 ; i < left.length ; i++ ) { + if( left[i] != right[i] ) { + return false; + } + } + + return true; + } + + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + // DER-encoding + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + + private static final Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + encode(getTag(),ostream); + } + + public void encode(Tag tag, OutputStream ostream) throws IOException { + SEQUENCE sequence = new SEQUENCE(); + + sequence.addElement( version ); + sequence.addElement( signerIdentifier ); + sequence.addElement( digestAlgorithm ); + if( signedAttributes != null ) { + sequence.addElement( new Tag(0), signedAttributes ); + } + sequence.addElement( digestEncryptionAlgorithm ); + sequence.addElement( encryptedDigest ); + if( unsignedAttributes != null ) { + sequence.addElement( new Tag(1), unsignedAttributes ); + } + + sequence.encode(tag,ostream); + } + + public static Template getTemplate() { + return templateInstance; + } + private static Template templateInstance = new Template(); + + /** + * A template for decoding a SignerInfo blob + * + */ + public static class Template implements ASN1Template { + + SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + + // serial number + seqt.addElement(INTEGER.getTemplate()); // vn + + // issuerAndSerialNumber + seqt.addElement(SignerIdentifier.getTemplate()); // signerId + + // digestAlgorithm + seqt.addElement(AlgorithmIdentifier.getTemplate()); // digest alg + + // signedAttributes + seqt.addOptionalElement( + new Tag(0), + new SET.OF_Template(Attribute.getTemplate())); + + // digestEncryptionAlgorithm + seqt.addElement(AlgorithmIdentifier.getTemplate()); // dig encr alg + + // encryptedDigest + seqt.addElement(OCTET_STRING.getTemplate()); // encr digest + + // unsigned attributes + seqt.addOptionalElement( + new Tag(1), + new SET.OF_Template(Attribute.getTemplate())); + + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + return decode(TAG,istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws IOException, InvalidBERException + { + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag,istream); + Assert.assert(seq.size() == 7); + + return new SignerInfo( + (INTEGER) seq.elementAt(0), + (SignerIdentifier) seq.elementAt(1), + (AlgorithmIdentifier) seq.elementAt(2), + (SET) seq.elementAt(3), + (AlgorithmIdentifier) seq.elementAt(4), + ((OCTET_STRING) seq.elementAt(5)).toByteArray(), + (SET) seq.elementAt(6) + ); + } + } // end of template + +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cms/manifest.mn b/mozilla/security/jss/org/mozilla/jss/pkix/cms/manifest.mn new file mode 100644 index 00000000000..4a5be442a5f --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cms/manifest.mn @@ -0,0 +1,76 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +CORE_DEPTH = ../../../../../.. + +MODULE = ninja + +NS_USE_JDK = 1 + + +PACKAGE = com/netscape/jss/pkix/cms + + +CLASSES = \ + EncapsulatedContentInfo \ + ContentInfo \ + DigestedData \ + DigestInfo \ + EncryptedContentInfo \ + EncryptedData \ + EnvelopedData \ + IssuerAndSerialNumber \ + RecipientInfo \ + SignedAndEnvelopedData \ + SignedData \ + SignerInfo \ + SignerIdentifier \ + $(NULL) + + + +JSRCS = \ + EncapsulatedContentInfo.java \ + ContentInfo.java \ + DigestedData.java \ + DigestInfo.java \ + EncryptedContentInfo.java \ + EncryptedData.java \ + EnvelopedData.java \ + IssuerAndSerialNumber.java \ + RecipientInfo.java \ + SignedAndEnvelopedData.java \ + SignedData.java \ + SignerInfo.java \ + SignerIdentifier.java \ + $(NULL) diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/cms/package.html b/mozilla/security/jss/org/mozilla/jss/pkix/cms/package.html new file mode 100644 index 00000000000..c7f79396285 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/cms/package.html @@ -0,0 +1,37 @@ + + + +Creating and interpeting CMS blobs. + + diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/crmf/CertId.java b/mozilla/security/jss/org/mozilla/jss/pkix/crmf/CertId.java new file mode 100644 index 00000000000..bf81f121be5 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/crmf/CertId.java @@ -0,0 +1,145 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkix.crmf; + +import com.netscape.jss.asn1.*; +import java.io.*; + +/** + * CRMF CertId. + *
+ * CertId ::= SEQUENCE {
+ *      issuer          GeneralName,
+ *      serialNumber    INTEGER }
+ * 
+ */ +public class CertId implements ASN1Value { + + /////////////////////////////////////////////////////////////////////// + // Members and member access + /////////////////////////////////////////////////////////////////////// + private ANY issuer; + private INTEGER serialNumber; + private SEQUENCE sequence; + + /** + * Returns the issuer field as an ANY. + * The actual type of the field is GeneralName. + */ + public ANY getIssuer() { + return issuer; + } + + /** + * Returns the serialNumber field. + */ + public INTEGER getSerialNumber() { + return serialNumber; + } + + /////////////////////////////////////////////////////////////////////// + // Constructors + /////////////////////////////////////////////////////////////////////// + private CertId() { } + + /** + * Constructs a new CertId from its components. Neither + * component may be null. + */ + public CertId(ANY issuer, INTEGER serialNumber) { + if( issuer == null || serialNumber == null ) { + throw new IllegalArgumentException( + "parameter to CertId constructor is null"); + } + sequence = new SEQUENCE(); + + this.issuer = issuer; + sequence.addElement(issuer); + + this.serialNumber = serialNumber; + sequence.addElement(serialNumber); + } + + /////////////////////////////////////////////////////////////////////// + // encoding/decoding + /////////////////////////////////////////////////////////////////////// + private static final Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + sequence.encode(ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException { + sequence.encode(implicitTag, ostream); + } + + private static final Template templateInstance = new Template(); + public static Template getTemplate() { + return templateInstance; + } + + /** + * A Template for decoding a CertId. + */ + public static class Template implements ASN1Template { + private SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + seqt.addElement( ANY.getTemplate() ); + seqt.addElement( INTEGER.getTemplate() ); + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws InvalidBERException, IOException { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws InvalidBERException, IOException { + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); + + return new CertId( (ANY) seq.elementAt(0), + (INTEGER) seq.elementAt(1) ); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/crmf/CertReqMsg.java b/mozilla/security/jss/org/mozilla/jss/pkix/crmf/CertReqMsg.java new file mode 100644 index 00000000000..32148220515 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/crmf/CertReqMsg.java @@ -0,0 +1,348 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.pkix.crmf; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; +import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.FileInputStream; +import com.netscape.jss.asn1.*; +import com.netscape.jss.pkix.primitive.*; +import com.netscape.jss.util.Assert; +import java.math.BigInteger; +import java.text.DateFormat; +import java.security.SignatureException; +import java.security.NoSuchAlgorithmException; +import com.netscape.jss.*; +import com.netscape.jss.crypto.*; +import com.netscape.jss.crypto.*; +import java.security.PublicKey; +import java.io.FileOutputStream; + +/** + * This class models a CRMF CertReqMsg structure. + */ +public class CertReqMsg implements ASN1Value { + + public static final Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + /** + * Retrieves the CertRequest contained in this structure. + */ + public CertRequest getCertReq() { + return certReq; + } + private CertRequest certReq; + + /** + * Returns true if this CertReqMsg has a + * regInfo field. + */ + public boolean hasRegInfo() { + return regInfo != null; + } + /** + * Returns the regInfo field. Should only be called if the + * field is present. + */ + public SEQUENCE getRegInfo() { + Assert.assert(regInfo != null); + return regInfo; + } + private SEQUENCE regInfo; + + /** + * Returns true if this CertReqMsg has a + * pop field. + */ + public boolean hasPop() { + return pop != null; + } + /** + * Returns the pop field. Should only be called if the + * field is present. + */ + public ProofOfPossession getPop() { + Assert.assert(pop != null); + return pop; + } + private ProofOfPossession pop = null; + + // no default constructor + private CertReqMsg() { } + + /** + * Constructs a CertReqmsg from a CertRequest and, optionally, + * a pop>/i> and a regInfo. + * @param pop May be NULL. + * @param regInfo May be NULL. + */ + public CertReqMsg( CertRequest certReq, ProofOfPossession pop, + SEQUENCE regInfo ) { + this.certReq = certReq; + this.pop = pop; + this.regInfo = regInfo; + } + + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + // Verification + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + + public void verify() throws SignatureException, + InvalidKeyFormatException, NoSuchAlgorithmException, + com.netscape.jss.CryptoManager.NotInitializedException, + TokenException, java.security.InvalidKeyException, IOException{ + ProofOfPossession.Type type = pop.getType(); + if (type == ProofOfPossession.SIGNATURE) { + POPOSigningKey sigkey = pop.getSignature(); + AlgorithmIdentifier alg = sigkey.getAlgorithmIdentifier(); + BIT_STRING sig_from = sigkey.getSignature(); + ByteArrayOutputStream bo = new ByteArrayOutputStream(); + certReq.encode(bo); + byte[] toBeVerified = bo.toByteArray(); + + PublicKey pubkey = null; + CertTemplate ct = certReq.getCertTemplate(); + if (ct.hasPublicKey()) { + SubjectPublicKeyInfo spi = ct.getPublicKey(); + pubkey = (PublicKey) spi.toPublicKey(); + } + + CryptoToken token = CryptoManager.getInstance() + .getInternalCryptoToken(); + SignatureAlgorithm sigAlg = + SignatureAlgorithm.fromOID(alg.getOID()); + Signature sig = token.getSignatureContext(sigAlg); + sig.initVerify(pubkey); + sig.update(toBeVerified); + if( sig.verify(sig_from.getBits()) ) { + //System.out.println("worked!!"); + return; // success + } else { + throw new SignatureException( + "Signed request information does not "+ + "match signature in POP"); + } + + } else if (type == ProofOfPossession.KEY_ENCIPHERMENT) { + POPOPrivKey keyEnc = pop.getKeyEncipherment(); + POPOPrivKey.Type ptype = keyEnc.getType(); + if (ptype == POPOPrivKey.THIS_MESSAGE) { + //BIT_STRING thisMessage = keyEnc.getThisMessage(); + //This should be the same as from the archive control + //It's verified by DRM. + + } else if (ptype == POPOPrivKey.SUBSEQUENT_MESSAGE) { + new ChallengeResponseException("requested"); + } + } + } + + /** + * Encodes this CertReqMsg to the given OutputStream using + * DER encoding. + */ + public void encode(OutputStream ostream) throws IOException { + //Assert.notYetImplemented("CertReqMsg encoding"); + encode(getTag(),ostream); + } + + /** + * Encodes this CertReqMsg to the given OutputStream using + * DER encoding, with the given implicit tag. + */ + public void encode(Tag implicit, OutputStream ostream) throws IOException { + //Assert.notYetImplemented("CertReqMsg encoding"); + SEQUENCE sequence = new SEQUENCE(); + + sequence.addElement( certReq ); + if (pop != null) + sequence.addElement( pop ); + if (regInfo != null) + sequence.addElement( regInfo ); + + sequence.encode(implicit,ostream); + } + + private static final Template templateInstance = new Template(); + public static Template getTemplate() { + return templateInstance; + } + + /** + * A class for decoding CertReqMsg structures from a BER encoding. + */ + public static class Template implements ASN1Template { + + public boolean tagMatch(Tag t) { + return TAG.equals(t); + } + + /** + * Decodes a CertReqMsg from the given input stream. + * + * @return A new CertReqMsg. The return value may be cast + * to a CertReqMsg. + * @throw InvalidBERException If the data on the input stream is not + * a valid BER encoding of a CertReqMsg. + */ + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + return decode(TAG, istream); + } + + /** + * Decodes a CertReqMsg from the given input stream, using + * the given implicit tag. + * + * @param implicit The implicit tag for this item. This must be + * supplied if the CertReqMsg appears in a context + * where it is implicitly tagged. + * @return A new CertReqMsg. The return value may be cast + * to a CertReqMsg. + * @throw InvalidBERException If the data on the input stream is not + * a valid BER encoding of a CertReqMsg. + */ + public ASN1Value decode(Tag implicit, InputStream istream) + throws IOException, InvalidBERException + { + SEQUENCE.Template seqt = new SEQUENCE.Template(); + + seqt.addElement( new CertRequest.Template() ); + seqt.addOptionalElement( new ProofOfPossession.Template()); + seqt.addOptionalElement( + new SEQUENCE.OF_Template( new AVA.Template() ) ); + + SEQUENCE seq = (SEQUENCE) seqt.decode(implicit, istream); + + return new CertReqMsg( + (CertRequest) seq.elementAt(0), + (ProofOfPossession) seq.elementAt(1), + (SEQUENCE) seq.elementAt(2) + ); + } + } + + public static void main(String args[]) { + + try { + if( args.length < 1 ) { + System.err.println("Give an arg"); + System.exit(0); + } + FileInputStream fis = new FileInputStream(args[0]); + + SEQUENCE.OF_Template seqt = new SEQUENCE.OF_Template( + new CertReqMsg.Template() ); + + SEQUENCE seq=null; + byte[] bytes = new byte[ fis.available() ]; + fis.read(bytes); + for(int i=0; i < 1; i++) { + seq = (SEQUENCE) seqt.decode(new ByteArrayInputStream(bytes)); + } + + System.out.println("Decoded "+seq.size()+" messages"); + + CertReqMsg reqmsg = (CertReqMsg) seq.elementAt(0); + + CertRequest certreq = reqmsg.getCertReq(); + + System.out.println("Request ID: "+certreq.getCertReqId() ); + + CertTemplate temp = certreq.getCertTemplate(); + + if( temp.hasVersion() ) { + System.out.println("Version: "+temp.getVersion()); + } else { + System.out.println("No version"); + } + if( temp.hasSerialNumber() ) { + System.out.println("Serial Number: "+temp.getSerialNumber()); + } else { + System.out.println("No serial number"); + } + if( temp.hasSigningAlg() ) { + System.out.println("SigningAlg: "+temp.getSigningAlg().getOID()); + } else { + System.out.println("No signing alg"); + } + if( temp.hasIssuer() ) { + System.out.println("Issuer: "+temp.getIssuer().getRFC1485()); + } else { + System.out.println("No issuer"); + } + if( temp.hasSubject() ) { + System.out.println("Subject: "+temp.getSubject().getRFC1485()); + } else { + System.out.println("No subject: "); + } + if( temp.hasPublicKey() ) { + System.out.println("Public Key: "+ + temp.getPublicKey().getAlgorithmIdentifier().getOID() ); + } else { + System.out.println("No public key"); + } + if( temp.hasIssuerUID() ) { + System.out.println("Issuer UID: "+new BigInteger(temp.getIssuerUID().getBits() ) ); + } else { + System.out.println("no issuer uid"); + } + if( temp.hasSubjectUID() ) { + System.out.println("Subject UID: "+new BigInteger(temp.getIssuerUID().getBits() ) ); + } else { + System.out.println("no subject uid"); + } + if( temp.hasNotBefore() ) { + System.out.println("Not Before: "+ + DateFormat.getInstance().format( temp.getNotBefore() )); + } + if( temp.hasNotAfter() ) { + System.out.println("Not After: "+ + DateFormat.getInstance().format( temp.getNotAfter() )); + } + + } catch( Exception e ) { + e.printStackTrace(); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/crmf/CertRequest.java b/mozilla/security/jss/org/mozilla/jss/pkix/crmf/CertRequest.java new file mode 100644 index 00000000000..89df5563b5a --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/crmf/CertRequest.java @@ -0,0 +1,175 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.pkix.crmf; + +import java.util.Date; +import com.netscape.jss.asn1.*; +import com.netscape.jss.util.Assert; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; +import com.netscape.jss.pkix.primitive.*; + +/** + * A PKIX CertRequest. Currently can only be decoded from its BER + * encoding. There are no methods for constructing one. + */ +public class CertRequest implements ASN1Value { + + private INTEGER certReqId; + private CertTemplate certTemplate; + private SEQUENCE controls; // may be null + + private CertRequest() { } + + /** + * Private constructor for the Template class. + * @param controls May be null. + */ + CertRequest(INTEGER certReqId, CertTemplate certTemplate, + SEQUENCE controls) + { + this.certReqId = certReqId; + this.certTemplate = certTemplate; + this.controls = controls; + } + + /** + * Returns the certReqId (certificate request ID) field. + */ + public INTEGER getCertReqId() { + return certReqId; + } + + /** + * Returns the CertTemplate field. + */ + public CertTemplate getCertTemplate() { + return certTemplate; + } + + /** + * Returns the number of optional Controls in the cert request. + * The number may be zero. + */ + public int numControls() { + if(controls == null) { + return 0; + } else { + return controls.size(); + } + + } + + /** + * Returns the ith Control. i must be in the + * range [0..numControls-1]. + */ + public AVA controlAt(int i) { + if( controls == null ) { + throw new ArrayIndexOutOfBoundsException(); + } + return (AVA) controls.elementAt(i); + } + + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + // DER-encoding + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + + public static final Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + /** + * This method is not yet supported. + */ + public void encode(OutputStream ostream) throws IOException { + //Assert.notYetImplemented("CertRequest encoding"); + encode(getTag(),ostream); + } + + /** + * This method is not yet supported. + */ + public void encode(Tag implicit, OutputStream ostream) throws IOException { + //Assert.notYetImplemented("CertRequest encoding"); + SEQUENCE sequence = new SEQUENCE(); + + sequence.addElement( certReqId ); + sequence.addElement( certTemplate ); + if (controls != null) + sequence.addElement( controls ); + + sequence.encode(implicit,ostream); + } + + /** + * A Template class for constructing CertRequests from their + * BER encoding. + */ + public static class Template implements ASN1Template { + private SEQUENCE.Template seqTemplate; + + public Template() { + seqTemplate = new SEQUENCE.Template(); + seqTemplate.addElement( new INTEGER.Template() ); + seqTemplate.addElement( new CertTemplate.Template() ); + seqTemplate.addOptionalElement( new + SEQUENCE.OF_Template( new AVA.Template() )); + } + + public boolean tagMatch( Tag tag ) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicit, InputStream istream) + throws IOException, InvalidBERException + { + + SEQUENCE seq = (SEQUENCE) seqTemplate.decode(implicit, istream); + return new CertRequest( + (INTEGER) seq.elementAt(0), + (CertTemplate) seq.elementAt(1), + (SEQUENCE) seq.elementAt(2) ); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/crmf/CertTemplate.java b/mozilla/security/jss/org/mozilla/jss/pkix/crmf/CertTemplate.java new file mode 100644 index 00000000000..01e6600964b --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/crmf/CertTemplate.java @@ -0,0 +1,566 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.pkix.crmf; + +import com.netscape.jss.asn1.*; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintStream; +import java.io.IOException; +import com.netscape.jss.util.Assert; +import java.util.Date; +import com.netscape.jss.pkix.primitive.*; +import com.netscape.jss.pkix.cert.Extension; +import java.util.Calendar; +import java.util.TimeZone; + +/** + * This class models a CRMF CertTemplate structure. + */ +public class CertTemplate implements ASN1Value { + + // All of these may be null + private INTEGER version; + private INTEGER serialNumber; + private AlgorithmIdentifier signingAlg; + private Name issuer; + private Date notBefore; + private Date notAfter; + private Name subject; + private SubjectPublicKeyInfo publicKey; + private BIT_STRING issuerUID; + private BIT_STRING subjectUID; + private SEQUENCE extensions; + + CertTemplate() { } + + /** + * Returns true if the version field is present. + */ + public boolean hasVersion() { + return (version!=null); + } + + /** + * Returns the version field of this CertTemplate. + */ + public INTEGER getVersion() { + return version; + } + + /** + * Sets the version field of this CertTemplate. + */ + public void setVersion(INTEGER version) { + this.version = version; + } + + /** + * Returns true if the serialNumber field is present. + */ + public boolean hasSerialNumber() { + return (serialNumber!=null); + } + + /** + * Returns the serialNumber field of this CertTemplate. + */ + public INTEGER getSerialNumber() { + return serialNumber; + } + + /** + * Sets the serialNumber field of this CertTemplate. + */ + public void setSerialNumber(INTEGER serialNumber) { + this.serialNumber = serialNumber; + } + + /** + * Returns true if the signingAlg field is present. + */ + public boolean hasSigningAlg() { + return (signingAlg!=null); + } + + /** + * Returns the signingAlg field of this CertTemplate. + */ + public AlgorithmIdentifier getSigningAlg() { + return signingAlg; + } + + /** + * Sets the signingAlg field of this CertTemplate. + */ + public void setSigningAlg(AlgorithmIdentifier signingAlg) { + this.signingAlg = signingAlg; + } + + /** + * Returns true if the issuer field is present. + */ + public boolean hasIssuer() { + return (issuer!=null); + } + + /** + * Returns the issuer field of this CertTemplate. + */ + public Name getIssuer() { + return issuer; + } + + /** + * Sets the issuer field of this CertTemplate. + */ + public void setIssuer(Name issuer) { + this.issuer = issuer; + } + + /** + * Returns true if the notBefore field is present. + */ + public boolean hasNotBefore() { + return (notBefore!=null); + } + + /** + * Returns the notBefore field of this CertTemplate. + */ + public Date getNotBefore() { + return notBefore; + } + + /** + * Sets the version field of this CertTemplate. + */ + public void setNotBefore(Date date) { + this.notBefore = date; + } + + /** + * Returns true if the notAfter field is present. + */ + public boolean hasNotAfter() { + return (notAfter!=null); + } + + /** + * Returns the notAfter field of this CertTemplate. + */ + public Date getNotAfter() { + return notAfter; + } + + /** + * Sets the notAfter field of this CertTemplate. + */ + public void setNotAfter(Date date) { + this.notAfter = date; + } + + /** + * Returns true if the subject field is present. + */ + public boolean hasSubject() { + return (subject!=null); + } + + /** + * Sets the subject field of this CertTemplate. + */ + public Name getSubject() { + return subject; + } + + /** + * Sets the subject field of this CertTemplate. + */ + public void setSubject(Name subject) { + this.subject = subject; + } + + /** + * Returns true if the publicKey field is present. + */ + public boolean hasPublicKey() { + return (publicKey!=null); + } + + /** + * Returns the publicKey field of this CertTemplate. + */ + public SubjectPublicKeyInfo getPublicKey() { + return publicKey; + } + + /** + * Sets the publicKey field of this CertTemplate. + */ + public void setPublicKey(SubjectPublicKeyInfo publicKey) { + this.publicKey = publicKey; + } + + /** + * Returns true if the issuerUID field is present. + */ + public boolean hasIssuerUID() { + return (issuerUID!=null); + } + + /** + * Returns the issuerUID field of this CertTemplate. + */ + public BIT_STRING getIssuerUID() { + return issuerUID; + } + + /** + * Sets the issuerUID field of this CertTemplate. + */ + public void setIssuerUID(BIT_STRING issuerUID) { + this.issuerUID = issuerUID; + } + + /** + * Returns true if the subjectUID field is present. + */ + public boolean hasSubjectUID() { + return (subjectUID!=null); + } + + /** + * Returns the subjectUID field of this CertTemplate. + */ + public BIT_STRING getSubjectUID() { + return subjectUID; + } + + /** + * Sets the subjectUID field of this CertTemplate. + */ + public void setSubjectUID(BIT_STRING subjectUID) { + this.subjectUID = subjectUID; + } + + /** + * Returns true if the extensions field is present. + */ + public boolean hasExtensions() { + return (extensions!=null); + } + + /** + * Sets the extensions field of this CertTemplate. + */ + public void setExtensions(SEQUENCE extensions) { + this.extensions = extensions; + } + + /** + * Returns the number of extensions present in the template. May be zero. + */ + public int numExtensions() { + if(extensions == null) { + return 0; + } else { + return extensions.size(); + } + } + + /** + * Returns the ith extension. + * @param idx The index of the extension to retrieve. Must be in the + * range [ 0, numExtensions()-1 ]. + */ + public Extension extensionAt(int idx) { + if(extensions == null) { + throw new ArrayIndexOutOfBoundsException(); + } + return (Extension) extensions.elementAt(idx); + } + + public void print(PrintStream ps, int indentSpaces) + throws InvalidBERException, IOException { + StringBuffer indentBuf = new StringBuffer(); + for(int i=0; i < indentSpaces; i++) { + indentBuf.append(" "); + } + String indent = indentBuf.toString(); + + if(version!=null) { + ps.println("Version: "+version.toString()); + } + if(serialNumber!=null) { + ps.println("Serial Number: "+serialNumber.toString()); + } + if(signingAlg!=null) { + ps.println("Signing Algorithm: "+signingAlg.getOID().toString()); + } + if(issuer!=null) { + ps.println("Issuer: "+issuer.getRFC1485()); + } + if(notBefore!=null) { + ps.println("Not Before: " + notBefore); + } + if(notAfter!=null) { + ps.println("Not After: " + notAfter); + } + if(subject!=null) { + ps.println("Subject: " + subject.getRFC1485()); + } + if(publicKey!=null) { + ps.println("publicKey is present"); + } + if(issuerUID != null ) { + ps.println("issuerUID is present"); + } + if(subjectUID != null ) { + ps.println("subjectUID is present"); + } + if(extensions != null ) { + ps.println("Extensions is present, with "+extensions.size()+ + " elements"); + } + } + + public static final Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + encode(TAG, ostream); + } + + // the last year for using UTCTime + static final int UTCTIME_CUTOFF_YEAR = 2049; + + /** + * Converts a Date into a UTCTime or GeneralizedTime, depending on + * whether it falls before or after the cutoff date. + */ + private static TimeBase dateToASN1(Date d) { + if(d==null) { + return null; + } + Calendar cal = Calendar.getInstance( TimeZone.getTimeZone("GMT") ); + cal.setTime(d); + if( cal.get(Calendar.YEAR) <= UTCTIME_CUTOFF_YEAR) { + return new UTCTime(d); + } else { + return new GeneralizedTime(d); + } + } + + public void encode(Tag t, OutputStream ostream) throws IOException { + SEQUENCE seq = new SEQUENCE(); + + seq.addElement(Tag.get(0), version); + seq.addElement(Tag.get(1), serialNumber); + seq.addElement(Tag.get(2), signingAlg); + if( issuer!=null ) { + // issuer is a CHOICE, so it must be EXPLICITly tagged + seq.addElement(new EXPLICIT(Tag.get(3), issuer )); + } + if( notBefore!=null || notAfter!=null ) { + SEQUENCE optionalVal = new SEQUENCE(); + // notBefore & notAfter are CHOICES, so must be EXPLICITly tagged + if( notBefore!=null ) { + optionalVal.addElement( new EXPLICIT( + Tag.get(0), dateToASN1(notBefore) ) ); + } + if( notAfter!=null ) { + optionalVal.addElement( new EXPLICIT( + Tag.get(1), dateToASN1(notAfter) ) ); + } + seq.addElement(Tag.get(4), optionalVal); + } + if( subject!=null ) { + // subject is a CHOICE, so it must be EXPLICITly tagged + seq.addElement(new EXPLICIT(Tag.get(5), subject)); + } + seq.addElement(Tag.get(6), publicKey); + seq.addElement(Tag.get(7), issuerUID); + seq.addElement(Tag.get(8), subjectUID); + seq.addElement(Tag.get(9), extensions); + + seq.encode(t, ostream); + } + + private static Template templateInstance = new Template(); + public static Template getTemplate() { + return templateInstance; + } + + /** + * A class for decoding CertTemplates. + */ + public static class Template implements ASN1Template { + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + /** + * Decodes a CertTemplate from its BER encoding. The return + * value of this method + */ + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicit, InputStream istream) + throws IOException, InvalidBERException + { + CHOICE.Template timeChoice = new CHOICE.Template(); + timeChoice.addElement( new GeneralizedTime.Template() ); + timeChoice.addElement( new UTCTime.Template() ); + + // optional validity. The times are CHOICEs, so they are + // EXPLICITly tagged + SEQUENCE.Template validity = new SEQUENCE.Template(); + validity.addOptionalElement( new EXPLICIT.Template( + Tag.get(0), timeChoice)); + validity.addOptionalElement( new EXPLICIT.Template( + Tag.get(1), timeChoice)); + + SEQUENCE.Template seqt = new SEQUENCE.Template(); + + seqt.addOptionalElement( Tag.get(0), new INTEGER.Template() ); + seqt.addOptionalElement( Tag.get(1), new INTEGER.Template() ); + seqt.addOptionalElement( Tag.get(2), + new AlgorithmIdentifier.Template() ); + seqt.addOptionalElement( new EXPLICIT.Template(Tag.get(3), + new Name.Template() )); + seqt.addOptionalElement( Tag.get(4), validity ); + seqt.addOptionalElement( new EXPLICIT.Template(Tag.get(5), + new Name.Template() )); + seqt.addOptionalElement( Tag.get(6), + new SubjectPublicKeyInfo.Template() ); + seqt.addOptionalElement( Tag.get(7), new BIT_STRING.Template() ); + seqt.addOptionalElement( Tag.get(8), new BIT_STRING.Template() ); + seqt.addOptionalElement( Tag.get(9), + new SEQUENCE.OF_Template( new Extension.Template() ) ); + + SEQUENCE seq = (SEQUENCE) seqt.decode(implicit, istream); + + CertTemplate ct = new CertTemplate(); + + ct.setVersion( (INTEGER) seq.elementAt(0) ); + ct.setSerialNumber( (INTEGER) seq.elementAt(1) ); + ct.setSigningAlg( (AlgorithmIdentifier) + seq.elementAt(2) ); + if( seq.elementAt(3) != null ) { + ct.setIssuer((Name)((EXPLICIT)seq.elementAt(3)).getContent() ); + } + + // validity + EXPLICIT explicit; + CHOICE choice; + ASN1Value val; + if( seq.elementAt(4) != null ) { + explicit = (EXPLICIT) ((SEQUENCE)seq.elementAt(4)).elementAt(0); + if( explicit != null ) { + choice = (CHOICE) explicit.getContent(); + val = choice.getValue(); + if( val instanceof TimeBase ) { + ct.setNotBefore( ((TimeBase)val).toDate() ); + } + } + explicit = (EXPLICIT) ((SEQUENCE)seq.elementAt(4)).elementAt(1); + if( explicit != null ) { + choice = (CHOICE) explicit.getContent(); + val = choice.getValue(); + if( val instanceof TimeBase ) { + ct.setNotAfter( ((TimeBase)val).toDate() ); + } + } + } + + if( seq.elementAt(5) != null ) { + ct.setSubject((Name)((EXPLICIT)seq.elementAt(5)).getContent() ); + } + ct.setPublicKey( (SubjectPublicKeyInfo) seq.elementAt(6) ); + ct.setIssuerUID( (BIT_STRING) seq.elementAt(7) ); + ct.setSubjectUID( (BIT_STRING) seq.elementAt(8) ); + ct.setExtensions( (SEQUENCE) seq.elementAt(9) ); + + return ct; + } + } + + public static void main(String args[]) { + + try { + + CertTemplate ct = new CertTemplate(); + Name name; + + ct.setVersion(new INTEGER(5)); + ct.setSerialNumber(new INTEGER(13112)); + + name = new Name(); + name.addCommonName("You"); + name.addStateOrProvinceName("California"); + ct.setIssuer(name); + ct.setNotBefore(new Date()); + name = new Name(); + name.addCommonName("Me"); + name.addCountryName("US"); + ct.setSubject(name); + ct.setIssuerUID( new BIT_STRING( new byte[] {0x00, 0x01}, 0 ) ); + + System.out.println("Constructed CertTemplate:"); + + byte[] encoded = ASN1Util.encode(ct); + java.io.FileOutputStream fos = new java.io.FileOutputStream("certTemplate"); + fos.write(encoded); + fos.close(); + + ct.print(System.out, 0); + + CertTemplate newCt = (CertTemplate) ASN1Util.decode( + CertTemplate.getTemplate(), encoded ); + + System.out.println("\nDecoded CertTemplate:"); + newCt.print(System.out, 0); + + } catch( Exception e ) { + e.printStackTrace(); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/crmf/ChallengeResponseException.java b/mozilla/security/jss/org/mozilla/jss/pkix/crmf/ChallengeResponseException.java new file mode 100644 index 00000000000..361187568de --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/crmf/ChallengeResponseException.java @@ -0,0 +1,74 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.pkix.crmf; + +/** + * An exception thrown when challenge response pop is requested. + */ +public class ChallengeResponseException extends java.lang.Exception { + + private ChallengeResponseException child=null; + + public ChallengeResponseException(String mesg) { + super(mesg); + } + + public ChallengeResponseException(ChallengeResponseException e, String mesg) { + super(mesg); + child = e; + } + + /** + * Prints out the exception class and error message, including + * all the nested exceptions. + */ + public String toString() { + if(child != null) { + return (super.toString()+ " >> " + child.toStringNested()); + } else { + return super.toString(); + } + } + + /** + * Prints out the error message of this exception, including all the + * nested exceptions. + */ + public String toStringNested() { + if(child != null) { + return ( getMessage() + " >> " + child.toStringNested()); + } else { + return getMessage(); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/crmf/Control.java b/mozilla/security/jss/org/mozilla/jss/pkix/crmf/Control.java new file mode 100644 index 00000000000..287318e9462 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/crmf/Control.java @@ -0,0 +1,128 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkix.crmf; + +import com.netscape.jss.asn1.*; +import java.io.*; +import com.netscape.jss.pkix.primitive.AVA; +import com.netscape.jss.util.Assert; + +/** + * A CRMF Control. + */ +public class Control extends AVA implements ASN1Value { + + // general CRMF OIDs + public static final OBJECT_IDENTIFIER + id_pkix = new OBJECT_IDENTIFIER( new long[] { 1, 3, 6, 1, 5, 5, 7 } ); + public static final OBJECT_IDENTIFIER + id_pkip = id_pkix.subBranch( 5 ); + public static final OBJECT_IDENTIFIER + id_regCtrl = id_pkip.subBranch( 1 ); + + + // Control OIDs + public static final OBJECT_IDENTIFIER + id_regCtrl_regToken = id_regCtrl.subBranch(1); + public static final OBJECT_IDENTIFIER + id_regCtrl_authenticator = id_regCtrl.subBranch(2); + public static final OBJECT_IDENTIFIER + id_regCtrl_pkiPublicationInfo = id_regCtrl.subBranch(3); + public static final OBJECT_IDENTIFIER + id_regCtrl_pkiArchiveOptions = id_regCtrl.subBranch(4); + public static final OBJECT_IDENTIFIER + id_regCtrl_oldCertID = id_regCtrl.subBranch(5); + public static final OBJECT_IDENTIFIER + id_regCtrl_protocolEncrKey = id_regCtrl.subBranch(6); + + public Control(OBJECT_IDENTIFIER oid, ASN1Value value) { + super(oid, value); + } + + /** + * Returns the value of this control as a UTF8String, if it actually + * is a UTF8String. + */ + public UTF8String getUTF8String() throws InvalidBERException { + return (UTF8String) getValue().decodeWith(UTF8String.getTemplate()); + } + + /** + * Returns the value of this control as a PKIArchiveOptions, if it + * actually is a PKIArchiveOptions. + */ + public PKIArchiveOptions getPKIArchiveOptions() throws InvalidBERException { + return (PKIArchiveOptions) getValue().decodeWith( + PKIArchiveOptions.getTemplate() ); + } + + /** + * Returns the value of this control as a PKIPublicationInfo, if it + * actually is a PKIPublicationInfo. + */ + public PKIPublicationInfo getPKIPublicationInfo() + throws InvalidBERException { + return (PKIPublicationInfo) getValue().decodeWith( + PKIPublicationInfo.getTemplate() ); + } + + /** + * A template class for decoding a Control from a BER stream. + */ + public static class Template extends AVA.Template implements ASN1Template { + private SEQUENCE.Template seqTemplate; + + public Template() { + seqTemplate = new SEQUENCE.Template(); + seqTemplate.addElement( new OBJECT_IDENTIFIER.Template() ); + seqTemplate.addElement( new ANY.Template() ); + } + + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicit, InputStream istream) + throws IOException, InvalidBERException + { + SEQUENCE seq = (SEQUENCE) seqTemplate.decode(implicit, istream); + OBJECT_IDENTIFIER oid = (OBJECT_IDENTIFIER) seq.elementAt(0); + ANY any = (ANY) seq.elementAt(1); + + return new Control( oid, any ); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/crmf/EncryptedKey.java b/mozilla/security/jss/org/mozilla/jss/pkix/crmf/EncryptedKey.java new file mode 100644 index 00000000000..ab53a145ddc --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/crmf/EncryptedKey.java @@ -0,0 +1,183 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkix.crmf; + +import com.netscape.jss.asn1.*; +import com.netscape.jss.util.Assert; +import java.io.*; + +public class EncryptedKey implements ASN1Value { + + /** + * The type of EncryptedKey. + */ + public static class Type { + private Type() { } + + static final Type ENCRYPTED_VALUE = new Type(); + static final Type ENVELOPED_DATA = new Type(); + } + public static final Type ENCRYPTED_VALUE = Type.ENCRYPTED_VALUE; + public static final Type ENVELOPED_DATA = Type.ENVELOPED_DATA; + + + /////////////////////////////////////////////////////////////////////// + // member and member access + /////////////////////////////////////////////////////////////////////// + private Type type; + private EncryptedValue encryptedValue; + private ANY envelopedData; + + public Type getType() { + return type; + } + + /** + * Should only be called if getType returns + * ENCRYPTED_VALUE. + */ + public EncryptedValue getEncryptedValue() { + return encryptedValue; + } + + /** + * Should only be called if getType returns + * ENVELOPED_DATA. ANY is returned to prevent a circular + * dependency between the com.netscape.jss.pkcs7 package and the + * com.netscape.jss.pkix hierarchy. + */ + public ANY getEnvelopedData() { + return envelopedData; + } + + /////////////////////////////////////////////////////////////////////// + // Constructors + /////////////////////////////////////////////////////////////////////// + + private EncryptedKey() { } + + public EncryptedKey(EncryptedValue encryptedValue) { + this.type = ENCRYPTED_VALUE; + this.encryptedValue = encryptedValue; + this.tag = SEQUENCE.TAG; + } + + public EncryptedKey(ANY envelopedData) { + this.type = ENVELOPED_DATA; + this.envelopedData = envelopedData; + this.tag = new Tag(0); + } + + /////////////////////////////////////////////////////////////////////// + // encoding/decoding + /////////////////////////////////////////////////////////////////////// + + private Tag tag; // set by constructor based on type + public Tag getTag() { + return tag; + } + + public void encode(OutputStream ostream) throws IOException { + encode(getTag(), ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException { + + // no IMPLICIT tags allowed on ANY + Assert.assert( getTag().equals(implicitTag)); + + if( type == ENCRYPTED_VALUE ) { + Assert.assert( encryptedValue != null ); + encryptedValue.encode(implicitTag, ostream); + } else { + Assert.assert(type == ENVELOPED_DATA); + Assert.assert(envelopedData != null); + envelopedData.encode(implicitTag, ostream); + } + } + + private static final Template templateInstance = new Template(); + public static Template getTemplate() { + return templateInstance; + } + + /** + * A Template for decoding BER-encoded EncryptedKeys. + */ + public static class Template implements ASN1Template { + + private CHOICE.Template choicet; + + public Template() { + choicet = new CHOICE.Template(); + + choicet.addElement( EncryptedValue.getTemplate() ); + choicet.addElement( new Tag(0), ANY.getTemplate() ); + } + + public boolean tagMatch(Tag tag) { + return choicet.tagMatch(tag); + } + + public ASN1Value decode(InputStream istream) + throws InvalidBERException, IOException { + try { + + CHOICE choice = (CHOICE) choicet.decode(istream); + + if( choice.getTag().equals(SEQUENCE.TAG) ) { + return new EncryptedKey( (EncryptedValue) choice.getValue() ); + } else { + Assert.assert( choice.getTag().equals(new Tag(0)) ); + return new EncryptedKey( (ANY) choice.getValue() ); + } + + } catch(InvalidBERException e) { + throw new InvalidBERException(e, "EncryptedKey"); + } + } + + /** + * @param implicitTag This parameter is ignored, because a CHOICE + * cannot have an implicitTag. + */ + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws InvalidBERException, IOException { + Assert.notReached("EncryptedKey, being a CHOICE, cannot be"+ + " implicitly tagged"); + return decode(istream); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/crmf/EncryptedValue.java b/mozilla/security/jss/org/mozilla/jss/pkix/crmf/EncryptedValue.java new file mode 100644 index 00000000000..877fd0b4bfc --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/crmf/EncryptedValue.java @@ -0,0 +1,220 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkix.crmf; + +import com.netscape.jss.asn1.*; +import java.io.*; +import com.netscape.jss.pkix.primitive.*; + +/** + * The CRMF structure EncryptedValue for storing the encrypted + * key to be archived. + */ +public class EncryptedValue implements ASN1Value { + + /////////////////////////////////////////////////////////////////////// + // members and member access + /////////////////////////////////////////////////////////////////////// + private AlgorithmIdentifier intendedAlg; // may be null + private AlgorithmIdentifier symmAlg; // may be null + private BIT_STRING encSymmKey; // may be null + private AlgorithmIdentifier keyAlg; // may be null + private OCTET_STRING valueHint; // may be null + private BIT_STRING encValue; // may be null + private SEQUENCE sequence; + + /** + * May return null. + */ + public AlgorithmIdentifier getIntendedAlg() { + return intendedAlg; + } + + /** + * May return null. + */ + public AlgorithmIdentifier getSymmAlg() { + return symmAlg; + } + + /** + * May return null. + */ + public BIT_STRING getEncSymmKey() { + return encSymmKey; + } + + /** + * May return null. + */ + public AlgorithmIdentifier getKeyAlg() { + return keyAlg; + } + + /** + * May return null. + */ + public OCTET_STRING getValueHint() { + return valueHint; + } + + public BIT_STRING getEncValue() { + return encValue; + } + + /////////////////////////////////////////////////////////////////////// + // Constructors + /////////////////////////////////////////////////////////////////////// + + private EncryptedValue() { } + + /** + * @param intendedAlg May be null. + * @param symmAlg May be null. + * @param encSymmKey May be null. + * @param keyAlg May be null. + * @param valueHint May be null. + * @param encValue May not be null. + */ + public EncryptedValue( AlgorithmIdentifier intendedAlg, + AlgorithmIdentifier symmAlg, + BIT_STRING encSymmKey, + AlgorithmIdentifier keyAlg, + OCTET_STRING valueHint, + BIT_STRING encValue ) { + if( encValue == null ) { + throw new IllegalArgumentException("encValue is null"); + } + + this.intendedAlg = intendedAlg; + this.symmAlg = symmAlg; + this.encSymmKey = encSymmKey; + this.keyAlg = keyAlg; + this.valueHint = valueHint; + this.encValue = encValue; + + sequence = new SEQUENCE(); + if(intendedAlg!=null) { + sequence.addElement( new Tag(0), intendedAlg ); + } + if( symmAlg!=null ) { + sequence.addElement( new Tag(1), symmAlg ); + } + if( encSymmKey!=null ) { + sequence.addElement( new Tag(2), encSymmKey ); + } + if( keyAlg!=null ) { + sequence.addElement( new Tag(3), keyAlg ); + } + if( valueHint!=null ) { + sequence.addElement( new Tag(4), valueHint ); + } + sequence.addElement(encValue); + } + + /////////////////////////////////////////////////////////////////////// + // encoding/decoding + /////////////////////////////////////////////////////////////////////// + + private static final Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + sequence.encode(ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException { + sequence.encode(implicitTag, ostream); + } + + private static final Template templateInstance = new Template(); + public static Template getTemplate() { + return templateInstance; + } + + /** + * A Template class for decoding BER-encoded EncryptedValues. + */ + public static class Template implements ASN1Template { + + private SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + + seqt.addOptionalElement( new Tag(0), + AlgorithmIdentifier.getTemplate()); + seqt.addOptionalElement( new Tag(1), + AlgorithmIdentifier.getTemplate()); + seqt.addOptionalElement( new Tag(2), + BIT_STRING.getTemplate()); + seqt.addOptionalElement( new Tag(3), + AlgorithmIdentifier.getTemplate()); + seqt.addOptionalElement( new Tag(4), + OCTET_STRING.getTemplate()); + seqt.addElement( BIT_STRING.getTemplate() ); + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws InvalidBERException, IOException { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws InvalidBERException, IOException { + try { + + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); + + return new EncryptedValue( + (AlgorithmIdentifier) seq.elementAt(0), + (AlgorithmIdentifier) seq.elementAt(1), + (BIT_STRING) seq.elementAt(2), + (AlgorithmIdentifier) seq.elementAt(3), + (OCTET_STRING) seq.elementAt(4), + (BIT_STRING) seq.elementAt(5) ); + + } catch(InvalidBERException e ) { + throw new InvalidBERException(e, "EncryptedValue"); + } + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/crmf/Makefile b/mozilla/security/jss/org/mozilla/jss/pkix/crmf/Makefile new file mode 100644 index 00000000000..8e7b071acaf --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/crmf/Makefile @@ -0,0 +1,75 @@ +#! gmake +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +####################################################################### +# (1) Include initial platform-independent assignments (MANDATORY). # +####################################################################### + +include manifest.mn + +####################################################################### +# (2) Include "global" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/config.mk + +####################################################################### +# (3) Include "component" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/$(MODULE)/config/config.mk + + +####################################################################### +# (4) Include "local" platform-dependent assignments (OPTIONAL). # +####################################################################### +#include config.mk + + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### +#include rules.mk diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/crmf/PKIArchiveOptions.java b/mozilla/security/jss/org/mozilla/jss/pkix/crmf/PKIArchiveOptions.java new file mode 100644 index 00000000000..610dfc6dcfe --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/crmf/PKIArchiveOptions.java @@ -0,0 +1,232 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkix.crmf; + +import com.netscape.jss.asn1.*; +import java.io.*; +import com.netscape.jss.util.Assert; + +public class PKIArchiveOptions implements ASN1Value { + + /** + * A type of PKIArchiveOption. + */ + public static class Type { + private Type() { } + + static final Type ENCRYPTED_PRIV_KEY = new Type(); + static final Type KEY_GEN_PARAMETERS = new Type(); + static final Type ARCHIVE_REM_GEN_PRIV_KEY = new Type(); + } + + public static final Type ENCRYPTED_PRIV_KEY = Type.ENCRYPTED_PRIV_KEY; + public static final Type KEY_GEN_PARAMETERS = Type.KEY_GEN_PARAMETERS; + public static final Type ARCHIVE_REM_GEN_PRIV_KEY = + Type.ARCHIVE_REM_GEN_PRIV_KEY; + + /////////////////////////////////////////////////////////////////////// + // members and member access + /////////////////////////////////////////////////////////////////////// + private EncryptedKey encryptedPrivKey; + private OCTET_STRING keyGenParameters; + private boolean archiveRemGenPrivKey; + private Type type; + + + /** + * Returns the type of PKIArchiveOptions. + */ + public Type getType() { + return type; + } + + /** + * Returns the encrypted key. Should only be called if the type + * is ENCRYPTED_PRIV_KEY. + */ + public EncryptedKey getEncryptedKey( ) { + Assert.assert(type == ENCRYPTED_PRIV_KEY); + return encryptedPrivKey; + } + + /** + * Returns the key gen parameters. Should only be called if the type + * is KEY_GEN_PARAMETERS. + public byte[] getKeyGenParameters( ) { + Assert.assert(type == KEY_GEN_PARAMETERS); + return keyGenParameters; + } + + /** + * Returns the archiveRemGenPrivKey field, which indicates that + * the sender wishes the receiver to generate and archive a key pair. + * Should only be called if the type is + * ARCHIVE_REM_GEN_PRIV_KEY. + */ + public boolean getArchiveRemGenPrivKey( ) { + Assert.assert( type == ARCHIVE_REM_GEN_PRIV_KEY ); + return archiveRemGenPrivKey; + } + + /////////////////////////////////////////////////////////////////////// + // constructors + /////////////////////////////////////////////////////////////////////// + private PKIArchiveOptions() { } + + public PKIArchiveOptions( EncryptedKey eKey ) { + encryptedPrivKey = eKey; + type = ENCRYPTED_PRIV_KEY; + tag = new Tag(0); + } + + public PKIArchiveOptions( byte[] keyGenParameters ) { + this.keyGenParameters = new OCTET_STRING(keyGenParameters); + type = KEY_GEN_PARAMETERS; + tag = new Tag(1); + } + + public PKIArchiveOptions( boolean archiveRemGenPrivKey ) { + this.archiveRemGenPrivKey = archiveRemGenPrivKey; + type = ARCHIVE_REM_GEN_PRIV_KEY; + tag = new Tag(2); + } + + /////////////////////////////////////////////////////////////////////// + // encoding/decoding + /////////////////////////////////////////////////////////////////////// + private Tag tag; // set by the constructor depending on the type + public Tag getTag() { + return tag; + } + + /** + * DER-encodes a PKIArchiveOptions. + */ + public void encode(OutputStream ostream) throws IOException { + encode( getTag(), ostream ); + } + + /** + * DER-encodes a PKIArchiveOptions. + * @param implicitTag This parameter is ignored. A CHOICE cannot + * have an implicit tag. + */ + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + // no implicit tags on a CHOICE + Assert.assert( implicitTag.equals(tag) ); + + if( type == ENCRYPTED_PRIV_KEY ) { + // CHOICEs are always EXPLICITly tagged + EXPLICIT explicit = new EXPLICIT( new Tag(0), encryptedPrivKey ); + explicit.encode(tag, ostream); + } else if( type == KEY_GEN_PARAMETERS ) { + keyGenParameters.encode(tag, ostream); + } else { + Assert.assert( type == ARCHIVE_REM_GEN_PRIV_KEY ); + (new BOOLEAN(archiveRemGenPrivKey)).encode(tag, ostream); + } + } + + private static final Template templateInstance = new Template(); + + public static Template getTemplate() { + return templateInstance; + } + + /** + * A template for decoding PKIArchiveOptions. + */ + public static class Template implements ASN1Template { + + CHOICE.Template template; + + public Template() { + template = new CHOICE.Template(); + + // CHOICEs are always EXPLICIT + template.addElement( new EXPLICIT.Template( + new Tag(0), + new EncryptedKey.Template() )); + + template.addElement( new Tag(1), new OCTET_STRING.Template() ); + template.addElement( new Tag(2), new BOOLEAN.Template() ); + } + + /** + * Returns true if the given tag can satisfy this CHOICE. + */ + public boolean tagMatch(Tag tag) { + return template.tagMatch(tag); + } + + /** + * Decodes a PKIArchiveOptions. + * @return A PKIArchiveOptions object. + */ + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + CHOICE choice = (CHOICE) template.decode(istream); + + if( choice.getTag().getNum() == 0 ) { + EncryptedKey ekey = (EncryptedKey) ((EXPLICIT)choice.getValue()).getContent(); + return new PKIArchiveOptions(ekey); + } else if( choice.getTag().getNum() == 1 ) { + OCTET_STRING kgp = (OCTET_STRING) choice.getValue(); + return new PKIArchiveOptions(kgp.toByteArray()); + } else if( choice.getTag().getNum() == 2 ) { + BOOLEAN arckey = (BOOLEAN) choice.getValue(); + return new PKIArchiveOptions(arckey.toBoolean()); + } else { + String s = "Unrecognized tag in PKIArchiveOptions"; + Assert.notReached(s); + throw new InvalidBERException(s); + } + } + + /** + * Decodes a PKIArchiveOptions. + * @param implicitTag This parameter is ignored. Since + * PKIArchiveOptions is a CHOICE, it cannot have an implicit tag. + * @return A PKIArchiveOptions object. + */ + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws IOException, InvalidBERException + { + return decode(istream); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/crmf/PKIPublicationInfo.java b/mozilla/security/jss/org/mozilla/jss/pkix/crmf/PKIPublicationInfo.java new file mode 100644 index 00000000000..a0faaca3bfd --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/crmf/PKIPublicationInfo.java @@ -0,0 +1,209 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkix.crmf; + +import com.netscape.jss.asn1.*; +import java.io.*; + +/** + * CRMF PKIPublicationInfo: + *
+ * PKIPublicationInfo ::= SEQUENCE {
+ *      action          INTEGER {
+ *          dontPublish     (0),
+ *          pleasePublish   (1) },
+ *      pubInfos SEQUENCE SIZE (1..MAX) OF SinglePubInfo OPTIONAL }
+ *
+ * SinglePubInfo ::= SEQUENCE {
+ *      pubMethod       INTEGER {
+ *          dontCare    (0),
+ *          x500        (1),
+ *          web         (2),
+ *          ldap        (3) },
+ *      pubLocation     GeneralName OPTIONAL }
+ * 
+ */ +public class PKIPublicationInfo implements ASN1Value { + + /** + * A PKIPublicationInfo action. + */ + public static final int DONT_PUBLISH = 0; + /** + * A PKIPublicationInfo action. + */ + public static final int PLEASE_PUBLISH = 1; + + /** + * A SinglePubInfo publication method. + */ + public static final int DONT_CARE = 0; + /** + * A SinglePubInfo publication method. + */ + public static final int X500 = 1; + /** + * A SinglePubInfo publication method. + */ + public static final int WEB = 2; + /** + * A SinglePubInfo publication method. + */ + public static final int LDAP = 3; + + /////////////////////////////////////////////////////////////////////// + // members and member access + /////////////////////////////////////////////////////////////////////// + + private int action; + private SEQUENCE pubInfos; // may be null + + /** + * Returns the action field. + */ + public int getAction() { + return action; + } + + /** + * Returns the number of SinglePubInfos. May be zero. + */ + public int numPubInfos() { + if( pubInfos == null ) { + return 0; + } else { + return pubInfos.size(); + } + } + + /** + * Returns the pubMethod in the SinglePubInfo at the given index. + * Should return DONT_CARE, X500, WEB, or LDAP. + */ + public int getPubMethod(int index) { + return ((INTEGER)((SEQUENCE)pubInfos.elementAt(index)). + elementAt(0)).intValue(); + } + + /** + * Returns the pubLocation in the SinglePubInfo at the given index. + * May return null, since pubLocation is an optional field. + */ + public ANY getPubLocation(int index) { + return (ANY) ((SEQUENCE)pubInfos.elementAt(index)).elementAt(1); + } + + /////////////////////////////////////////////////////////////////////// + // constructors + /////////////////////////////////////////////////////////////////////// + + private PKIPublicationInfo() { } + + /** + * Creates a new PKIPublicationInfo. + * @param action DONT_PUBLISH or PLEASE_PUBLISH. + * @param pubInfos A SEQUENCE of SinglePubInfo, may be null. + */ + public PKIPublicationInfo(int action, SEQUENCE pubInfos) { + this.action = action; + this.pubInfos = pubInfos; + } + + /////////////////////////////////////////////////////////////////////// + // decoding/encoding + /////////////////////////////////////////////////////////////////////// + + private static final Tag TAG = SEQUENCE.TAG; + + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + encode(TAG, ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException { + SEQUENCE seq = new SEQUENCE(); + + seq.addElement( new INTEGER(action) ); + seq.addElement( pubInfos ); + + seq.encode(implicitTag, ostream); + } + + private static final Template templateInstance = new Template(); + + public static Template getTemplate() { + return templateInstance; + } + + /** + * A Template for decoding a PKIPublicationInfo. + */ + public static class Template implements ASN1Template { + + private SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + seqt.addElement( INTEGER.getTemplate() ); + + SEQUENCE.Template pubInfot = new SEQUENCE.Template(); + pubInfot.addElement(INTEGER.getTemplate()); + pubInfot.addOptionalElement(ANY.getTemplate()); + + seqt.addOptionalElement( new SEQUENCE.OF_Template(pubInfot) ); + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws InvalidBERException, IOException { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws InvalidBERException, IOException { + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); + + return new PKIPublicationInfo( + ((INTEGER)seq.elementAt(0)).intValue(), + (SEQUENCE) seq.elementAt(1) ); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/crmf/POPOPrivKey.java b/mozilla/security/jss/org/mozilla/jss/pkix/crmf/POPOPrivKey.java new file mode 100644 index 00000000000..267f7db64a6 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/crmf/POPOPrivKey.java @@ -0,0 +1,255 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkix.crmf; + +import com.netscape.jss.asn1.*; +import com.netscape.jss.util.Assert; +import java.io.*; + +/** + * CRMF POPOPrivKey: + *
+ * POPOPrivKey ::= CHOICE {
+ *      thisMessage         [0] BIT STRING,
+ *      subsequentMessage   [1] SubsequentMessage,
+ *      dhMAC               [2] BIT STRING }
+ *
+ * SubsequentMessage ::= INTEGER {
+ *      encrCert        (0),
+ *      challengeResp   (1) }
+ * 
+ */ +public class POPOPrivKey implements ASN1Value { + + /** + * The type of POPOPrivKey. + */ + public static class Type { + private Type() { } + + static final Type THIS_MESSAGE = new Type(); + static final Type SUBSEQUENT_MESSAGE = new Type(); + static final Type DHMAC = new Type(); + } + public static final Type THIS_MESSAGE = Type.THIS_MESSAGE; + public static final Type SUBSEQUENT_MESSAGE = Type.SUBSEQUENT_MESSAGE; + public static final Type DHMAC = Type.DHMAC; + + /** + * The SubsequentMessage field is encrCert. + */ + public static final int ENCR_CERT = 0; + + /** + * The SubsequentMessage field is challengeResp. + */ + public static final int CHALLENGE_RESP = 1; + + + /////////////////////////////////////////////////////////////////////// + // Members and member access + /////////////////////////////////////////////////////////////////////// + private Type type; + private BIT_STRING thisMessage; // if type == THIS_MESSAGE + private INTEGER subsequentMessage; // if type == SUBSEQUENT_MESSAGE + private BIT_STRING dhMAC; // if type == DHMAC + + /** + * Returns the type of POPOPrivKey: THIS_MESSAGE, SUBSEQUENT_MESSAGE, + * or DHMAC. + */ + public Type getType() { + return type; + } + + /** + * If type==THIS_MESSAGE, returns the thisMessage field. Otherwise, + * returns null. + */ + public BIT_STRING getThisMessage() { + return thisMessage; + } + + /** + * If type==SUBSEQUENT_MESSAGE, returns the subsequentMessage field. + * Otherwise, returns null. The return value can be converted to an + * integer and compared with ENCR_CERT and CHALLENGE_RESP. + */ + public INTEGER getSubsequentMessage() { + return subsequentMessage; + } + + /** + * If type==DHMAC, returns the dhMAC field. Otherwise, returns null. + */ + public BIT_STRING getDhMAC() { + return dhMAC; + } + + /////////////////////////////////////////////////////////////////////// + // Constructors + /////////////////////////////////////////////////////////////////////// + private POPOPrivKey() { } + + private POPOPrivKey(Type type, BIT_STRING thisMessage, + INTEGER subsequentMessage, BIT_STRING dhMAC) { + this.type = type; + this.thisMessage = thisMessage; + this.subsequentMessage = subsequentMessage; + this.dhMAC = dhMAC; + } + + /** + * Creates a new POPOPrivKey with the given thisMessage field. + */ + public static POPOPrivKey createThisMessage(BIT_STRING thisMessage) { + return new POPOPrivKey(THIS_MESSAGE, thisMessage, null, null); + } + + /** + * Creates a new POPOPrivKey with the given subsequentMessage field. + */ + public static POPOPrivKey createSubsequentMessage(int subsequentMessage) { + if(subsequentMessage!=ENCR_CERT && subsequentMessage!=CHALLENGE_RESP) { + throw new IllegalArgumentException( + "Illegal subsequentMessage value: " + subsequentMessage ); + } + + return new POPOPrivKey(SUBSEQUENT_MESSAGE, null, + new INTEGER(subsequentMessage), null); + } + + /** + * Creates a new POPOPrivKey with the given dhMAC field. + */ + public static POPOPrivKey createDhMAC(BIT_STRING dhMAC) { + return new POPOPrivKey(DHMAC, null, null, dhMAC); + } + + /////////////////////////////////////////////////////////////////////// + // encoding/decoding + /////////////////////////////////////////////////////////////////////// + + public Tag getTag() { + if(type == THIS_MESSAGE) { + return Tag.get(0); + } else if(type == SUBSEQUENT_MESSAGE) { + return Tag.get(1); + } else { + Assert.assert(type == DHMAC); + return Tag.get(2); + } + } + + public void encode(OutputStream ostream) throws IOException { + if(type == THIS_MESSAGE) { + thisMessage.encode(Tag.get(0), ostream); + } else if(type == SUBSEQUENT_MESSAGE) { + subsequentMessage.encode(Tag.get(1), ostream); + } else { + Assert.assert(type == DHMAC); + dhMAC.encode(Tag.get(2), ostream); + } + } + + /** + * Should not be called, because POPOPrivKey is a CHOICE and cannot have + * an implicit tag. + */ + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException { + Assert.notReached( + "POPOPrivKey is a CHOICE and cannot have an implicit tag"); + encode(ostream); + } + + private static final Template templateInstance = new Template(); + public static Template getTemplate() { + return templateInstance; + } + + /** + * A Template for decoding a POPOPrivKey. + */ + public static class Template implements ASN1Template { + + private CHOICE.Template choicet; + + public Template() { + choicet = new CHOICE.Template(); + + choicet.addElement( Tag.get(0), BIT_STRING.getTemplate() ); + choicet.addElement( Tag.get(1), INTEGER.getTemplate() ); + choicet.addElement( Tag.get(2), BIT_STRING.getTemplate() ); + } + + public boolean tagMatch(Tag tag) { + return choicet.tagMatch(tag); + } + + /** + * Should not be called, because POPOPrivKey is a CHOICE and cannot + * have an implicit tag. + */ + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws InvalidBERException, IOException { + Assert.notReached( + "POPOPrivKey is a CHOICE and cannot have an implicitTag"); + return decode(istream); + } + + public ASN1Value decode(InputStream istream) + throws InvalidBERException, IOException { + + CHOICE choice = (CHOICE) choicet.decode(istream); + + Tag chosen = choice.getTag(); + + if( chosen.equals(Tag.get(0)) ) { + return createThisMessage( (BIT_STRING) choice.getValue() ); + } else if( chosen.equals(Tag.get(1)) ) { + INTEGER I = (INTEGER) choice.getValue(); + int i = I.intValue(); + if( i != ENCR_CERT && i != CHALLENGE_RESP ) { + throw new InvalidBERException( + "SubsequentMessage has invalid value: "+i); + } + return createSubsequentMessage( i ); + } else { + Assert.assert( chosen.equals(Tag.get(2)) ); + return createDhMAC( (BIT_STRING) choice.getValue() ); + } + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/crmf/POPOSigningKey.java b/mozilla/security/jss/org/mozilla/jss/pkix/crmf/POPOSigningKey.java new file mode 100644 index 00000000000..c0bc1979bb8 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/crmf/POPOSigningKey.java @@ -0,0 +1,169 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkix.crmf; + +import com.netscape.jss.asn1.*; +import com.netscape.jss.pkix.primitive.*; +import java.io.*; + +/** + * CRMF POPOSigningKey: + *
+ * POPOSigningKey ::= SEQUENCE {
+ *      poposkInput         [0] POPOSigningKeyInput OPTIONAL,
+ *      algorithmIdentifier AlgorithmIdentifier,
+ *      signature           BIT STRING }
+ * 
+ */ +public class POPOSigningKey implements ASN1Value { + + /////////////////////////////////////////////////////////////////////// + // members and member access + /////////////////////////////////////////////////////////////////////// + private ANY poposkInput; // may be null + private AlgorithmIdentifier algorithmIdentifier; + private BIT_STRING signature; + private SEQUENCE sequence; + + /** + * Retrieves the input to the Proof-of-Possession of the signing key. + * May return null, because this field is optional. Returns an ANY + * because this type is not currently parsed. + */ + public ANY getPoposkInput() { + return poposkInput; + } + + /** + * Retrieves the algorithm identifier for the signature. + */ + public AlgorithmIdentifier getAlgorithmIdentifier() { + return algorithmIdentifier; + } + + /** + * Retrieves the signature. + */ + public BIT_STRING getSignature() { + return signature; + } + + /////////////////////////////////////////////////////////////////////// + // Constructors + /////////////////////////////////////////////////////////////////////// + + private POPOSigningKey() { } + + /** + * Creates a POPOSigningKey. + * @param poposkInput May be null. + */ + public POPOSigningKey(ANY poposkInput, + AlgorithmIdentifier algorithmIdentifier, BIT_STRING signature) { + + if(algorithmIdentifier==null || signature==null) { + throw new IllegalArgumentException("parameter to POPOSigningKey"+ + " constructor is null"); + } + + this.poposkInput = poposkInput; + this.algorithmIdentifier = algorithmIdentifier; + this.signature = signature; + + sequence = new SEQUENCE(); + sequence.addElement( Tag.get(0), poposkInput ); + sequence.addElement( algorithmIdentifier ); + sequence.addElement( signature ); + } + + + /////////////////////////////////////////////////////////////////////// + // encoding/decoding + /////////////////////////////////////////////////////////////////////// + + private static final Tag TAG = SEQUENCE.TAG; + + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + sequence.encode(TAG, ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException { + sequence.encode(implicitTag, ostream); + } + + private static final Template templateInstance = new Template(); + public static Template getTemplate() { + return templateInstance; + } + + /** + * A Template for decoding POPOSigningKey. + */ + public static class Template implements ASN1Template { + + private SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + seqt.addOptionalElement( new EXPLICIT.Template( + Tag.get(0), ANY.getTemplate()) ); + seqt.addElement( AlgorithmIdentifier.getTemplate()); + seqt.addElement( BIT_STRING.getTemplate() ); + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws InvalidBERException, IOException { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws InvalidBERException, IOException { + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); + + return new POPOSigningKey( + (ANY) seq.elementAt(0), + (AlgorithmIdentifier) seq.elementAt(1), + (BIT_STRING) seq.elementAt(2) ); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/crmf/ProofOfPossession.java b/mozilla/security/jss/org/mozilla/jss/pkix/crmf/ProofOfPossession.java new file mode 100644 index 00000000000..3ed63707092 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/crmf/ProofOfPossession.java @@ -0,0 +1,251 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkix.crmf; + +import com.netscape.jss.asn1.*; +import java.io.*; +import com.netscape.jss.util.Assert; + +/** + * CRMF ProofOfPossession: + *
+ * ProofOfPossession ::= CHOICE {
+ *      raVerified          [0] NULL,
+ *      signature           [1] POPOSigningKey,
+ *      keyEncipherment     [2] POPOPrivKey,
+ *      keyAgreement        [3] POPOPrivKey }
+ * 
+ */ +public class ProofOfPossession implements ASN1Value { + + /** + * The type of ProofOfPossesion. + */ + public static class Type { + private Type() { } + + static Type RA_VERIFIED = new Type(); + static Type SIGNATURE = new Type(); + static Type KEY_ENCIPHERMENT = new Type(); + static Type KEY_AGREEMENT = new Type(); + } + public static Type RA_VERIFIED = Type.RA_VERIFIED; + public static Type SIGNATURE = Type.SIGNATURE; + public static Type KEY_ENCIPHERMENT = Type.KEY_ENCIPHERMENT; + public static Type KEY_AGREEMENT = Type.KEY_AGREEMENT; + + /////////////////////////////////////////////////////////////////////// + // members and member access + /////////////////////////////////////////////////////////////////////// + + private Type type; + private POPOSigningKey signature; // if type == SIGNATURE + private POPOPrivKey keyEncipherment; // if type == KEY_ENCIPHERMENT + private POPOPrivKey keyAgreement; // if type == KEY_AGREEMENT + + /** + * Returns the type of ProofOfPossesion:
    + *
  • RA_VERIFIED + *
  • SIGNATURE + *
  • KEY_ENCIPHERMENT + *
  • KEY_AGREEMENT + *
+ */ + public Type getType() { + return type; + } + + /** + * If type == SIGNATURE, returns the signature field. Otherwise, + * returns null. + */ + public POPOSigningKey getSignature() { + return signature; + } + + /** + * If type == KEY_ENCIPHERMENT, returns the keyEncipherment field. + * Otherwise, returns null. + */ + public POPOPrivKey getKeyEncipherment() { + return keyEncipherment; + } + + /** + * If type == KEY_AGREEMENT, returns the keyAgreement field. Otherwise, + * returns null. + */ + public POPOPrivKey getKeyAgreement() { + return keyAgreement; + } + + /////////////////////////////////////////////////////////////////////// + // Constructors + /////////////////////////////////////////////////////////////////////// + + private ProofOfPossession() { } + + private ProofOfPossession(Type type, POPOSigningKey signature, + POPOPrivKey keyEncipherment, POPOPrivKey keyAgreement) { + this.type = type; + this.signature = signature; + this.keyEncipherment = keyEncipherment; + this.keyAgreement = keyAgreement; + } + + /** + * Creates a new ProofOfPossesion with an raVerified field. + */ + public static ProofOfPossession + createRaVerified() { + return new ProofOfPossession( RA_VERIFIED, null, null, null ); + } + + /** + * Creates a new ProofOfPossesion with the given signature field. + */ + public static ProofOfPossession + createSignature(POPOSigningKey signature) { + return new ProofOfPossession( SIGNATURE, signature, null, null ); + } + + /** + * Creates a new ProofOfPossesion with the given keyEncipherment field. + */ + public static ProofOfPossession + createKeyEncipherment(POPOPrivKey keyEncipherment) { + return new ProofOfPossession( + KEY_ENCIPHERMENT, null, keyEncipherment, null ); + } + + /** + * Creates a new ProofOfPossesion with the given keyAgreement field. + */ + public static ProofOfPossession + createKeyAgreement(POPOPrivKey keyAgreement) { + return new ProofOfPossession( + KEY_AGREEMENT, null, null, keyAgreement ); + } + + /////////////////////////////////////////////////////////////////////// + // decoding/encoding + /////////////////////////////////////////////////////////////////////// + + + public Tag getTag() { + if( type == RA_VERIFIED ) { + return Tag.get(0); + } else if( type == SIGNATURE ) { + return Tag.get(1); + } else if( type == KEY_ENCIPHERMENT ) { + return Tag.get(2); + } else { + Assert.assert( type == KEY_AGREEMENT ); + return Tag.get(3); + } + } + + public void encode(OutputStream ostream) throws IOException { + + if( type == RA_VERIFIED ) { + (new NULL()).encode(Tag.get(0), ostream); + } else if( type == SIGNATURE ) { + signature.encode(Tag.get(1), ostream); + } else if( type == KEY_ENCIPHERMENT ) { + // a CHOICE must be explicitly tagged + EXPLICIT e = new EXPLICIT( Tag.get(2), keyEncipherment ); + e.encode(ostream); + } else { + Assert.assert( type == KEY_AGREEMENT ); + // a CHOICE must be explicitly tagged + EXPLICIT e = new EXPLICIT( Tag.get(3), keyAgreement ); + e.encode(ostream); + } + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException { + Assert.notReached("A CHOICE cannot be implicitly tagged"); + encode(ostream); + } + + /** + * A Template for decoding a ProofOfPossession. + */ + public static class Template implements ASN1Template { + + private CHOICE.Template choicet; + + public Template() { + choicet = new CHOICE.Template(); + + choicet.addElement( Tag.get(0), NULL.getTemplate() ); + choicet.addElement( Tag.get(1), POPOSigningKey.getTemplate() ); + EXPLICIT.Template et = new EXPLICIT.Template( + Tag.get(2), POPOPrivKey.getTemplate() ); + choicet.addElement( et ); + et = new EXPLICIT.Template( + Tag.get(3), POPOPrivKey.getTemplate() ); + choicet.addElement( et ); + } + + public boolean tagMatch(Tag tag) { + return choicet.tagMatch(tag); + } + + public ASN1Value decode(InputStream istream) + throws InvalidBERException, IOException { + CHOICE c = (CHOICE) choicet.decode(istream); + + if( c.getTag().equals(Tag.get(0)) ) { + return createRaVerified(); + } else if( c.getTag().equals(Tag.get(1)) ) { + return createSignature( (POPOSigningKey) c.getValue() ); + } else if( c.getTag().equals(Tag.get(2)) ) { + EXPLICIT e = (EXPLICIT) c.getValue(); + return createKeyEncipherment( (POPOPrivKey) e.getContent() ); + } else { + Assert.assert( c.getTag().equals(Tag.get(3)) ); + EXPLICIT e = (EXPLICIT) c.getValue(); + return createKeyAgreement( (POPOPrivKey) e.getContent() ); + } + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws InvalidBERException, IOException { + Assert.notReached("A CHOICE cannot be implicitly tagged"); + return decode(istream); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/crmf/manifest.mn b/mozilla/security/jss/org/mozilla/jss/pkix/crmf/manifest.mn new file mode 100644 index 00000000000..5e4df139784 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/crmf/manifest.mn @@ -0,0 +1,89 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +CORE_DEPTH = ../../../../../.. + +MODULE = ninja + +NS_USE_JDK = 1 + +PACKAGE = com/netscape/jss/pkix/crmf + +# These are meant to be used within Ninja only. +PRIVATE_EXPORTS = \ + $(NULL) + +JNI_GEN = \ + $(NULL) + +CLASSES = \ + CertId \ + CertReqMsg \ + CertRequest \ + CertTemplate \ + Control \ + EncryptedKey \ + EncryptedValue \ + PKIArchiveOptions \ + PKIPublicationInfo \ + POPOPrivKey \ + POPOSigningKey \ + ProofOfPossession \ + ChallengeResponseException \ + $(NULL) + +PRIVATE_CLASSES = \ + $(NULL) + + +JSRCS = \ + CertId.java \ + CertRequest.java \ + CertReqMsg.java \ + CertTemplate.java \ + Control.java \ + EncryptedKey.java \ + EncryptedValue.java \ + PKIArchiveOptions.java \ + PKIPublicationInfo.java \ + POPOPrivKey.java \ + POPOSigningKey.java \ + ProofOfPossession.java \ + ChallengeResponseException.java \ + $(NULL) + +PRIVATE_JSRCS = + + +CSRCS = \ + $(NULL) diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/crmf/package.html b/mozilla/security/jss/org/mozilla/jss/pkix/crmf/package.html new file mode 100644 index 00000000000..efbcea75e9e --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/crmf/package.html @@ -0,0 +1,37 @@ + + + +The PKIX CRMF protocol. + + diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/manifest.mn b/mozilla/security/jss/org/mozilla/jss/pkix/manifest.mn new file mode 100644 index 00000000000..35ea68b7f2d --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/manifest.mn @@ -0,0 +1,74 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +CORE_DEPTH = ../../../../.. + +MODULE = ninja + +NS_USE_JDK = 1 + +REQUIRES = nspr20 dbm security + +PACKAGE = com/netscape/jss/pkix + +# These are meant to be used within Ninja only. +PRIVATE_EXPORTS = \ + $(NULL) + +JNI_GEN = \ + $(NULL) + +CLASSES = \ + $(NULL) + +PRIVATE_CLASSES = \ + $(NULL) + + +JSRCS = \ + $(NULL) + +PRIVATE_JSRCS = + + +CSRCS = \ + $(NULL) + +DIRS = \ + primitive \ + cert \ + crmf \ + cmmf \ + cms \ + cmc \ + $(NULL) diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/primitive/AVA.java b/mozilla/security/jss/org/mozilla/jss/pkix/primitive/AVA.java new file mode 100644 index 00000000000..8f5a2d8150b --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/primitive/AVA.java @@ -0,0 +1,134 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.pkix.primitive; + +import com.netscape.jss.asn1.*; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; +import com.netscape.jss.util.Assert; + +/** + * An AttributeValueAssertion, which has the following ASN.1 + * definition (roughly): + *
+ *      AttributeValueAssertion ::= SEQUENCE {
+ *          type        OBJECT IDENTIFIER,
+ *          value       ANY DEFINED BY type }
+ * 
+ */ +public class AVA implements ASN1Value { + + private OBJECT_IDENTIFIER oid; + private ANY value; + + public static final Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + private AVA() { } + + public AVA(OBJECT_IDENTIFIER oid, ASN1Value value) { + this.oid = oid; + if( value instanceof ANY ) { + this.value = (ANY) value; + } else { + byte[] encoded = ASN1Util.encode(value); + try { + this.value = (ANY) ASN1Util.decode(ANY.getTemplate(), encoded); + } catch( InvalidBERException e ) { + Assert.notReached("InvalidBERException while decoding as ANY"); + } + } + } + + public OBJECT_IDENTIFIER getOID() { + return oid; + } + + /** + * Returns the value of this AVA, encoded as an ANY. + */ + public ANY getValue() { + return value; + } + + public void encode(OutputStream ostream) throws IOException { + encode(TAG, ostream); + } + + public void encode(Tag implicit, OutputStream ostream) + throws IOException + { + SEQUENCE seq = new SEQUENCE(); + seq.addElement(oid); + seq.addElement(value); + + seq.encode(implicit, ostream); + } + +/** + * A Template for decoding an AVA. + */ +public static class Template implements ASN1Template { + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicit, InputStream istream) + throws IOException, InvalidBERException + { + SEQUENCE.Template seqt = new SEQUENCE.Template(); + + seqt.addElement( new OBJECT_IDENTIFIER.Template() ); + seqt.addElement( new ANY.Template() ); + + SEQUENCE seq = (SEQUENCE) seqt.decode(implicit, istream); + + // The template should have enforced this + Assert.assert(seq.size() == 2); + + return new AVA( (OBJECT_IDENTIFIER) seq.elementAt(0), + seq.elementAt(1) ); + } +} + +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/primitive/AlgorithmIdentifier.java b/mozilla/security/jss/org/mozilla/jss/pkix/primitive/AlgorithmIdentifier.java new file mode 100644 index 00000000000..11676998021 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/primitive/AlgorithmIdentifier.java @@ -0,0 +1,139 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.pkix.primitive; + +import com.netscape.jss.asn1.*; +import com.netscape.jss.util.Assert; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; + +public class AlgorithmIdentifier implements ASN1Value { + + private OBJECT_IDENTIFIER oid; + private ASN1Value parameters=null; + private SEQUENCE sequence = new SEQUENCE(); + + public static final Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + /** + * Creates an AlgorithmIdentifier with no parameter. + */ + public AlgorithmIdentifier(OBJECT_IDENTIFIER oid) { + this.oid = oid; + sequence.addElement( oid ); + } + + /** + * Creates an AlgorithmIdentifier. + * + * @param parameters The algorithm parameters. A value of null + * will be encoded with an ASN.1 NULL. + */ + public AlgorithmIdentifier(OBJECT_IDENTIFIER oid, ASN1Value parameters) { + this.oid = oid; + sequence.addElement( oid ); + this.parameters = parameters; + if( parameters != null ) { + sequence.addElement(parameters); + } else { + sequence.addElement(new NULL()); + } + } + + public OBJECT_IDENTIFIER getOID() { + return oid; + } + + /** + * If this instance was constructed, returns the + * parameter passed in to the constructer. If this instance was + * decoded from a template, returns an ANY that was read from the + * BER stream. In either case, it will return null if no parameters + * were supplied. + */ + public ASN1Value getParameters() { + return parameters; + } + + private static final AlgorithmIdentifier.Template templateInstance = + new AlgorithmIdentifier.Template(); + public static AlgorithmIdentifier.Template getTemplate() { + return templateInstance; + } + + public void encode(OutputStream ostream) throws IOException { + encode(TAG, ostream); + } + + public void encode(Tag implicit, OutputStream ostream) + throws IOException + { + sequence.encode(implicit, ostream); + } + +public static class Template implements ASN1Template { + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicit, InputStream istream) + throws IOException, InvalidBERException + { + SEQUENCE.Template seqt = new SEQUENCE.Template(); + seqt.addElement( new OBJECT_IDENTIFIER.Template() ); + seqt.addOptionalElement( new ANY.Template() ); + + SEQUENCE seq = (SEQUENCE) seqt.decode(implicit, istream); + + // the template should have enforced this + Assert.assert( seq.size() == 2 ); + + return new AlgorithmIdentifier( + (OBJECT_IDENTIFIER)seq.elementAt(0), // OID + seq.elementAt(1) // parameters + ); + } +} // end of Template + +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/primitive/Attribute.java b/mozilla/security/jss/org/mozilla/jss/pkix/primitive/Attribute.java new file mode 100644 index 00000000000..dbb011e1dac --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/primitive/Attribute.java @@ -0,0 +1,138 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.pkix.primitive; + +import com.netscape.jss.asn1.*; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; +import com.netscape.jss.util.Assert; + +/** + * An Attribute, which has the following ASN.1 + * definition (roughly): + *
+ *      Attribute ::= SEQUENCE {
+ *          type        OBJECT IDENTIFIER,
+ *          value       SET }
+ * 
+ */ +public class Attribute implements ASN1Value { + + private OBJECT_IDENTIFIER type; + private SET values; + + public static final Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + private Attribute() { } + + public Attribute(OBJECT_IDENTIFIER type, SET values) { + this.type = type; + this.values = values; + } + + public Attribute(OBJECT_IDENTIFIER type, ASN1Value value) { + this.type = type; + this.values = new SET(); + values.addElement(value); + } + + public OBJECT_IDENTIFIER getType() { + return type; + } + + /** + * If this AVA was constructed, returns the SET of ASN1Values passed to the + * constructor. If this Atrribute was decoded with an Attribute.Template, + * returns a SET of ANYs. + */ + public SET getValues() { + return values; + } + + public void encode(OutputStream ostream) throws IOException { + encode(TAG, ostream); + } + + public void encode(Tag implicit, OutputStream ostream) + throws IOException + { + SEQUENCE seq = new SEQUENCE(); + seq.addElement(type); + seq.addElement(values); + + seq.encode(implicit, ostream); + } + + public static Template getTemplate() { + return templateInstance; + } + private static Template templateInstance = new Template(); + +/** + * A Template for decoding an Attribute. + */ +public static class Template implements ASN1Template { + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicit, InputStream istream) + throws IOException, InvalidBERException + { + SEQUENCE.Template seqt = new SEQUENCE.Template(); + + seqt.addElement( new OBJECT_IDENTIFIER.Template() ); + seqt.addElement( new SET.OF_Template(new ANY.Template())); + + SEQUENCE seq = (SEQUENCE) seqt.decode(implicit, istream); + + // The template should have enforced this + Assert.assert(seq.size() == 2); + + return new Attribute( (OBJECT_IDENTIFIER) seq.elementAt(0), + (SET) seq.elementAt(1)); + } +} + +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/primitive/DirectoryString.java b/mozilla/security/jss/org/mozilla/jss/pkix/primitive/DirectoryString.java new file mode 100644 index 00000000000..ddc7c0b51ae --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/primitive/DirectoryString.java @@ -0,0 +1,184 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkix.primitive; + +import com.netscape.jss.asn1.*; +import com.netscape.jss.util.Assert; +import java.io.CharConversionException; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * An X.500 DirectoryString. + * DirectoryString is defined as follows: + *
+ * DirectoryString ::= CHOICE {
+ *      teletexString               TeletexString (SIZE (1..MAX)),
+ *      printableString             PrintableString (SIZE (1..MAX)),
+ *      universalString             UniversalString (SIZE (1..MAX)),
+ *      utf8String                  UTF8String (SIZE (1..MAX)),
+ *      bmpString                   BMPString (SIZE (1..MAX))  }
+ * 
+ */ +public class DirectoryString implements ASN1Value { + + private DirectoryString() { } + + private CharacterString asn1String; + + /** + * Encodes a Java String into a Directory String. + * The following rules for choosing an encoding are from the + * IETF + * PKIX document Internet X.509 Public Key Infrastructure: + * Certificate and CRL Profile:
    + *
  • The preferred encoding is UTF8String, and all certificates + * issued after December 31, 2003, MUST use UTF8String encoding, + * with a few exceptions. + *
  • Until December 31, 2003, strings that fit in the PrintableString + * character set MAY use PrintableString. + *
  • Until December 31, 2003, string that fit in the BMPString character + * set MAY use BMPString. + *
  • Strings that fit in neither the PrintableString nor the BMPString + * character set MUST use UTF8String. + *
+ * This is all very nice, but for backwards compatibility, what we really + * do is:
    + *
  • Try PrintableString + *
  • Try TeletexString + *
  • Try UniversalString + *
+ */ + public DirectoryString(String s) throws CharConversionException { + try { + try { + asn1String = new PrintableString(s); + } catch( CharConversionException e ) { + asn1String = new TeletexString(s); + } + } catch( CharConversionException e ) { + asn1String = new UniversalString(s); + } + } + + /** + * Creates a DirectoryString from an ASN.1 string. + * @param s Must be a TeletexString, PrintableString, UniversalString, + * UTF8String, or BMPString. + */ + public DirectoryString(CharacterString s) { + if( !(s instanceof PrintableString ) && !(s instanceof BMPString) && + !(s instanceof UTF8String) && !(s instanceof TeletexString) && + !(s instanceof UniversalString) ) + { + throw new IllegalArgumentException("DirectoryString must be "+ + "TeletexString, PrintableString, UniversalString, UTF8STring,"+ + " or BMPString"); + } + asn1String = s; + } + + /** + * Converts an ASN.1 DirectoryString to a Java string. + * + * @param dirstr An ANY containing a BER-encoded DirectoryString. + * @exception InvalidBERException If the encoding does not contain a + * valid DirectoryString. + */ + public String toString() { + return asn1String.toString(); + } + + public Tag getTag() { + return asn1String.getTag(); + } + + public void encode(OutputStream ostream) throws IOException { + asn1String.encode(ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + asn1String.encode(implicitTag, ostream); + } + + /** + * Returns a singleton instance of the decoding template for this class. + */ + public static Template getTemplate() { + return templateInstance; + } + private static final Template templateInstance = new Template(); + + /** + * A Template for decoding DirectoryStrings from their BER encoding. + */ + public static class Template implements ASN1Template { + private CHOICE.Template choicet; + + public Template() { + choicet = new CHOICE.Template(); + choicet.addElement( PrintableString.getTemplate() ); + choicet.addElement( BMPString.getTemplate() ); + choicet.addElement( UTF8String.getTemplate() ); + choicet.addElement( TeletexString.getTemplate() ); + choicet.addElement( UniversalString.getTemplate() ); + } + + public boolean tagMatch(Tag tag) { + return choicet.tagMatch(tag); + } + + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + CHOICE choice = (CHOICE) choicet.decode(istream); + + return new DirectoryString( (CharacterString) choice.getValue()); + } + + /** + * @param implicitTag This paramter is ignored, because + * DirectoryStrings (being CHOICEs) cannot have implicit tags. + */ + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws IOException, InvalidBERException + { + Assert.assert( tagMatch(implicitTag) ); + return decode(istream); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/primitive/EncryptedPrivateKeyInfo.java b/mozilla/security/jss/org/mozilla/jss/pkix/primitive/EncryptedPrivateKeyInfo.java new file mode 100644 index 00000000000..4d2dc56fd58 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/primitive/EncryptedPrivateKeyInfo.java @@ -0,0 +1,312 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkix.primitive; + +import com.netscape.jss.asn1.*; +import java.io.*; +import com.netscape.jss.crypto.*; +import com.netscape.jss.util.Assert; +import java.security.*; +import com.netscape.jss.CryptoManager; +import com.netscape.jss.util.Password; +import java.security.spec.AlgorithmParameterSpec; + +/** + * PKCS #8 EncryptedPrivateKeyInfo. + *
+ * EncryptedPrivateKeyInfo ::= SEQUENCE {
+ *      encryptionAlgorithm     AlgorithmIdentifier,
+ *      encryptedData           OCTET STRING }
+ * 
+ */ +public class EncryptedPrivateKeyInfo implements ASN1Value { + + /////////////////////////////////////////////////////////////////////// + // members and member access + /////////////////////////////////////////////////////////////////////// + private AlgorithmIdentifier encryptionAlgorithm; + private OCTET_STRING encryptedData; + private SEQUENCE sequence; + + public AlgorithmIdentifier getEncryptionAlgorithm() { + return encryptionAlgorithm; + } + + public OCTET_STRING getEncryptedData() { + return encryptedData; + } + + /////////////////////////////////////////////////////////////////////// + // Constructors + /////////////////////////////////////////////////////////////////////// + + private EncryptedPrivateKeyInfo() { } + + /** + * Creates an EncryptedPrivateKeyInfo from its components. + * + */ + public EncryptedPrivateKeyInfo( AlgorithmIdentifier encryptionAlgorithm, + OCTET_STRING encryptedData) + { + if( encryptionAlgorithm==null || encryptedData==null ) { + throw new IllegalArgumentException( + "EncryptedPrivateKeyInfo parameter is null"); + } + + this.encryptionAlgorithm = encryptionAlgorithm; + this.encryptedData = encryptedData; + + sequence = new SEQUENCE(); + sequence.addElement(encryptionAlgorithm); + sequence.addElement(encryptedData); + + } + + /////////////////////////////////////////////////////////////////////// + // crypto shortcuts + /////////////////////////////////////////////////////////////////////// + + /** + * Creates a new EncryptedPrivateKeyInfo, where the data is encrypted + * with a password-based key. + * + * @param keyGenAlg The algorithm for generating a symmetric key from + * a password, salt, and iteration count. + * @param password The password to use in generating the key. + * @param salt The salt to use in generating the key. + * @param iterationCount The number of hashing iterations to perform + * while generating the key. + * @param charToByteConverter The mechanism for converting the characters + * in the password into bytes. If null, the default mechanism + * will be used, which is UTF8. + * @param pki The PrivateKeyInfo to be encrypted and stored in the + * EncryptedContentInfo. Before they are encrypted, they will be + * padded using PKCS padding. + */ + public static EncryptedPrivateKeyInfo + createPBE(PBEAlgorithm keyGenAlg, Password password, byte[] salt, + int iterationCount, + KeyGenerator.CharToByteConverter charToByteConverter, + PrivateKeyInfo pki) + throws CryptoManager.NotInitializedException, NoSuchAlgorithmException, + InvalidKeyException, InvalidAlgorithmParameterException, TokenException, + CharConversionException + { + try { + + // check key gen algorithm + if( ! (keyGenAlg instanceof PBEAlgorithm) ) { + throw new NoSuchAlgorithmException("Key generation algorithm"+ + " is not a PBE algorithm"); + } + PBEAlgorithm pbeAlg = (PBEAlgorithm) keyGenAlg; + + CryptoManager cman = CryptoManager.getInstance(); + + // generate key + CryptoToken token = cman.getInternalCryptoToken(); + KeyGenerator kg = token.getKeyGenerator( keyGenAlg ); + PBEKeyGenParams pbekgParams = new PBEKeyGenParams( + password, salt, iterationCount); + if( charToByteConverter != null ) { + kg.setCharToByteConverter( charToByteConverter ); + } + kg.initialize(pbekgParams); + SymmetricKey key = kg.generate(); + + // generate IV + EncryptionAlgorithm encAlg = pbeAlg.getEncryptionAlg(); + AlgorithmParameterSpec params=null; + if( encAlg.getParameterClass().equals( IVParameterSpec.class ) ) { + params = new IVParameterSpec( kg.generatePBE_IV() ); + } + + // perform encryption + Cipher cipher = token.getCipherContext( encAlg ); + cipher.initEncrypt( key, params ); + byte[] encrypted = cipher.doFinal( Cipher.pad( + ASN1Util.encode(pki), encAlg.getBlockSize()) ); + + // make encryption algorithm identifier + PBEParameter pbeParam = new PBEParameter( salt, iterationCount ); + AlgorithmIdentifier encAlgID = new AlgorithmIdentifier( + keyGenAlg.toOID(), pbeParam); + + // create EncryptedPrivateKeyInfo + EncryptedPrivateKeyInfo epki = new EncryptedPrivateKeyInfo ( + encAlgID, + new OCTET_STRING(encrypted) ); + + return epki; + + } catch( IllegalBlockSizeException e ) { + Assert.notReached("IllegalBlockSizeException in EncryptedContentInfo" + +".createPBE"); + } catch( BadPaddingException e ) { + Assert.notReached("BadPaddingException in EncryptedContentInfo" + +".createPBE"); + } + return null; + } + + /** + * Decrypts an EncryptedPrivateKeyInfo that was encrypted with a PBE + * algorithm. The algorithm and its parameters are extracted from + * the EncryptedPrivateKeyInfo. + * + * @param pass The password to use to generate the PBE key. + * @param charToByteConverter The converter to change the password + * characters to bytes. If null, the default conversion is used. + */ + public PrivateKeyInfo + decrypt(Password pass, KeyGenerator.CharToByteConverter charToByteConverter) + throws CryptoManager.NotInitializedException, NoSuchAlgorithmException, + InvalidBERException, InvalidKeyException, + InvalidAlgorithmParameterException, TokenException, + IllegalBlockSizeException, BadPaddingException, CharConversionException + { + // get the key gen parameters + AlgorithmIdentifier algid = encryptionAlgorithm; + KeyGenAlgorithm kgAlg = KeyGenAlgorithm.fromOID(algid.getOID()); + if( !(kgAlg instanceof PBEAlgorithm)) { + throw new NoSuchAlgorithmException("KeyGenAlgorithm is not a "+ + "PBE algorithm"); + } + ASN1Value params = algid.getParameters(); + if( params == null ) { + throw new InvalidAlgorithmParameterException( + "PBE algorithms require parameters"); + } + PBEParameter pbeParams; + if( params instanceof PBEParameter ) { + pbeParams = (PBEParameter) params; + } else { + byte[] encodedParams = ASN1Util.encode(params); + pbeParams = (PBEParameter) + ASN1Util.decode(PBEParameter.getTemplate(), encodedParams); + } + PBEKeyGenParams kgp = new PBEKeyGenParams(pass, + pbeParams.getSalt(), pbeParams.getIterations() ); + + // compute the key and IV + CryptoToken token = + CryptoManager.getInstance().getInternalCryptoToken(); + KeyGenerator kg = token.getKeyGenerator( kgAlg ); + if( charToByteConverter != null ) { + kg.setCharToByteConverter( charToByteConverter ); + } + kg.initialize(kgp); + SymmetricKey key = kg.generate(); + + // compute algorithm parameters + EncryptionAlgorithm encAlg = ((PBEAlgorithm)kgAlg).getEncryptionAlg(); + AlgorithmParameterSpec algParams; + if( encAlg.getParameterClass().equals( IVParameterSpec.class ) ) { + algParams = new IVParameterSpec( kg.generatePBE_IV() ); + } else { + algParams = null; + } + + // perform the decryption + Cipher cipher = token.getCipherContext( encAlg ); + cipher.initDecrypt(key, algParams); + byte[] decrypted = Cipher.unPad( cipher.doFinal( + encryptedData.toByteArray() ) ); + + return (PrivateKeyInfo) + ASN1Util.decode(PrivateKeyInfo.getTemplate(), decrypted); + + } + + /////////////////////////////////////////////////////////////////////// + // DER encoding + /////////////////////////////////////////////////////////////////////// + + private static final Tag TAG = SEQUENCE.TAG; + + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + sequence.encode(ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + sequence.encode(implicitTag, ostream); + } + + private static final Template templateInstance = new Template(); + public static Template getTemplate() { + return templateInstance; + } + + /** + * A template class for decoding EncryptedPrivateKeyInfos from BER. + */ + public static class Template implements ASN1Template { + + private SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + + seqt.addElement( AlgorithmIdentifier.getTemplate() ); + seqt.addElement( OCTET_STRING.getTemplate() ); + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws InvalidBERException, IOException + { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws InvalidBERException, IOException + { + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); + + return new EncryptedPrivateKeyInfo( + (AlgorithmIdentifier) seq.elementAt(0), + (OCTET_STRING) seq.elementAt(1) ); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/primitive/Makefile b/mozilla/security/jss/org/mozilla/jss/pkix/primitive/Makefile new file mode 100644 index 00000000000..8e7b071acaf --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/primitive/Makefile @@ -0,0 +1,75 @@ +#! gmake +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +####################################################################### +# (1) Include initial platform-independent assignments (MANDATORY). # +####################################################################### + +include manifest.mn + +####################################################################### +# (2) Include "global" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/config.mk + +####################################################################### +# (3) Include "component" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/$(MODULE)/config/config.mk + + +####################################################################### +# (4) Include "local" platform-dependent assignments (OPTIONAL). # +####################################################################### +#include config.mk + + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### +#include rules.mk diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/primitive/Name.java b/mozilla/security/jss/org/mozilla/jss/pkix/primitive/Name.java new file mode 100644 index 00000000000..521dd0a5150 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/primitive/Name.java @@ -0,0 +1,341 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.pkix.primitive; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; +import java.io.BufferedInputStream; +import java.io.FileInputStream; +import java.io.CharConversionException; +import java.io.ByteArrayInputStream; +import com.netscape.jss.asn1.*; + +/** + * An X.500 Name. + */ +public class Name implements ASN1Value { + + SEQUENCE rdns; + + /** + * Creates an empty Name. + */ + public Name() { + rdns = new SEQUENCE(); + } + + /** + * Creates a name from a sequence of relative distinguished names. + */ + Name( SEQUENCE rdns ) { + this.rdns = rdns; + } + + /** + * Adds a relative distinguished name to the Name. + * + * @param name A relative distinguished name (RDN) to be added to the Name. + */ + public void addElement( RDN name ) { + rdns.addElement( name ); + } + + /** + * Adds a relative distinguished name containing a single AVA. + * + * @param ava An AttributeValueAssertion, which will be inserted as + * the sole element of a new RDN, which will be stored in the Name. + */ + public void addElement( AVA ava ) { + rdns.addElement( new RDN( ava ) ); + } + + /** + * Inserts the given RDN at the given index in the Name. + */ + public void insertElementAt( RDN name, int idx ) { + rdns.insertElementAt( name, idx); + } + + /** + * Returns the RDN at the given index in the Name. + */ + public RDN elementAt( int idx ) { + return (RDN) rdns.elementAt(idx); + } + + /** + * Removes the Name element at the given index. + */ + public void removeElementAt( int idx ) { + rdns.removeElementAt( idx ); + } + + /** + * Returns the number of RDNs in the Name. + */ + public int size() { + return rdns.size(); + } + + public static final Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + rdns.encode(ostream); + } + + public void encode(Tag implicit, OutputStream ostream) + throws IOException + { + rdns.encode(implicit, ostream); + } + + /** + * The OID for the common name (CN) attribute. + */ + public static final OBJECT_IDENTIFIER commonName = + new OBJECT_IDENTIFIER( new long[]{ 2, 5, 4, 3 } ); + /** + * The OID for the country name (C) attribute. + */ + public static final OBJECT_IDENTIFIER countryName = + new OBJECT_IDENTIFIER( new long[]{ 2, 5, 4, 6 } ); + /** + * The OID for the locality name (L) attribute. + */ + public static final OBJECT_IDENTIFIER localityName = + new OBJECT_IDENTIFIER( new long[]{ 2, 5, 4, 7 } ); + /** + * The OID for the state or province name (S) attribute. + */ + public static final OBJECT_IDENTIFIER stateOrProvinceName = + new OBJECT_IDENTIFIER( new long[]{ 2, 5, 4, 8 } ); + /** + * The OID for the organization name (O) attribute. + */ + public static final OBJECT_IDENTIFIER organizationName = + new OBJECT_IDENTIFIER( new long[]{ 2, 5, 4, 10 } ); + /** + * The OID for the organizational unit name (OU) attribute. + */ + public static final OBJECT_IDENTIFIER organizationalUnitName = + new OBJECT_IDENTIFIER( new long[]{ 2, 5, 4, 11 } ); + + + /** + * Adds a common name (CN) to the Name. + * @CN The common name. + * It will be formatted according to the IETF PKIX rules for + * directory strings. + */ + public void addCommonName(String CN) throws CharConversionException { + addElement( new AVA( commonName, new DirectoryString(CN) ) ); + } + + /** + * Adds a country name (C) to the Name. It must be exactly two characters. + * @C The country name. + * It will be formatted according to the IETF PKIX rules for + * directory strings. + * @exception IllegalArgumentException If C.length() != 2. + */ + public void addCountryName(String C) throws CharConversionException { + if( C.length() != 2 ) { + throw new IllegalArgumentException("Country name must be exactly"+ + " 2 characters"); + } + addElement( new AVA( countryName, new DirectoryString(C) ) ); + } + + /** + * Adds a locality name (L) to the Name. + * @L The locality name. + * It will be formatted according to the IETF PKIX rules for + * directory strings. + */ + public void addLocalityName(String L) throws CharConversionException { + addElement( new AVA( localityName, new DirectoryString(L) ) ); + } + + /** + * Adds a state or province name (S) to the Name. + * @S The state or province name. + * It will be formatted according to the IETF PKIX rules for + * directory strings. + */ + public void addStateOrProvinceName(String S) + throws CharConversionException + { + addElement( new AVA( stateOrProvinceName, new DirectoryString(S) ) ); + } + + /** + * Adds an organization name (O) to the Name. + * @O The organization name. + * It will be formatted according to the IETF PKIX rules for + * directory strings. + */ + public void addOrganizationName(String O) throws CharConversionException { + addElement( new AVA( organizationName, new DirectoryString(O) ) ); + } + + /** + * Adds an organizational unit name (OU) to the Name. + * @OU The organizational unit name. + * It will be formatted according to the IETF PKIX rules for + * directory strings. + */ + public void addOrganizationalUnitName(String OU) + throws CharConversionException + { + addElement( new AVA( organizationalUnitName, + new DirectoryString(OU) ) ); + } + + private String typeToString( OBJECT_IDENTIFIER type ) { + if( type.equals(commonName) ) { + return "CN"; + } else if( type.equals(countryName) ) { + return "C"; + } else if( type.equals(localityName) ) { + return "L"; + } else if( type.equals(stateOrProvinceName) ) { + return "S"; + } else if( type.equals(organizationName) ) { + return "O"; + } else if( type.equals(organizationalUnitName) ) { + return "OU"; + } else { + return null; + } + } + + private String AVAToString(AVA ava) throws InvalidBERException + { + OBJECT_IDENTIFIER oid = ava.getOID(); + String type = typeToString( oid ); + if( type == null ) { + return ""; + } else { + return type + "=" + + (DirectoryString) (((ANY)ava.getValue()). + decodeWith(DirectoryString.getTemplate())); + } + } + + public String getRFC1485() throws InvalidBERException { + StringBuffer buf = new StringBuffer(80); + for( int r = 0; r < rdns.size(); r++ ) { + if( r > 0) { + buf.append(", "); + } + buf.append( AVAToString( ((RDN)rdns.elementAt(r)).at(0)) ); + } + return buf.toString(); + } + + private static final Name.Template templateInstance = new Name.Template(); + public static Name.Template getTemplate() { + return templateInstance; + } + + public static void main(String args[]) { + + try { + + if(args.length == 0) { + Name name = new Name(); + OBJECT_IDENTIFIER oid; + + oid = new OBJECT_IDENTIFIER( new long[]{ 2, 5, 4, 10 } ); + AVA ava = new AVA( oid, new PrintableString("Netscape") ); + name.addElement( ava ); + + oid = new OBJECT_IDENTIFIER( new long[]{ 2, 5, 4, 3} ); + ava = new AVA( oid, new PrintableString("moi")); + name.addElement( ava ); + + name.encode(System.out); + } else { + + BufferedInputStream bis = new BufferedInputStream( + new FileInputStream(args[0]) ); + + Name.Template temp = new Name.Template(); + + Name name = (Name) temp.decode(bis); + + System.out.println("Got name."); + + for( int i = 0; i < name.size(); i++ ) { + AVA a = name.elementAt(i).at(0); + PrintableString.Template pst = new PrintableString.Template(); + PrintableString ps = (PrintableString) + pst.decode( new ByteArrayInputStream( + ((ANY)a.getValue()).getEncoded() ) ); + System.out.println("OID: "+a.getOID()+", String: "+ps); + } + System.out.println("End of name"); + } + } catch( Exception e) { + e.printStackTrace(); + } + } + + +public static class Template implements ASN1Template { + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicit, InputStream istream) + throws IOException, InvalidBERException + { + SEQUENCE.OF_Template seqt = new SEQUENCE.OF_Template( + new RDN.Template() ); + SEQUENCE seq = (SEQUENCE) seqt.decode(implicit, istream); + return new Name( seq ); + } +} + +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/primitive/PBEParameter.java b/mozilla/security/jss/org/mozilla/jss/pkix/primitive/PBEParameter.java new file mode 100644 index 00000000000..75e8499692b --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/primitive/PBEParameter.java @@ -0,0 +1,145 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkix.primitive; + +import com.netscape.jss.asn1.*; +import java.io.*; + +/** + * PKCS #5 PBEParameter, and PKCS #12 pkcs-12PbeParams. The only + * difference between the two is that PKCS #5 dictates that the size of the + * salt must be 8 bytes, while PKCS #12 leaves the salt length undefined. + * To work with both standards, this class does not check the length of the + * salt but rather leaves that to the application. + */ +public class PBEParameter implements ASN1Value { + + /////////////////////////////////////////////////////////////////////// + // members and member access + /////////////////////////////////////////////////////////////////////// + private byte[] salt; + private int iterations; + private SEQUENCE sequence; + + public byte[] getSalt() { + return salt; + } + + public int getIterations() { + return iterations; + } + + /////////////////////////////////////////////////////////////////////// + // constructors + /////////////////////////////////////////////////////////////////////// + private PBEParameter() { } + + /** + * Creates a PBEParameter from a salt and iteration count. Neither + * may be null. + */ + public PBEParameter(byte[] salt, int iterations) { + this.salt = salt; + this.iterations = iterations; + sequence = new SEQUENCE(); + sequence.addElement( new OCTET_STRING(salt) ); + sequence.addElement( new INTEGER(iterations) ); + } + + /** + * Creates a PBEParameter from a salt and iteration count. Neither + * may be null. + */ + public PBEParameter(OCTET_STRING salt, INTEGER iterations) { + this( salt.toByteArray(), iterations.intValue() ); + } + + /////////////////////////////////////////////////////////////////////// + // DER encoding + /////////////////////////////////////////////////////////////////////// + + private static final Tag TAG = SEQUENCE.TAG; + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + sequence.encode(ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + sequence.encode(implicitTag, ostream); + } + + + private static final Template templateInstance = new Template(); + public static Template getTemplate() { + return templateInstance; + } + + /** + * A template class for decoding a PBEParameter. + */ + public static class Template implements ASN1Template { + + private SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + seqt.addElement( OCTET_STRING.getTemplate() ); + seqt.addElement( INTEGER.getTemplate() ); + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws InvalidBERException, IOException + { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws InvalidBERException, IOException + { + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); + + return new PBEParameter( (OCTET_STRING) seq.elementAt(0), + (INTEGER) seq.elementAt(1) ); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/primitive/PrivateKeyInfo.java b/mozilla/security/jss/org/mozilla/jss/pkix/primitive/PrivateKeyInfo.java new file mode 100644 index 00000000000..0930e8bbff5 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/primitive/PrivateKeyInfo.java @@ -0,0 +1,198 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkix.primitive; + +import com.netscape.jss.asn1.*; +import java.io.*; +import com.netscape.jss.crypto.PrivateKey; +import java.security.NoSuchAlgorithmException; + +public class PrivateKeyInfo + implements ASN1Value, java.security.PrivateKey { + + /////////////////////////////////////////////////////////////////////// + // members and member access + /////////////////////////////////////////////////////////////////////// + private INTEGER version; + private AlgorithmIdentifier privateKeyAlgorithm; + private OCTET_STRING privateKey; + private SET attributes; // may be null + private SEQUENCE sequence; + + public INTEGER getVersion() { + return version; + } + + public AlgorithmIdentifier getPrivateKeyAlgorithm() { + return privateKeyAlgorithm; + } + + public String getAlgorithm() { + try { + return PrivateKey.Type.fromOID(privateKeyAlgorithm.getOID()) + .toString(); + } catch( NoSuchAlgorithmException e ) { + return null; + } + } + + public String getFormat() { + return "PKCS#8"; + } + + public byte[] getEncoded() { + return privateKey.toByteArray(); + } + + public OCTET_STRING getPrivateKey() { + return privateKey; + } + + /** + * May return null if no attributes are present. + */ + public SET getAttributes() { + return attributes; + } + + /////////////////////////////////////////////////////////////////////// + // Constructors + /////////////////////////////////////////////////////////////////////// + + private PrivateKeyInfo() { } + + /** + * Create a PrivateKeyInfo from its components. + * + * @param attributes May be null if there are no attributes, in which + * case the attributes field will be omitted from the DER encoding. + * Each element must be a com.netscape.jss.pkix.primitive.Attribute. + */ + public PrivateKeyInfo(INTEGER version, + AlgorithmIdentifier privateKeyAlgorithm, + OCTET_STRING privateKey, SET attributes) + { + if( version==null || privateKeyAlgorithm==null || privateKey==null ) { + throw new IllegalArgumentException( + "PrivateKeyInfo parameter is null"); + } + + this.version = version; + this.privateKeyAlgorithm = privateKeyAlgorithm; + this.privateKey = privateKey; + this.attributes = attributes; + + sequence = new SEQUENCE(); + sequence.addElement(version); + sequence.addElement(privateKeyAlgorithm); + sequence.addElement(privateKey); + + if(attributes!=null) { + sequence.addElement( new Tag(0), attributes ); + + // make sure all the attributes are Attributes + int size = attributes.size(); + for(int i=0; i < size; i++) { + if( ! (attributes.elementAt(i) instanceof Attribute) ) { + throw new IllegalArgumentException("element "+i+ + " of attributes is not an Attribute"); + } + } + } + } + + /////////////////////////////////////////////////////////////////////// + // DER encoding + /////////////////////////////////////////////////////////////////////// + + private static final Tag TAG = SEQUENCE.TAG; + + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + sequence.encode(ostream); + } + + public void encode(Tag implicitTag, OutputStream ostream) + throws IOException + { + sequence.encode(implicitTag, ostream); + } + + private static final Template templateInstance = new Template(); + public static Template getTemplate() { + return templateInstance; + } + + /** + * A template class for decoding PrivateKeyInfos from BER. + */ + public static class Template implements ASN1Template { + + private SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + + seqt.addElement( INTEGER.getTemplate() ); + seqt.addElement( AlgorithmIdentifier.getTemplate() ); + seqt.addElement( OCTET_STRING.getTemplate() ); + seqt.addOptionalElement( new Tag(0), + new SET.OF_Template( Attribute.getTemplate() ) ); + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws InvalidBERException, IOException + { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicitTag, InputStream istream) + throws InvalidBERException, IOException + { + SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); + + return new PrivateKeyInfo( (INTEGER) seq.elementAt(0), + (AlgorithmIdentifier) seq.elementAt(1), + (OCTET_STRING) seq.elementAt(2), + (SET) seq.elementAt(3) ); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/primitive/RDN.java b/mozilla/security/jss/org/mozilla/jss/pkix/primitive/RDN.java new file mode 100644 index 00000000000..1965ebf1ff5 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/primitive/RDN.java @@ -0,0 +1,134 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.pkix.primitive; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; +import com.netscape.jss.asn1.*; + +/** + * A RelativeDistinguishedName, whose ASN.1 is: + *
+ * RelativeDistinguishedName ::= SET SIZE(1..MAX) OF AttributeValueAssertion
+ * 
+ */ +public class RDN implements ASN1Value { + + private SET avas; + + private RDN() { } + + /** + * An RDN must have at least one element at all times, so an initial + * element must be provided. + */ + public RDN(AVA initialElement) { + avas = new SET(); + avas.addElement(initialElement); + } + + // This is for private use only, so we can be constructed from our + // template. + RDN(SET avas) { + this.avas = avas; + } + + public void add( AVA ava ) { + avas.addElement( ava ); + } + + public AVA at( int idx ) { + return (AVA) avas.elementAt( idx ); + } + + /** + * @exception TooFewElementsException If removing this element would + * result in the RDN being empty. + */ + public void removeAt( int idx ) throws TooFewElementsException { + if( avas.size() <= 1 ) { + throw new TooFewElementsException(); + } + avas.removeElementAt( idx ); + } + + public int size() { + return avas.size(); + } + + public static final Tag TAG = SET.TAG; + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + avas.encode(ostream); + } + + public void encode(Tag implicit, OutputStream ostream) + throws IOException + { + avas.encode(implicit, ostream); + } + +public static class Template implements ASN1Template { + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicit, InputStream istream) + throws IOException, InvalidBERException + { + AVA.Template avatemp = new AVA.Template(); + SET.OF_Template sett = new SET.OF_Template( avatemp ); + + SET set = (SET) sett.decode(implicit, istream); + + if(set.size() < 1) { + throw new InvalidBERException("RDN with zero elements; "+ + "an RDN must have at least one element"); + } + + return new RDN(set); + } +} + +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/primitive/SubjectPublicKeyInfo.java b/mozilla/security/jss/org/mozilla/jss/pkix/primitive/SubjectPublicKeyInfo.java new file mode 100644 index 00000000000..c33bffde078 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/primitive/SubjectPublicKeyInfo.java @@ -0,0 +1,181 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.pkix.primitive; + +import com.netscape.jss.asn1.*; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; +import com.netscape.jss.util.Assert; +import java.security.PublicKey; +import java.security.NoSuchAlgorithmException; +import com.netscape.jss.crypto.PrivateKey; +import com.netscape.jss.crypto.InvalidKeyFormatException; +import com.netscape.jss.pkcs11.PK11PubKey; + +/** + * A SubjectPublicKeyInfo, which stores information about a public key. + * This class implements java.security.PublicKey. + */ +public class SubjectPublicKeyInfo + implements ASN1Value, java.security.PublicKey { + + private AlgorithmIdentifier algorithm; + private BIT_STRING subjectPublicKey; + + public String getAlgorithm() { + try { + return PrivateKey.Type.fromOID(algorithm.getOID()).toString(); + } catch( NoSuchAlgorithmException e ) { + // unknown algorithm + return null; + } + } + + public String getFormat() { + return "X.509"; + } + + public byte[] getEncoded() { + if( subjectPublicKey.getPadCount() != 0 ) { + Assert.notReached("public key is not an integral number of bytes"); + return null; + } + return subjectPublicKey.getBits(); + } + + + public AlgorithmIdentifier getAlgorithmIdentifier() { + return algorithm; + } + + public BIT_STRING getSubjectPublicKey() { + return subjectPublicKey; + } + + private SubjectPublicKeyInfo() { } + + public SubjectPublicKeyInfo(AlgorithmIdentifier algorithm, + BIT_STRING subjectPublicKey) + { + this.algorithm = algorithm; + this.subjectPublicKey = subjectPublicKey; + } + + public SubjectPublicKeyInfo(PublicKey pubk) + throws InvalidBERException, IOException + { + SubjectPublicKeyInfo spki = (SubjectPublicKeyInfo) + ASN1Util.decode( getTemplate(), pubk.getEncoded() ); + algorithm = spki.algorithm; + subjectPublicKey = spki.subjectPublicKey; + } + + public static final Tag TAG = SEQUENCE.TAG; + + public Tag getTag() { + return TAG; + } + + public void encode(OutputStream ostream) throws IOException { + encode(TAG, ostream); + } + + public void encode(Tag implicit, OutputStream ostream) + throws IOException + { + SEQUENCE seq = new SEQUENCE(); + seq.addElement( algorithm ); + seq.addElement( subjectPublicKey ); + seq.encode( implicit, ostream ); + } + + private static final Template templateInstance = new Template(); + public static Template getTemplate() { + return templateInstance; + } + + /** + * Creates a PublicKey from the public key information. Currently + * only RSA and DSA keys can be converted. + * + * @exception NoSuchAlgorithmException If the cryptographic provider + * does not recognize the algorithm for this public key. + * @exception InvalidKeyFormatException If the subjectPublicKey could + * not be decoded correctly. + */ + public PublicKey toPublicKey() throws NoSuchAlgorithmException, + InvalidKeyFormatException + { + PrivateKey.Type type = PrivateKey.Type.fromOID( algorithm.getOID() ); + + if( subjectPublicKey.getPadCount() != 0 ) { + throw new InvalidKeyFormatException(); + } + + return PK11PubKey.fromRaw(type, subjectPublicKey.getBits() ); + } + + public static class Template implements ASN1Template { + + private SEQUENCE.Template seqt; + + public Template() { + seqt = new SEQUENCE.Template(); + + seqt.addElement( AlgorithmIdentifier.getTemplate() ); + seqt.addElement( BIT_STRING.getTemplate() ); + } + + public boolean tagMatch(Tag tag) { + return TAG.equals(tag); + } + + public ASN1Value decode(InputStream istream) + throws IOException, InvalidBERException + { + return decode(TAG, istream); + } + + public ASN1Value decode(Tag implicit, InputStream istream) + throws IOException, InvalidBERException + { + SEQUENCE seq = (SEQUENCE) seqt.decode(implicit, istream); + + return new SubjectPublicKeyInfo( + (AlgorithmIdentifier) seq.elementAt(0), + (BIT_STRING) seq.elementAt(1) + ); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/primitive/TooFewElementsException.java b/mozilla/security/jss/org/mozilla/jss/pkix/primitive/TooFewElementsException.java new file mode 100644 index 00000000000..3960058e53d --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/primitive/TooFewElementsException.java @@ -0,0 +1,37 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.pkix.primitive; + + +public class TooFewElementsException extends Exception { +} diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/primitive/manifest.mn b/mozilla/security/jss/org/mozilla/jss/pkix/primitive/manifest.mn new file mode 100644 index 00000000000..4fc07ba54bc --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/primitive/manifest.mn @@ -0,0 +1,85 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +CORE_DEPTH = ../../../../../.. + +MODULE = ninja + +NS_USE_JDK = 1 + +PACKAGE = com/netscape/jss/pkix/primitive + +# These are meant to be used within Ninja only. +PRIVATE_EXPORTS = \ + $(NULL) + +JNI_GEN = \ + $(NULL) + +CLASSES = \ + AlgorithmIdentifier \ + Attribute \ + AVA \ + DirectoryString \ + EncryptedPrivateKeyInfo \ + Name \ + PBEParameter \ + PrivateKeyInfo \ + RDN \ + SubjectPublicKeyInfo \ + TooFewElementsException \ + $(NULL) + +PRIVATE_CLASSES = \ + $(NULL) + + +JSRCS = \ + AlgorithmIdentifier.java \ + Attribute.java \ + AVA.java \ + DirectoryString.java \ + EncryptedPrivateKeyInfo.java \ + Name.java \ + PBEParameter.java \ + PrivateKeyInfo.java \ + RDN.java \ + SubjectPublicKeyInfo.java \ + TooFewElementsException.java \ + $(NULL) + +PRIVATE_JSRCS = + + +CSRCS = \ + $(NULL) diff --git a/mozilla/security/jss/org/mozilla/jss/pkix/primitive/package.html b/mozilla/security/jss/org/mozilla/jss/pkix/primitive/package.html new file mode 100644 index 00000000000..254d854f2c5 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/pkix/primitive/package.html @@ -0,0 +1,38 @@ + + + +Frequently-used primitive ASN.1 types, such as AlgorithmIdentifier, +PrivateKeyInfo, and X.500 Name. + + diff --git a/mozilla/security/jss/org/mozilla/jss/provider/DSASignature.java b/mozilla/security/jss/org/mozilla/jss/provider/DSASignature.java new file mode 100644 index 00000000000..a8ffb8e5626 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/provider/DSASignature.java @@ -0,0 +1,117 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.provider; + +import java.security.PrivateKey; +import java.security.SecureRandom; +import java.security.InvalidKeyException; +import java.security.SignatureException; +import java.security.PublicKey; +import java.security.InvalidParameterException; +import com.netscape.jss.crypto.SignatureAlgorithm; +import java.security.spec.AlgorithmParameterSpec; +import java.security.InvalidAlgorithmParameterException; + +public class DSASignature extends java.security.Signature { + + protected Signature sig = new Signature(); + + public DSASignature() { + super("DSA"); + } + + public void engineInitSign(PrivateKey privateKey, SecureRandom random) + throws InvalidKeyException + { + sig.engineInitSign(privateKey, random, + SignatureAlgorithm.DSASignatureWithSHA1Digest); + } + + public void engineInitSign(PrivateKey privateKey) + throws InvalidKeyException + { + sig.engineInitSign(privateKey, + SignatureAlgorithm.DSASignatureWithSHA1Digest); + } + + public void engineInitVerify(PublicKey publicKey) + throws InvalidKeyException + { + sig.engineInitVerify(publicKey, + SignatureAlgorithm.DSASignatureWithSHA1Digest); + } + + public void engineUpdate(byte b) + throws SignatureException + { + sig.engineUpdate(b); + } + + public void engineUpdate(byte[] b, int off, int len) + throws SignatureException + { + sig.engineUpdate(b, off, len); + } + + public byte[] engineSign() throws SignatureException { + return sig.engineSign(); + } + + public int engineSign(byte[] outbuf, int offset, int len) + throws SignatureException + { + return sig.engineSign(outbuf, offset, len); + } + + public boolean engineVerify(byte[] sigBytes) throws SignatureException { + return sig.engineVerify(sigBytes); + } + + public void engineSetParameter(AlgorithmParameterSpec params) + throws InvalidAlgorithmParameterException + { + sig.engineSetParameter(params); + } + + protected void engineSetParameter(String param, Object value) + throws InvalidParameterException + { + throw new InvalidParameterException(); + } + + protected Object engineGetParameter(String param) + throws InvalidParameterException + { + throw new InvalidParameterException(); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/provider/MD2MessageDigest.java b/mozilla/security/jss/org/mozilla/jss/provider/MD2MessageDigest.java new file mode 100644 index 00000000000..d49b7f6c09e --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/provider/MD2MessageDigest.java @@ -0,0 +1,50 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.provider; + +import com.netscape.jss.crypto.DigestAlgorithm; + +/** + * The JSS JCA MD2 provider. + */ +public class MD2MessageDigest extends MessageDigest { + + public MD2MessageDigest() { + super(DigestAlgorithm.MD2.toString()); + } + + protected DigestAlgorithm getAlg() { + return DigestAlgorithm.MD2; + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/provider/MD2RSASignature.java b/mozilla/security/jss/org/mozilla/jss/provider/MD2RSASignature.java new file mode 100644 index 00000000000..b6c237bc799 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/provider/MD2RSASignature.java @@ -0,0 +1,117 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.provider; + +import java.security.PrivateKey; +import java.security.SecureRandom; +import java.security.SignatureException; +import java.security.InvalidKeyException; +import java.security.PublicKey; +import java.security.InvalidParameterException; +import com.netscape.jss.crypto.SignatureAlgorithm; +import java.security.spec.AlgorithmParameterSpec; +import java.security.InvalidAlgorithmParameterException; + +public class MD2RSASignature extends java.security.Signature { + + protected Signature sig = new Signature(); + + public MD2RSASignature() { + super("MD2/RSA"); + } + + public void engineInitSign(PrivateKey privateKey, SecureRandom random) + throws InvalidKeyException + { + sig.engineInitSign(privateKey, random, + SignatureAlgorithm.RSASignatureWithMD2Digest); + } + + public void engineInitSign(PrivateKey privateKey) + throws InvalidKeyException + { + sig.engineInitSign(privateKey, + SignatureAlgorithm.RSASignatureWithMD2Digest); + } + + public void engineInitVerify(PublicKey publicKey) + throws InvalidKeyException + { + sig.engineInitVerify(publicKey, + SignatureAlgorithm.RSASignatureWithMD2Digest); + } + + public void engineUpdate(byte b) + throws SignatureException + { + sig.engineUpdate(b); + } + + public void engineUpdate(byte[] b, int off, int len) + throws SignatureException + { + sig.engineUpdate(b, off, len); + } + + public byte[] engineSign() throws SignatureException { + return sig.engineSign(); + } + + public int engineSign(byte[] outbuf, int offset, int len) + throws SignatureException + { + return sig.engineSign(outbuf, offset, len); + } + + public boolean engineVerify(byte[] sigBytes) throws SignatureException { + return sig.engineVerify(sigBytes); + } + + public void engineSetParameter(AlgorithmParameterSpec params) + throws InvalidAlgorithmParameterException + { + sig.engineSetParameter(params); + } + + protected void engineSetParameter(String param, Object value) + throws InvalidParameterException + { + throw new InvalidParameterException(); + } + + protected Object engineGetParameter(String param) + throws InvalidParameterException + { + throw new InvalidParameterException(); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/provider/MD5MessageDigest.java b/mozilla/security/jss/org/mozilla/jss/provider/MD5MessageDigest.java new file mode 100644 index 00000000000..48e74973e83 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/provider/MD5MessageDigest.java @@ -0,0 +1,50 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.provider; + +import com.netscape.jss.crypto.DigestAlgorithm; + +/** + * The JSS JCA MD5 provider. + */ +public class MD5MessageDigest extends MessageDigest { + + public MD5MessageDigest() { + super(DigestAlgorithm.MD5.toString()); + } + + protected DigestAlgorithm getAlg() { + return DigestAlgorithm.MD5; + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/provider/MD5RSASignature.java b/mozilla/security/jss/org/mozilla/jss/provider/MD5RSASignature.java new file mode 100644 index 00000000000..fa4bff3a4c1 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/provider/MD5RSASignature.java @@ -0,0 +1,117 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.provider; + +import java.security.PrivateKey; +import java.security.SecureRandom; +import java.security.SignatureException; +import java.security.InvalidKeyException; +import java.security.PublicKey; +import java.security.InvalidParameterException; +import com.netscape.jss.crypto.SignatureAlgorithm; +import java.security.spec.AlgorithmParameterSpec; +import java.security.InvalidAlgorithmParameterException; + +public class MD5RSASignature extends java.security.Signature { + + protected Signature sig = new Signature(); + + public MD5RSASignature() { + super("MD5/RSA"); + } + + public void engineInitSign(PrivateKey privateKey, SecureRandom random) + throws InvalidKeyException + { + sig.engineInitSign(privateKey, random, + SignatureAlgorithm.RSASignatureWithMD5Digest); + } + + public void engineInitSign(PrivateKey privateKey) + throws InvalidKeyException + { + sig.engineInitSign(privateKey, + SignatureAlgorithm.RSASignatureWithMD5Digest); + } + + public void engineInitVerify(PublicKey publicKey) + throws InvalidKeyException + { + sig.engineInitVerify(publicKey, + SignatureAlgorithm.RSASignatureWithMD5Digest); + } + + public void engineUpdate(byte b) + throws SignatureException + { + sig.engineUpdate(b); + } + + public void engineUpdate(byte[] b, int off, int len) + throws SignatureException + { + sig.engineUpdate(b, off, len); + } + + public byte[] engineSign() throws SignatureException { + return sig.engineSign(); + } + + public int engineSign(byte[] outbuf, int offset, int len) + throws SignatureException + { + return sig.engineSign(outbuf, offset, len); + } + + public boolean engineVerify(byte[] sigBytes) throws SignatureException { + return sig.engineVerify(sigBytes); + } + + public void engineSetParameter(AlgorithmParameterSpec params) + throws InvalidAlgorithmParameterException + { + sig.engineSetParameter(params); + } + + protected void engineSetParameter(String param, Object value) + throws InvalidParameterException + { + throw new InvalidParameterException(); + } + + protected Object engineGetParameter(String param) + throws InvalidParameterException + { + throw new InvalidParameterException(); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/provider/Makefile b/mozilla/security/jss/org/mozilla/jss/provider/Makefile new file mode 100644 index 00000000000..155e7145452 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/provider/Makefile @@ -0,0 +1,76 @@ +#! gmake +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + + +####################################################################### +# (1) Include initial platform-independent assignments (MANDATORY). # +####################################################################### + +include manifest.mn + +####################################################################### +# (2) Include "global" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/config.mk + +####################################################################### +# (3) Include "component" configuration information. (OPTIONAL) # +####################################################################### +include $(CORE_DEPTH)/$(MODULE)/config/config.mk + + +####################################################################### +# (4) Include "local" platform-dependent assignments (OPTIONAL). # +####################################################################### + + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### +include $(CORE_DEPTH)/$(MODULE)/config/rules.mk + + + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### + + diff --git a/mozilla/security/jss/org/mozilla/jss/provider/MessageDigest.java b/mozilla/security/jss/org/mozilla/jss/provider/MessageDigest.java new file mode 100644 index 00000000000..78af4d7f936 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/provider/MessageDigest.java @@ -0,0 +1,133 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.provider; + +import com.netscape.jss.crypto.*; +import com.netscape.jss.util.Debug; +import com.netscape.jss.util.Assert; +import java.security.DigestException; +import java.security.NoSuchAlgorithmException; + +/** + * A JCA provider of message digesting implemented with + * Netscape Security Services. One big problem is the Sun interface doesn't + * thrown any exceptions, so I can't thrown any exceptions, even though + * lots can go wrong. + */ +abstract class MessageDigest extends java.security.MessageDigest { + + private com.netscape.jss.crypto.JSSMessageDigest md; + + /** + * Returns the particular algorithm that the subclass is implementing. + */ + protected abstract DigestAlgorithm getAlg(); + + /** + * Creates a JSS MessageDigest provider object. + */ + protected MessageDigest(String algName) { + super( algName ); + + try { + Debug.trace(Debug.OBNOXIOUS, "In JSS JCA message digest constructor"); + CryptoToken internal = TokenSupplierManager.getTokenSupplier(). + getInternalCryptoToken(); + md = internal.getDigestContext( getAlg() ); + } catch( java.security.NoSuchAlgorithmException e ) { + Debug.trace(Debug.ERROR, "Unknown message digesting algorithm: "+ + algName); + Assert.notReached("Unknown message digesting algorithm"); + } catch( DigestException e ) { + Debug.trace(Debug.ERROR, "Digest Exception while creating "+ + algName + " digest" ); + Assert.notReached("Digest exception creating message digest"); + } + } + + protected void engineUpdate(byte input) { + try { + Debug.trace(Debug.OBNOXIOUS, "In JSS JCA message digest engineUpdate"); + md.update(input); + } catch( DigestException e ) { + Debug.trace(Debug.ERROR, "Digest Exception while updating digest"); + Assert.notReached("Digest exception while updating digest"); + } + } + + protected void engineUpdate(byte[] input, int offset, int len) { + try { + + Debug.trace(Debug.OBNOXIOUS, "In JSS JCA message digest engineUpdate"); + md.update(input, offset, len); + + } catch( DigestException e ) { + Debug.trace(Debug.ERROR, "Digest Exception while updating digest"); + Assert.notReached("Digest exception while updating digest"); + } + } + + protected byte[] engineDigest() { + try { + + Debug.trace(Debug.OBNOXIOUS, "In JSS JCA message digest engineDigest"); + return md.digest(); + + } catch( DigestException e ) { + Debug.trace(Debug.ERROR, "Digest Exception while finalizing digest"); + Assert.notReached("Digest exception while finalizing digest"); + return null; + } + } + + protected void engineReset() { + try { + + Debug.trace(Debug.OBNOXIOUS, "In JSS JCA message digest engineReset"); + md.reset(); + + } catch( DigestException e ) { + Debug.trace(Debug.ERROR, "Digest Exception while resetting digest"); + Assert.notReached("Digest exception while resetting digest"); + } + } + + /** + * Throws CloneNotSupportedException, because this implementation is + * not clonable. + */ + public Object clone() throws CloneNotSupportedException { + throw new CloneNotSupportedException(); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/provider/Provider.java b/mozilla/security/jss/org/mozilla/jss/provider/Provider.java new file mode 100644 index 00000000000..f231640eb6b --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/provider/Provider.java @@ -0,0 +1,77 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.provider; + +public class Provider extends java.security.Provider { + + public Provider() { + super("Netscape", 1.4, + "Provides Signature and Message Digesting"); + + ///////////////////////////////////////////////////////////// + // Signature + ///////////////////////////////////////////////////////////// + + put("Signature.SHA1withDSA", "com.netscape.jss.provider.DSASignature"); + + put("Alg.Alias.Signature.DSA", "SHA1withDSA"); + put("Alg.Alias.Signature.DSS", "SHA1withDSA"); + put("Alg.Alias.Signature.SHA/DSA", "SHA1withDSA"); + put("Alg.Alias.Signature.SHA-1/DSA", "SHA1withDSA"); + put("Alg.Alias.Signature.SHA1/DSA", "SHA1withDSA"); + put("Alg.Alias.Signature.DSAWithSHA1", "SHA1withDSA"); + put("Alg.Alias.Signature.SHAwithDSA", "SHA1withDSA"); + + put("Signature.MD5/RSA", "com.netscape.jss.provider.MD5RSASignature"); + put("Signature.MD2/RSA", "com.netscape.jss.provider.MD2RSASignature"); + put("Signature.SHA-1/RSA", + "com.netscape.jss.provider.SHA1RSASignature"); + + put("Alg.Alias.Signature.SHA1/RSA", "SHA-1/RSA"); + + ///////////////////////////////////////////////////////////// + // Message Digesting + ///////////////////////////////////////////////////////////// + + put("MessageDigest.SHA-1", + "com.netscape.jss.provider.SHA1MessageDigest"); + put("MessageDigest.MD2", + "com.netscape.jss.provider.MD2MessageDigest"); + put("MessageDigest.MD5", + "com.netscape.jss.provider.MD5MessageDigest"); + + put("Alg.Alias.MessageDigest.SHA1", "SHA-1"); + put("Alg.Alias.MessageDigest.SHA", "SHA-1"); + + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/provider/SHA1MessageDigest.java b/mozilla/security/jss/org/mozilla/jss/provider/SHA1MessageDigest.java new file mode 100644 index 00000000000..186e6457e4c --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/provider/SHA1MessageDigest.java @@ -0,0 +1,50 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.provider; + +import com.netscape.jss.crypto.DigestAlgorithm; + +/** + * The JSS JCA SHA1 provider. + */ +public class SHA1MessageDigest extends MessageDigest { + + public SHA1MessageDigest() { + super(DigestAlgorithm.SHA1.toString()); + } + + protected DigestAlgorithm getAlg() { + return DigestAlgorithm.SHA1; + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/provider/SHA1RSASignature.java b/mozilla/security/jss/org/mozilla/jss/provider/SHA1RSASignature.java new file mode 100644 index 00000000000..f0ce3b2bf29 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/provider/SHA1RSASignature.java @@ -0,0 +1,117 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.provider; + +import java.security.PrivateKey; +import java.security.SecureRandom; +import java.security.SignatureException; +import java.security.InvalidKeyException; +import java.security.PublicKey; +import java.security.InvalidParameterException; +import com.netscape.jss.crypto.SignatureAlgorithm; +import java.security.spec.AlgorithmParameterSpec; +import java.security.InvalidAlgorithmParameterException; + +public class SHA1RSASignature extends java.security.Signature { + + protected Signature sig = new Signature(); + + public SHA1RSASignature() { + super("SHA-1/RSA"); + } + + public void engineInitSign(PrivateKey privateKey, SecureRandom random) + throws InvalidKeyException + { + sig.engineInitSign(privateKey, random, + SignatureAlgorithm.RSASignatureWithSHA1Digest); + } + + public void engineInitSign(PrivateKey privateKey) + throws InvalidKeyException + { + sig.engineInitSign(privateKey, + SignatureAlgorithm.RSASignatureWithSHA1Digest); + } + + public void engineInitVerify(PublicKey publicKey) + throws InvalidKeyException + { + sig.engineInitVerify(publicKey, + SignatureAlgorithm.RSASignatureWithSHA1Digest); + } + + public void engineUpdate(byte b) + throws SignatureException + { + sig.engineUpdate(b); + } + + public void engineUpdate(byte[] b, int off, int len) + throws SignatureException + { + sig.engineUpdate(b, off, len); + } + + public byte[] engineSign() throws SignatureException { + return sig.engineSign(); + } + + public int engineSign(byte[] outbuf, int offset, int len) + throws SignatureException + { + return sig.engineSign(outbuf, offset, len); + } + + public boolean engineVerify(byte[] sigBytes) throws SignatureException { + return sig.engineVerify(sigBytes); + } + + public void engineSetParameter(AlgorithmParameterSpec params) + throws InvalidAlgorithmParameterException + { + sig.engineSetParameter(params); + } + + protected void engineSetParameter(String param, Object value) + throws InvalidParameterException + { + throw new InvalidParameterException(); + } + + protected Object engineGetParameter(String param) + throws InvalidParameterException + { + throw new InvalidParameterException(); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/provider/Signature.java b/mozilla/security/jss/org/mozilla/jss/provider/Signature.java new file mode 100644 index 00000000000..8b8f26d994c --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/provider/Signature.java @@ -0,0 +1,158 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.provider; + +import java.security.SecureRandom; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.PublicKey; +import com.netscape.jss.crypto.*; +import java.security.SignatureException; +import java.security.spec.AlgorithmParameterSpec; +import java.security.InvalidAlgorithmParameterException; + +public class Signature { + + com.netscape.jss.crypto.Signature sig; + + public void engineInitSign(java.security.PrivateKey privateKey, + SecureRandom random, SignatureAlgorithm sigAlg) + throws InvalidKeyException + { + // discard the random + engineInitSign(privateKey, sigAlg); + } + + public void engineInitSign(java.security.PrivateKey privateKey, + SignatureAlgorithm sigAlg) throws InvalidKeyException + { + try { + sig = getSigContext(privateKey, sigAlg); + sig.initSign((PrivateKey)privateKey); + } catch(java.security.NoSuchAlgorithmException e) { + throw new InvalidKeyException("Algorithm not supported"); + } catch(TokenException e) { + throw new InvalidKeyException("Token exception occurred"); + } + } + + protected static com.netscape.jss.crypto.Signature + getSigContext(java.security.PrivateKey privateKey, + SignatureAlgorithm sigAlg) + throws NoSuchAlgorithmException, InvalidKeyException, TokenException + { + CryptoToken token; + PrivateKey privk; + + if( ! (privateKey instanceof PrivateKey) ) { + throw new InvalidKeyException(); + } + privk = (PrivateKey)privateKey; + + token = privk.getOwningToken(); + + return token.getSignatureContext(sigAlg); + } + + public void engineInitVerify(PublicKey publicKey, SignatureAlgorithm sigAlg) + throws InvalidKeyException + { + try { + CryptoToken token = + TokenSupplierManager.getTokenSupplier().getInternalCryptoToken(); + sig = token.getSignatureContext(sigAlg); + sig.initVerify(publicKey); + } catch(java.security.NoSuchAlgorithmException e) { + throw new InvalidKeyException("Algorithm not supported"); + } catch(TokenException e) { + throw new InvalidKeyException("Token exception occurred"); + } + } + + public void engineUpdate(byte b) + throws SignatureException + { + try { + sig.update(b); + } catch( TokenException e) { + throw new SignatureException("TokenException: "+e.toString()); + } + } + + public void engineUpdate(byte[] b, int off, int len) + throws SignatureException + { + try { + sig.update(b, off, len); + } catch( TokenException e) { + throw new SignatureException("TokenException: "+e.toString()); + } + } + + public byte[] engineSign() throws SignatureException { + try { + return sig.sign(); + } catch(TokenException e) { + throw new SignatureException("TokenException: "+e.toString()); + } + } + + public int engineSign(byte[] outbuf, int offset, int len) + throws SignatureException + { + try { + return sig.sign(outbuf, offset, len); + } catch(TokenException e) { + throw new SignatureException("TokenException: "+e.toString()); + } + } + + public boolean engineVerify(byte[] sigBytes) throws SignatureException { + try { + return sig.verify(sigBytes); + } catch( TokenException e) { + throw new SignatureException("TokenException: "+e.toString()); + } + } + + public void engineSetParameter(AlgorithmParameterSpec params) + throws InvalidAlgorithmParameterException + { + try { + sig.setParameter(params); + } catch( TokenException e ) { + throw new InvalidAlgorithmParameterException( + "TokenException: "+e.toString()); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/provider/manifest.mn b/mozilla/security/jss/org/mozilla/jss/provider/manifest.mn new file mode 100644 index 00000000000..5ae2b4622c3 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/provider/manifest.mn @@ -0,0 +1,68 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +CORE_DEPTH = ../../../../.. + +MODULE = ninja + +NS_USE_JDK = 1 + +PACKAGE = com/netscape/jss/provider + +REQUIRES = nspr20 dbm security + +CLASSES = \ + MD5MessageDigest \ + MD2MessageDigest \ + MessageDigest \ + Provider \ + Signature \ + DSASignature \ + MD5RSASignature \ + MD2RSASignature \ + SHA1MessageDigest \ + SHA1RSASignature \ + $(NULL) + +JSRCS = \ + MD5MessageDigest.java \ + MD2MessageDigest.java \ + MessageDigest.java \ + Provider.java \ + Signature.java \ + DSASignature.java \ + MD5RSASignature.java \ + MD2RSASignature.java \ + SHA1MessageDigest.java \ + SHA1RSASignature.java \ + $(NULL) diff --git a/mozilla/security/jss/org/mozilla/jss/rules.mk b/mozilla/security/jss/org/mozilla/jss/rules.mk new file mode 100644 index 00000000000..4b62eb196a2 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/rules.mk @@ -0,0 +1,95 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +ifeq ($(JAVADOC_NSS),1) +JAVADOC_TARGETS= \ + com.netscape.jss.NSSInit \ + com.netscape.jss.KeyDatabaseException \ + com.netscape.jss.CertDatabaseException \ + com.netscape.jss.crypto.AlreadyInitializedException \ + com.netscape.jss.util.Password \ + com.netscape.jss.util.PasswordCallback \ + com.netscape.jss.util.PasswordCallbackInfo \ + com.netscape.jss.util.ConsolePasswordCallback \ + com.netscape.jss.ssl.PrintOutputStreamWriter \ + com.netscape.jss.ssl.SSLHandshakeCompletedEvent \ + com.netscape.jss.ssl.SSLHandshakeCompletedListener\ + com.netscape.jss.ssl.SSLInputStream \ + com.netscape.jss.ssl.SSLOutputStream \ + com.netscape.jss.ssl.SSLSecurityStatus \ + com.netscape.jss.ssl.SSLServerSocket \ + com.netscape.jss.ssl.SSLSocket \ + com.netscape.jss.ssl.SSLSocketImpl \ + $(NULL) +else +JAVADOC_TARGETS= \ + com.netscape.jss.util.Assert \ + com.netscape.jss.util.AssertionException \ + com.netscape.jss.util.Password \ + com.netscape.jss.util.PasswordCallback \ + com.netscape.jss.util.IncorrectPasswordException \ + com.netscape.jss.util.NotImplementedException \ + com.netscape.jss.util.NullPasswordCallback\ + com.netscape.jss.util.ConsolePasswordCallback\ + com.netscape.jss.util.PasswordCallbackInfo\ + com.netscape.jss.util.UTF8Converter \ + util/Debug.java \ + com.netscape.jss.crypto \ + com.netscape.jss \ + com.netscape.jss.pkcs11.PK11Module \ + com.netscape.jss.ssl \ + com.netscape.jss.asn1 \ + com.netscape.jss.pkix.primitive \ + com.netscape.jss.pkix.cert \ + com.netscape.jss.pkix.crmf \ + com.netscape.jss.pkix.cmmf \ + com.netscape.jss.pkcs7 \ + com.netscape.jss.pkcs12 \ + $(NULL) +endif + +ifndef NUKE_JAVA_FILES +javadoc: + @echo \ +"Generating Javadoc will destroy any .java files in the top-level" + @echo \ +"ns/ninja/com/netscape/jss directory. You must set the NUKE_JAVA_FILES" + @echo \ +"environment variable to confirm that this is OK." +else +javadoc: + cp manage/*.java . + if [ ! -d "$(CORE_DEPTH)/ninja/doc" ] ; then mkdir $(CORE_DEPTH)/ninja/doc; fi + /share/builds/components/cms_jdk/SunOS/1.2.2_05a/bin/javadoc -native -public -sourcepath $(CORE_DEPTH)/ninja -d $(CORE_DEPTH)/ninja/doc $(JAVADOC_TARGETS) + rm *.java +endif diff --git a/mozilla/security/jss/org/mozilla/jss/tests/CloseDBs.java b/mozilla/security/jss/org/mozilla/jss/tests/CloseDBs.java new file mode 100644 index 00000000000..efa4bbd7869 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/tests/CloseDBs.java @@ -0,0 +1,89 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss; + +import com.netscape.jss.crypto.*; +import java.util.Enumeration; +import java.math.BigInteger; + +public final class CloseDBs extends com.netscape.jss.DatabaseCloser { + + public CloseDBs() throws Exception { + super(); + } + + public static void main(String args[]) { + int i; + try { + if(args.length != 1) { + System.err.println("Usage: CloseDBs "); + System.exit(0); + } + + CryptoManager.initialize( args[0] +"/secmod.db", + args[0] +"/key3.db", + args[0] +"/cert7.db" ); + + CryptoManager manager = CryptoManager.getInstance(); + + Enumeration tokens = manager.getAllTokens(); + CryptoStore store; + X509Certificate certs[]; + PrivateKey keys[]; + while(tokens.hasMoreElements()) { + CryptoToken token = (CryptoToken) tokens.nextElement(); + store = token.getCryptoStore(); + System.out.println("Token: "+token.getName()); + + certs = store.getCertificates(); + System.out.println("Certs:"); + for(i=0; i < certs.length; i++) { + System.out.println( certs[i].getNickname() ); + } + + keys = store.getPrivateKeys(); + System.out.println("Keys:"); + for(i=0; i < keys.length; i++) { + System.out.println( new BigInteger( keys[i].getUniqueID() ) ); + } + } + + System.out.println("Closing databases..."); + (new CloseDBs()).closeDatabases(); + System.out.println("Databases are closed."); + } catch(Exception e) { + e.printStackTrace(); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/tests/DigestTest.java b/mozilla/security/jss/org/mozilla/jss/tests/DigestTest.java new file mode 100644 index 00000000000..336eb100928 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/tests/DigestTest.java @@ -0,0 +1,133 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.crypto; + +import java.io.*; +import com.netscape.jss.CryptoManager; +import com.netscape.jss.util.Password; +import com.netscape.jss.util.Debug; +import java.security.MessageDigest; + +public class DigestTest { + + public static void main(String []argv) { + + try { + + Debug.setLevel(Debug.OBNOXIOUS); + + if( argv.length != 2 ) { + System.out.println("Usage: DigestTest "); + System.exit(0); + } + String dbdir = argv[0]; + FileInputStream fis = new FileInputStream(argv[1]); + byte[] toBeDigested = new byte[ fis.available() ]; + int read = fis.read( toBeDigested ); + System.out.println(read + " bytes to be digested"); + byte[] nsdigestOut; + byte[] sundigestOut; + + CryptoManager.initialize(dbdir+"/secmod.db", dbdir+"/key3.db", + dbdir+"/cert7.db"); + + ///////////////////////////////////////////////////////////// + // Install SUN provider + java.security.Security.addProvider(new sun.security.provider.Sun() ); + + ///////////////////////////////////////////////////////////// + // Test SHA-1 + ///////////////////////////////////////////////////////////// + java.security.MessageDigest nsdigest = + java.security.MessageDigest.getInstance("SHA-1", "Netscape"); + java.security.MessageDigest sundigest = + java.security.MessageDigest.getInstance("SHA-1", "SUN"); + + nsdigestOut = nsdigest.digest(toBeDigested); + sundigestOut = sundigest.digest(toBeDigested); + + if( MessageDigest.isEqual(nsdigestOut, sundigestOut) ) { + System.out.println("Sun and Netscape give same SHA-1 hash"); + } else { + System.out.println("ERROR: Sun and Netscape give different"+ + " SHA-1 hashes"); + } + + ///////////////////////////////////////////////////////////// + // Test MD5 + ///////////////////////////////////////////////////////////// + nsdigest = java.security.MessageDigest.getInstance("MD5", "Netscape"); + sundigest = java.security.MessageDigest.getInstance("MD5", "SUN"); + + nsdigestOut = nsdigest.digest(toBeDigested); + sundigestOut = sundigest.digest(toBeDigested); + + if( MessageDigest.isEqual(nsdigestOut, sundigestOut) ) { + System.out.println("Sun and Netscape give same MD5 hash"); + } else { + System.out.println("ERROR: Sun and Netscape give different"+ + " MD5 hashes"); + } + + ///////////////////////////////////////////////////////////// + // Test SHA-1 HMAC + ///////////////////////////////////////////////////////////// + CryptoManager cm = CryptoManager.getInstance(); + CryptoToken token = cm.getInternalCryptoToken(); + byte[] salt = { 0, 1, 2, 3,4 ,5 ,6 ,7 }; + PBEKeyGenParams pbe = new PBEKeyGenParams( + new Password("password".toCharArray()), + salt, + 1 ); + KeyGenerator kg = token.getKeyGenerator( + PBEAlgorithm.PBE_SHA1_DES3_CBC ); + kg.initialize(pbe); + SymmetricKey symkey = kg.generate(); + com.netscape.jss.crypto.JSSMessageDigest digest = + token.getDigestContext( HMACAlgorithm.SHA1 ); + digest.initHMAC(symkey); + digest.update(toBeDigested); + byte[] digestOut = digest.digest(); + if( digestOut.length == digest.getOutputSize() ) { + System.out.println("digest output size is " + digestOut.length); + } else { + System.out.println("ERROR: digest output size is "+ + digestOut.length + ", should be "+digest.getOutputSize() ); + } + + + } catch( Exception e ) { + e.printStackTrace(); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/tests/JCASigTest.java b/mozilla/security/jss/org/mozilla/jss/tests/JCASigTest.java new file mode 100644 index 00000000000..27ee86e6716 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/tests/JCASigTest.java @@ -0,0 +1,115 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.crypto; + +import java.security.*; +import java.security.cert.X509Certificate; +import java.io.*; +import com.netscape.jss.util.*; +import com.netscape.jss.*; + +public class JCASigTest { + + public static void usage() { + System.out.println( + "Usage: java com.netscape.jss.crypto.JCASigTest "); + } + + public static void main(String args[]) { + CryptoToken token; + CryptoManager manager; + byte[] data = new byte[] {1,2,3,4,5,6,7,8,9}; + byte[] signature; + java.security.Signature signer; + PublicKey pubk; + KeyPairGenerator kpgen; + KeyPair keyPair; + + Debug.setLevel(Debug.OBNOXIOUS); + + if(args.length != 2) { + usage(); + return; + } + String dbdir = args[0]; + String tokenname = args[1]; + + try { + CryptoManager.InitializationValues vals = new + CryptoManager.InitializationValues + ( args[0]+"/secmod.db", + args[0]+"/key3.db", + args[0]+"/cert7.db" ); + CryptoManager.initialize(vals); + manager = CryptoManager.getInstance(); + + token = manager.getTokenByName(tokenname); + + Provider[] providers = Security.getProviders(); + for(int i=0; i < providers.length; i++) { + System.out.println("Provider "+i+": "+providers[i].getName()); + } + + // Generate an RSA keypair + kpgen = token.getKeyPairGenerator(KeyPairAlgorithm.RSA); + kpgen.initialize(1024); + keyPair = kpgen.genKeyPair(); + + // RSA MD5 + signer = java.security.Signature.getInstance("MD5/RSA"); + System.out.println("Created a signing context"); + signer.initSign( + (com.netscape.jss.crypto.PrivateKey)keyPair.getPrivate()); + System.out.println("initialized the signing operation"); + + signer.update(data); + System.out.println("updated signature with data"); + signature = signer.sign(); + System.out.println("Successfully signed!"); + + signer.initVerify(keyPair.getPublic()); + System.out.println("initialized verification"); + signer.update(data); + System.out.println("updated verification with data"); + if( signer.verify(signature) ) { + System.out.println("Signature Verified Successfully!"); + } else { + System.out.println("ERROR: Signature failed to verify."); + } + + } catch(Exception e) { + e.printStackTrace(); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/tests/KeyWrapping.java b/mozilla/security/jss/org/mozilla/jss/tests/KeyWrapping.java new file mode 100644 index 00000000000..7c39cf2bb47 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/tests/KeyWrapping.java @@ -0,0 +1,153 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss; + +import com.netscape.jss.crypto.*; +import com.netscape.jss.CryptoManager; +import com.netscape.jss.util.Assert; +import com.netscape.jss.util.Password; +import java.security.InvalidAlgorithmParameterException; +import java.security.KeyPair; + +public class KeyWrapping { + + public static void main(String args[]) { + + try { + + CryptoManager.initialize("secmod.db", "key3.db", "cert7.db"); + CryptoManager cm = CryptoManager.getInstance(); + CryptoToken token = cm.getInternalCryptoToken(); + CryptoToken keyToken = cm.getInternalKeyStorageToken(); + KeyGenerator kg = token.getKeyGenerator(KeyGenAlgorithm.DES); + KeyGenerator keyKg = keyToken.getKeyGenerator(KeyGenAlgorithm.DES3); + + SymmetricKey wrapped = kg.generate(); + SymmetricKey wrapper = kg.generate(); + SymmetricKey keyWrapper = keyKg.generate(); + SymmetricKey keyWrapped = keyKg.clone(wrapped); + + // wrap a symmetric with a symmetric + byte[] plaintextPre = new byte[] { + (byte)0x73, (byte)0x24, (byte)0x51, (byte)0x48, + (byte)0x32, (byte)0x87, (byte)0x23, (byte)0x33, (byte)0x65}; + byte[] plaintext = Cipher.pad(plaintextPre, + EncryptionAlgorithm.DES_ECB.getBlockSize()); + + System.out.println("plaintext length is " + plaintext.length); + + Cipher encryptor = token.getCipherContext(EncryptionAlgorithm.DES_ECB); + encryptor.initEncrypt(wrapped); + byte[] ciphertext = encryptor.doFinal(plaintext); + + System.out.println("ciphertext length is " + ciphertext.length); + + KeyWrapper keyWrap = token.getKeyWrapper(KeyWrapAlgorithm.DES_ECB); + keyWrap.initWrap(wrapper,null); + byte[] wrappedKey = keyWrap.wrap(wrapped); + + keyWrap.initUnwrap(wrapper, null); + SymmetricKey unwrapped = keyWrap.unwrapSymmetric(wrappedKey, + SymmetricKey.DES, 0); + + Cipher decryptor = token.getCipherContext(EncryptionAlgorithm.DES_ECB); + decryptor.initDecrypt(unwrapped); + byte[] recoveredPre = decryptor.doFinal(ciphertext); + System.out.println("Decrypted "+ recoveredPre.length+ " bytes"); + byte[] recovered = Cipher.unPad(recoveredPre, + EncryptionAlgorithm.DES_ECB.getBlockSize()); + + System.out.println("plaintext:"); + displayByteArray(plaintextPre); + System.out.println("ciphertext:"); + displayByteArray(ciphertext); + System.out.println("recovered:"); + displayByteArray(recovered); + + + // wrap a private with a symmetric + keyWrap = keyToken.getKeyWrapper(KeyWrapAlgorithm.DES3_CBC_PAD); + IVParameterSpec iv = new IVParameterSpec(recovered); + keyWrap.initWrap(keyWrapper,iv); + KeyPairGenerator kpg = + keyToken.getKeyPairGenerator(KeyPairAlgorithm.RSA); + kpg.initialize(512); + kpg.temporaryPairs(true); + KeyPair kp = kpg.genKeyPair(); + java.security.PublicKey pub = kp.getPublic(); + PrivateKey privk = (com.netscape.jss.crypto.PrivateKey)kp.getPrivate(); + + wrappedKey = keyWrap.wrap(privk); + System.out.println("Original key:"); + displayByteArray(privk.getUniqueID()); + privk = null; kp = null; + //keyToken.getCryptoStore().deletePrivateKey(privk); + + keyWrap.initUnwrap(keyWrapper,iv); + PrivateKey newPrivk = keyWrap.unwrapTemporaryPrivate(wrappedKey, + PrivateKey.RSA, pub ); + + System.out.println("New key:"); + displayByteArray(newPrivk.getUniqueID()); + + // wrap a symmetric with a private + keyWrap = keyToken.getKeyWrapper(KeyWrapAlgorithm.RSA); + keyWrap.initWrap(pub,null); + wrappedKey = keyWrap.wrap(keyWrapped); + keyWrap.initUnwrap(newPrivk, null); + unwrapped = keyWrap.unwrapSymmetric(wrappedKey, SymmetricKey.DES, 0); + unwrapped = kg.clone(unwrapped); + decryptor = token.getCipherContext(EncryptionAlgorithm.DES_ECB); + decryptor.initDecrypt(unwrapped); + recovered = decryptor.doFinal(ciphertext); + System.out.println("Recovered again:"); + displayByteArray(Cipher.unPad(recovered, 8)); + + + } catch(Exception e) { + e.printStackTrace(); + } + } + + public static void + displayByteArray(byte[] ba) { + for(int i=0; i < ba.length; i++) { + System.out.print( Integer.toHexString(ba[i]&0xff) + " " ); + if( (i % 26) == 25 ) { + System.out.println(""); + } + } + System.out.println(""); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/tests/ListCerts.java b/mozilla/security/jss/org/mozilla/jss/tests/ListCerts.java new file mode 100644 index 00000000000..84fa4f5ccae --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/tests/ListCerts.java @@ -0,0 +1,70 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.crypto; + +import com.netscape.jss.CryptoManager; + +public class ListCerts { + + public static void main(String args[]) { + + try { + + if( args.length != 2 ) { + System.out.println("Usage: ListCerts "); + return; + } + String dbdir = args[0]; + String nickname = args[1]; + + CryptoManager.initialize(dbdir+"/secmod.db", dbdir+"/key3.db", + dbdir+"/cert7.db"); + + CryptoManager cm = CryptoManager.getInstance(); + + X509Certificate[] certs = cm.findCertsByNickname(nickname); + + System.out.println(certs.length + " certs found with this nickname."); + + for(int i=0; i < certs.length; i++) { + System.out.println("\nSubject: "+certs[i].getSubjectDN()); + System.out.println("Issuer: "+certs[i].getIssuerDN()); + } + + System.out.println("END"); + + } catch( Exception e ) { + e.printStackTrace(); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/tests/Makefile b/mozilla/security/jss/org/mozilla/jss/tests/Makefile new file mode 100644 index 00000000000..4b9a5013bab --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/tests/Makefile @@ -0,0 +1,76 @@ +#! gmake +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +####################################################################### +# (1) Include initial platform-independent assignments (MANDATORY). # +####################################################################### + +include manifest.mn + +####################################################################### +# (2) Include "global" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/config.mk + +####################################################################### +# (3) Include "component" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/$(MODULE)/config/config.mk + +####################################################################### +# (4) Include "local" platform-dependent assignments (OPTIONAL). # +####################################################################### + +include config.mk + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/$(MODULE)/config/rules.mk + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### + + + diff --git a/mozilla/security/jss/org/mozilla/jss/tests/PK10Gen.java b/mozilla/security/jss/org/mozilla/jss/tests/PK10Gen.java new file mode 100644 index 00000000000..9e2715c8078 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/tests/PK10Gen.java @@ -0,0 +1,106 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss; + +import com.netscape.jss.crypto.*; +import com.netscape.jss.CryptoManager; +import com.netscape.jss.pkcs11.*; +import com.netscape.jss.pkcs11.PK11Token; +import com.netscape.jss.util.*; + +public class PK10Gen { + public static void main(String args[]) { + CryptoManager manager; + Password pass1=null, pass2=null; + char[] passchar1 = {'f', 'o', 'o', 'b', 'a', 'r'}; + char[] passchar2 = {'n', 'e', 't', 's', 'c', 'a', 'p', 'e'}; + + if(args.length != 2) { + System.err.println("Usage: java com.netscape.jss.PK10Gen [rsa|dsa]"); + return; + } + + try { + CryptoManager.initialize(args[0]+"/secmod.db", args[0]+"/key3.db", args[0]+"/cert7.db"); + /* + CryptoManager.initialize("secmod.db", "key3.db", "cert7.db"); + CryptoManager cm = CryptoManager.getInstance(); + PK11Token token = (PK11Token)cm.getInternalCryptoToken(); + */ + /* + CryptoManager.InitializationValues vals = new + CryptoManager.InitializationValues( args[0]+"/secmodule.db", + args[0]+"/key3.db", + args[0]+"/cert7.db"); + CryptoManager.initialize(vals); + */ + try { + manager = CryptoManager.getInstance(); + } catch( CryptoManager.NotInitializedException e ) { + System.out.println("CryptoManager not initialized"); + return; + } + + CryptoToken token = (PK11Token) manager.getInternalKeyStorageToken(); + if(token.isLoggedIn() == false) { + System.out.println("Good, isLoggedIn correctly says we're"+ + " not logged in"); + } else { + System.out.println("ERROR: isLoggedIn incorrectly says we're"+ + " logged in"); + } + + pass1 = new Password( (char[]) passchar1.clone()); + pass2 = new Password( new char[]{0} ); + token.initPassword(pass2, pass1); + pass1.clear(); + pass2.clear(); + System.out.println("initialized PIN"); + token.login(pass1); + System.out.println("logged in"); + + String blob = token.generateCertRequest("cn=christina Fu", + 512, + args[1], + (byte[]) null, + (byte[]) null, + (byte[]) null); + System.out.println("pkcs#10 blob = \n" + blob); + } catch(Exception e) { + System.out.println("exception caught in PK10Gen: " + + e.getMessage()); + e.printStackTrace(); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/tests/SelfTest.java b/mozilla/security/jss/org/mozilla/jss/tests/SelfTest.java new file mode 100644 index 00000000000..7c86a76d0af --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/tests/SelfTest.java @@ -0,0 +1,252 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.pkcs11; + +import com.netscape.jss.util.*; +import com.netscape.jss.crypto.*; +import com.netscape.jss.*; +import java.io.*; +import java.awt.*; +import java.security.cert.*; + +public class SelfTest { + + public static void main(String[] args) throws Throwable { + CryptoToken tok; + CryptoToken intTok; + CryptoManager manager; + Password pass1=null, pass2=null; + KeyPairGenerator keyPairGenerator; + java.security.KeyPair keyPair; + java.util.Enumeration items; + char[] passchar1 = {'f', 'o', 'o', 'b', 'a', 'r'}; + char[] passchar2 = {'n', 'e', 't', 's', 'c', 'a', 'p', 'e'}; + + Debug.setLevel(Debug.OBNOXIOUS); + + if(args.length != 1) { + System.err.println("Usage: java ...SelfTest "); + return; + } + + CryptoManager.InitializationValues vals = new + CryptoManager.InitializationValues( args[0]+"/secmodule.db", + args[0]+"/key3.db", + args[0]+"/cert7.db"); + CryptoManager.initialize(vals); + try { + manager = CryptoManager.getInstance(); + } catch( CryptoManager.NotInitializedException e ) { + System.out.println("CryptoManager not initialized"); + return; + } + + try { + tok = manager.getTokenByName("asdffda"); + System.out.println("ERROR: found a nonexistent token"); + } catch (NoSuchTokenException e) { + System.out.println("Good, could not find non-existent token"); + } + + try { + + items = manager.getModules(); + System.out.println("Modules:"); + while(items.hasMoreElements()) { + System.out.println("\t"+ + ((PK11Module)items.nextElement()).getName() ); + } + + items = manager.getAllTokens(); + System.out.println("All Tokens:"); + while(items.hasMoreElements()) { + System.out.println("\t"+ + ((CryptoToken)items.nextElement()).getName() ); + } + + items = manager.getExternalTokens(); + System.out.println("External Tokens:"); + while(items.hasMoreElements()) { + System.out.println("\t"+ + ((CryptoToken)items.nextElement()).getName() ); + } + + + tok = manager.getTokenByName("Internal Key Storage Token"); + System.out.println("Good, found internal DB token"); + + if( tok.equals(manager.getInternalKeyStorageToken()) ) { + System.out.println("Good, it really is the key storage token"); + } else { + System.out.println("ERROR: it's not the same as the key "+ + "storage token!"); + } + if( ((PK11Token)tok).isInternalKeyStorageToken() ) { + System.out.println("Good, "+tok.getName()+" knows "+ + "what it is"); + } else { + System.out.println("ERROR: "+tok.getName()+" doesn't know"+ + " it is key storage token"); + } + + intTok = manager.getInternalCryptoToken(); + if( ((PK11Token)intTok).isInternalCryptoToken() ) { + System.out.println("Good, "+tok.getName()+ + " knows it is the internal token"); + } else { + System.out.println("ERROR: "+tok.getName()+ + " doesn't know what that it is the internal token"); + } + + + if(tok.isLoggedIn() == false) { + System.out.println("Good, isLoggedIn correctly says we're"+ + " not logged in"); + } else { + System.out.println("ERROR: isLoggedIn incorrectly says we're"+ + " logged in"); + } + + System.out.println("Good, successfully opened token \""+ + tok.getName()+"\""); + + pass1 = new Password( (char[]) passchar1.clone()); + pass2 = new Password( new char[]{0} ); + tok.initPassword(pass2, pass1); + pass1.clear(); + pass2.clear(); + System.out.println("Good, initialized PIN"); + tok.logout(); + + try { + pass1 = new Password( (char[]) passchar2.clone()); + tok.login(pass1); + System.out.println("ERROR: Successfully logged in with wrong"+ + " PIN"); + } catch (IncorrectPasswordException e) { + System.out.println("Good, unable to login with wrong PIN"); + } finally { + pass1.clear(); + } + + pass1 = new Password( (char[]) passchar1.clone()); + tok.login(pass1); + pass1.clear(); + System.out.println("Good, logged in"); + + if(tok.isLoggedIn() == true) { + System.out.println("Good, isLoggedIn correctly says we're"+ + " logged in"); + } else { + System.out.println("ERROR: isLoggedIn incorrectly says we're"+ + " not logged in"); + } + + pass1 = new Password( (char[]) passchar1.clone()); + pass2 = new Password( (char[]) passchar2.clone()); + tok.changePassword(pass1, pass2); + pass1.clear(); pass2.clear(); + System.out.println("Good, changed PIN"); + + try { + pass1 = new Password( (char[]) passchar1.clone()); + tok.login(pass1); + // Should still be logged in + System.out.println("Good, logging in with wrong PIN ok if "+ + " already logged in"); + } catch (IncorrectPasswordException e) { + System.out.println("ERROR: logged in second time with wrong"+ + "PIN, but we should still be logged in"); + } finally { + pass1.clear(); + } + + try { + tok.logout(); + System.out.println("Good, logged out successfully."); + } catch (TokenException e) { + System.out.println("ERROR: failed to logout from token"); + } + + if(tok.isLoggedIn() == false) { + System.out.println("Good, isLoggedIn correctly says we're"+ + " not logged in"); + } else { + System.out.println("ERROR: isLoggedIn incorrectly says we're"+ + " logged in"); + } + + try { + tok.logout(); + System.out.println("ERROR: logged out twice in a row"); + } catch (TokenException e) { + System.out.println("Good, got an exception when we tried"+ + " to log out twice in a row"); + } + try { + pass1 = new Password( (char[]) passchar1.clone()); + tok.login(pass1); + pass1.clear(); + System.out.println("ERROR: logged in with wrong pw"); + } catch (IncorrectPasswordException e) { + System.out.println("Good, logging in with wrong PIN gave err"); + } + + System.out.println("Test completed"); + + tok = null; + + } catch (IncorrectPasswordException e) { + System.out.println("Got an incorrect PIN: "+e); + } catch (AlreadyInitializedException e) { + System.out.println( + "ERROR: This test only works with uninitialized databases"); + } catch (TokenException e) { + System.out.println("Token error: " + e); + } catch (NoSuchTokenException e) { + System.out.println("ERROR: could not find internal DB token"); + } finally { + if(pass1 != null) { + pass1.clear(); + } + if(pass2 != null) { + pass2.clear(); + } + } + + //System.gc(); + //NativeProxy.assertRegistryEmpty(); + //System.runFinalization(); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/tests/SymKeyGen.java b/mozilla/security/jss/org/mozilla/jss/tests/SymKeyGen.java new file mode 100644 index 00000000000..4c09f5b1991 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/tests/SymKeyGen.java @@ -0,0 +1,161 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss; + +import com.netscape.jss.crypto.*; +import com.netscape.jss.CryptoManager; +import com.netscape.jss.util.Assert; +import com.netscape.jss.util.Password; +import java.security.InvalidAlgorithmParameterException; + +public class SymKeyGen { + + public static void main(String args[]) { + + try { + + CryptoManager.initialize("secmod.db", "key3.db", "cert7.db"); + CryptoManager cm = CryptoManager.getInstance(); + CryptoToken token = cm.getInternalCryptoToken(); + byte[] keyData; + + // DES key + KeyGenerator kg = token.getKeyGenerator(KeyGenAlgorithm.DES); + SymmetricKey key = kg.generate(); + if( key.getType() != SymmetricKey.DES ) { + throw new Exception("wrong algorithm"); + } + if( ! key.getOwningToken().equals( token ) ) { + throw new Exception("wrong token"); + } + if( key.getStrength() != 56 ) { + throw new Exception("wrong strength"); + } + keyData = key.getKeyData(); + if( keyData.length != 8 ) { + throw new Exception("key data wrong length"); + } + System.out.println("DES key is correct"); + + IVParameterSpec iv = new IVParameterSpec( + new byte[]{ (byte)0xff, (byte)0x00, (byte)0xff, (byte)0x00, + (byte)0xff, (byte)0x00, (byte)0xff, (byte)0x00 } ); + Cipher cipher = token.getCipherContext(EncryptionAlgorithm.DES_CBC_PAD); + cipher.initEncrypt(key, iv); + byte[] plaintext = new byte[] { (byte)0xff, (byte)0x00 }; + byte[] ciphertext = cipher.doFinal(plaintext); + cipher.initDecrypt(key, iv); + byte[] recovered = cipher.doFinal(ciphertext); + if( recovered.length != plaintext.length ) { + throw new Exception("Recovered plaintext has different length ("+ + recovered.length+") than original ("+plaintext.length+")"); + } + for(int i=0; i < recovered.length; i++) { + if( plaintext[i] != recovered[i] ) { + throw new Exception("Recovered plaintext differs from original" + + " at position "+i); + } + } + System.out.println("DES encryption succeeded"); + + + // DES3 key + kg = token.getKeyGenerator(KeyGenAlgorithm.DES3); + key = kg.generate(); + if( key.getType() != SymmetricKey.DES3 ) { + throw new Exception("wrong algorithm"); + } + if( ! key.getOwningToken().equals( token ) ) { + throw new Exception("wrong token"); + } + if( key.getStrength() != 168 ) { + throw new Exception("wrong strength"); + } + keyData = key.getKeyData(); + if( keyData.length != 24 ) { + throw new Exception("key data wrong length"); + } + System.out.println("DES3 key is correct"); + + // RC4 key + kg = token.getKeyGenerator(KeyGenAlgorithm.RC4); + kg.initialize(128); + key = kg.generate(); + if( key.getType() != SymmetricKey.RC4 ) { + throw new Exception("wrong algorithm"); + } + if( ! key.getOwningToken().equals( token ) ) { + throw new Exception("wrong token"); + } + if( key.getStrength() != 128 ) { + throw new Exception("wrong strength"); + } + keyData = key.getKeyData(); + if( keyData.length != 16 ) { + throw new Exception("key data wrong length"); + } + System.out.println("RC4 key is correct"); + + // PBE MD5 DES CBC + kg = token.getKeyGenerator(PBEAlgorithm.PBE_MD5_DES_CBC); + try { + kg.initialize(56); + throw new Exception("ERROR: Initializing PBE key with strength "+ + "succeeded"); + } catch( InvalidAlgorithmParameterException e) { } + Password pass = new Password( ("passwd").toCharArray() ); + byte[] salt = new byte[] { (byte)0xff, (byte)0x00, (byte)0xff }; + PBEKeyGenParams kgp = new PBEKeyGenParams(pass, salt, 2); + kg.initialize(kgp); + key = kg.generate(); + if( key.getType() != SymmetricKey.DES ) { + throw new Exception("Wrong key type: "+key.getType()); + } + if( ! key.getOwningToken().equals( token ) ) { + throw new Exception("wrong token"); + } + if( key.getStrength() != 56 && key.getStrength() != 64) { + throw new Exception("wrong strength: "+key.getStrength()); + } + keyData = key.getKeyData(); + if( keyData.length != 8 ) { + throw new Exception("key data wrong length"); + } + System.out.println("PBE key is correct"); + + } catch(Exception e) { + e.printStackTrace(); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/tests/TestExportControlPolicy.java b/mozilla/security/jss/org/mozilla/jss/tests/TestExportControlPolicy.java new file mode 100644 index 00000000000..6f697aef352 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/tests/TestExportControlPolicy.java @@ -0,0 +1,209 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss; + +import com.netscape.jss.*; +import com.netscape.jss.crypto.*; + +/** + * A command-line utility for testing Export Control Policies in "jssjava". + */ +public class TestExportControlPolicy { + + public static void main(String args[]) { + CryptoManager cm; + int policy; + + try { + CryptoManager.InitializationValues vals = new + CryptoManager.InitializationValues( "./secmodule.db", + "./key3.db", + "./cert7.db"); + CryptoManager.initialize( vals ); + + cm = CryptoManager.getInstance(); + + + // (1) Test getExportControlPolicyType() method. + // + // NOTE: + // domestic: "the DOMESTIC" + // export: "the EXPORT" + // france: "the FRANCE" + // + System.out.print( "\ngetExportControlPolicyType() utilizes " ); + + policy = cm.getExportControlPolicyType(); + + if( policy == CryptoManager.NULL_POLICY ) { + System.out.print( "the NULL " ); + } else if( policy == CryptoManager.DOMESTIC_POLICY ) { + System.out.print( "the DOMESTIC " ); + } else if( policy == CryptoManager.EXPORT_POLICY ) { + System.out.print( "the EXPORT " ); + } else if( policy == CryptoManager.FRANCE_POLICY ) { + System.out.print( "the FRANCE " ); + } else { + System.out.print( "NO " ); + } + + System.out.println( "export control policy." ); + + + // (2) Test isDomestic() method. + // + // NOTE: + // domestic: "is" + // export: "is NOT" + // france: "is NOT" + // + System.out.print( "isDomestic() says that jssjava " ); + + if( cm.isDomestic() == true ) { + System.out.print( "is " ); + } else { + System.out.print( "is NOT " ); + } + + System.out.println( "domestic." ); + + + /////////////////////////////// + // // + // NOTE: For the remainder // + // of this test, please use // + // the following algorithms: // + // // + // EncryptionAlgorithm // + // KeyGenAlgorithm // + // KeyPairAlgorithm // + // KeyWrapAlgorithm // + // PBEAlgorithm // + // SignatureAlgorithm // + // // + /////////////////////////////// + + + // (3) Test the isAllowed() method using DES_CBC for + // CRS BULK ENCRYPTION + // + // NOTE: + // domestic: "allowed" + // export: "allowed" + // france: "NOT allowed" + // + if( ! KeyWrapAlgorithm.DES_CBC.isAllowed( + Algorithm.Usage.JAVA_CRS_BULK_ENCRYPTION ) ) { + System.out.println( "DES_CBC is NOT allowed for " + + "CRS BULK ENCRYPTION!" ); + } else { + System.out.println( "DES_CBC is allowed for " + + "CRS BULK ENCRYPTION!" ); + } + + + // (4) Test the isAllowed() method using RC4 for KRA STORAGE + // + // NOTE: + // domestic: "NOT allowed" + // export: "NOT allowed" + // france: "NOT allowed" + // + if( ! KeyGenAlgorithm.RC4.isAllowed( + Algorithm.Usage.JAVA_KRA_STORAGE ) ) { + System.out.println( "RC4 is NOT allowed for KRA STORAGE!" ); + } else { + System.out.println( "RC4 is allowed for KRA STORAGE!" ); + } + + // (5) Test the isAllowed() method using PBE_SHA1_DES3_CBC for + // KRA PKCS 12 + // + // NOTE: + // domestic: "allowed" + // export: "allowed" + // france: "allowed" + // + if( ! PBEAlgorithm.PBE_SHA1_DES3_CBC.isAllowed( + Algorithm.Usage.JAVA_KRA_PKCS_12 ) ) { + System.out.println( "PBE_SHA1_DES3_CBC is NOT allowed for " + + "KRA PKCS 12!" ); + } else { + System.out.println( "PBE_SHA1_DES3_CBC is allowed for " + + "KRA PKCS 12!" ); + } + + // (6) Test the getStrongestKeySize() method + // SEC_OID_PKCS1_RSA_ENCRYPTION for SSL KEY EXCHANGE + // + // NOTE: + // domestic: 512 + // export: 512 + // france: 4096 + // + System.out.println( "Strongest key size of " + + "SEC_OID_PKCS1_RSA_ENCRYPTION is " + + KeyWrapAlgorithm.RSA.getStrongestKeySize( + Algorithm.Usage.JAVA_SSL_KEY_EXCHANGE ) + + "-bits for KeyWrapping." ); + + // (7) Test the getStrongestKeySize() method + // for DES_CBC for CRS BULK ENCRYPTION + // + // NOTE: + // domestic: 56 + // export: 56 + // france: 0 + // + System.out.println( "Strongest key size of " + + "DES_CBC is " + + KeyWrapAlgorithm.DES_CBC.getStrongestKeySize( + Algorithm.Usage.JAVA_CRS_BULK_ENCRYPTION ) + + "-bits for KeyWrapping." ); + + + // (8) Test getAllAlgorithms() method + // (currently unused; ergo untested) + + System.out.println( "\n" ); + } catch(NumberFormatException e) { + System.err.println("Invalid key size: "+e); + } catch(java.security.InvalidParameterException e) { + System.err.println("Invalid key size: "+e); + } catch(Exception e) { + System.err.println(e); + } + } +} + diff --git a/mozilla/security/jss/org/mozilla/jss/tests/config.mk b/mozilla/security/jss/org/mozilla/jss/tests/config.mk new file mode 100644 index 00000000000..b7d50a24d7a --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/tests/config.mk @@ -0,0 +1,52 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +####################################################################### +# Adjust specific variables for all platforms # +####################################################################### + +LD_LIBS += \ + $(LIBSECMOD) \ + $(LIBCERT) \ + $(LIBKEY) \ + $(LIBCRYPTO) \ + $(LIBHASH) \ + $(LIBPLDS) \ + $(LIBSECUTIL) \ + $(LIBPR) \ + $(LIBDBM) \ + $(LIBPLC) \ + $(LIBSYSTEM) \ + $(LIBJSSUTIL) \ + $(LIBJSSPKCS11) \ + $(NULL) diff --git a/mozilla/security/jss/org/mozilla/jss/tests/manifest.mn b/mozilla/security/jss/org/mozilla/jss/tests/manifest.mn new file mode 100644 index 00000000000..2f1a8291ee5 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/tests/manifest.mn @@ -0,0 +1,66 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +CORE_DEPTH = ../../../../.. + +MODULE = ninja + +NS_USE_JDK = 1 + +REQUIRES = nspr20 dbm security + +PRIVATE_CLASSES = \ + DigestTest \ + SelfTest \ + SymKeyGen \ + PK10Gen \ + JCASigTest \ + CloseDBs \ + KeyWrapping \ + TestExportControlPolicy \ + ListCerts \ + socketTest \ + $(NULL) + +JSRCS = \ + DigestTest.java \ + SelfTest.java \ + SymKeyGen.java \ + PK10Gen.java \ + JCASigTest.java \ + CloseDBs.java \ + KeyWrapping.java \ + TestExportControlPolicy.java \ + ListCerts.java \ + socketTest.java \ + $(NULL) diff --git a/mozilla/security/jss/org/mozilla/jss/tests/socketTest.java b/mozilla/security/jss/org/mozilla/jss/tests/socketTest.java new file mode 100644 index 00000000000..12d167c8b81 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/tests/socketTest.java @@ -0,0 +1,52 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +import java.io.*; +import com.netscape.jss.ssl.*; +import com.netscape.jss.*; + +public class socketTest { + + public static void main(String []args) { + try { + + // initialize CryptoManager. + CryptoManager.initialize("secmod.db", "key3.db", "cert7.db"); + + SSLSocket sslSocket = new SSLSocket("www.verisign.com", 443); + + System.out.println("Test"); + } catch( Exception e ) { + e.printStackTrace(); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/tests/unix.sh b/mozilla/security/jss/org/mozilla/jss/tests/unix.sh new file mode 100644 index 00000000000..84b8e34a812 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/tests/unix.sh @@ -0,0 +1,145 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +#!/usr/bin/tcsh + + +if ( `uname` == "AIX" ) then + + + + setenv LIBPATH ../../../../../dist/AIX4.2_DBG.OBJ/lib:/share/builds/components/jdk/1.1.6/AIX/lib/aix/native_threads + echo Testing \"jssjava\" on `uname` `uname -v`.`uname -r` DBG platform . . . + ../../../../../dist/AIX4.2_DBG.OBJ/bin/jssjava -classpath ../../../../../dist/classes_DBG:/share/builds/components/jdk/1.1.6/AIX/lib/classes.zip com.netscape.jss.crypto.PQGGen 512 + echo Testing \"jssjava_g\" on `uname` `uname -v`.`uname -r` DBG platform . . . + ../../../../../dist/AIX4.2_DBG.OBJ/bin/jssjava_g -classpath ../../../../../dist/classes_DBG:/share/builds/components/jdk/1.1.6/AIX/lib/classes.zip com.netscape.jss.crypto.PQGGen 512 + + + setenv LIBPATH ../../../../../dist/AIX4.2_OPT.OBJ/lib:/share/builds/components/jdk/1.1.6/AIX/lib/aix/native_threads + echo Testing \"jssjava\" on `uname` `uname -v`.`uname -r` OPT platform . . . + ../../../../../dist/AIX4.2_OPT.OBJ/bin/jssjava -classpath ../../../../../dist/classes:/share/builds/components/jdk/1.1.6/AIX/lib/classes.zip com.netscape.jss.crypto.PQGGen 512 + + + + + +else if ( `uname` == "HP-UX" ) then + + + setenv SHLIB_PATH ../../../../../dist/HP-UXB.11.00_DBG.OBJ/lib:/share/builds/components/jdk/1.1.5/HP-UX/lib/PA_RISC/native_threads + echo Testing \"jssjava\" on `uname` `uname -r` DBG platform . . . + ../../../../../dist/HP-UXB.11.00_DBG.OBJ/bin/jssjava -classpath ../../../../../dist/classes_DBG:/share/builds/components/jdk/1.1.5/HP-UX/lib/classes.zip com.netscape.jss.crypto.PQGGen 512 + echo Testing \"jssjava_g\" on `uname` `uname -r` DBG platform . . . + ../../../../../dist/HP-UXB.11.00_DBG.OBJ/bin/jssjava_g -classpath ../../../../../dist/classes_DBG:/share/builds/components/jdk/1.1.5/HP-UX/lib/classes.zip com.netscape.jss.crypto.PQGGen 512 + + + setenv SHLIB_PATH ../../../../../dist/HP-UXB.11.00_OPT.OBJ/lib:/share/builds/components/jdk/1.1.5/HP-UX/lib/PA_RISC/native_threads + echo Testing \"jssjava\" on `uname` `uname -r` OPT platform . . . + ../../../../../dist/HP-UXB.11.00_OPT.OBJ/bin/jssjava -classpath ../../../../../dist/classes:/share/builds/components/jdk/1.1.5/HP-UX/lib/classes.zip com.netscape.jss.crypto.PQGGen 512 + + + + + +else if ( ( `uname` == "IRIX" ) || ( `uname` == "IRIX64" ) ) then + + + setenv LD_LIBRARY_PATH ../../../../../dist/IRIX6.2_PTH_DBG.OBJ/lib:/share/builds/components/jdk/1.1.5/IRIX/lib32/sgi/native_threads + echo Testing \"jssjava\" on `uname` `uname -r` DBG platform . . . + ../../../../../dist/IRIX6.2_PTH_DBG.OBJ/bin/jssjava -classpath ../../../../../dist/classes_DBG:/share/builds/components/jdk/1.1.5/IRIX/lib/rt.jar com.netscape.jss.crypto.PQGGen 512 + echo Testing \"jssjava_g\" on `uname` `uname -r` DBG platform . . . + ../../../../../dist/IRIX6.2_PTH_DBG.OBJ/bin/jssjava_g -classpath ../../../../../dist/classes_DBG:/share/builds/components/jdk/1.1.5/IRIX/lib/rt.jar com.netscape.jss.crypto.PQGGen 512 + + + setenv LD_LIBRARY_PATH ../../../../../dist/IRIX6.2_PTH_OPT.OBJ/lib:/share/builds/components/jdk/1.1.5/IRIX/lib32/sgi/native_threads + echo Testing \"jssjava\" on `uname` `uname -r` OPT platform . . . + ../../../../../dist/IRIX6.2_PTH_OPT.OBJ/bin/jssjava -classpath ../../../../../dist/classes:/share/builds/components/jdk/1.1.5/IRIX/lib/rt.jar com.netscape.jss.crypto.PQGGen 512 + + + + + +else if ( `uname` == "OSF1" ) then + + + setenv LD_LIBRARY_PATH ../../../../../dist/OSF1V4.0D_DBG.OBJ/lib:/share/builds/components/jdk/1.1.6/OSF1/lib/alpha + echo Testing \"jssjava\" on `uname` `uname -r`D DBG platform . . . + ../../../../../dist/OSF1V4.0D_DBG.OBJ/bin/jssjava -classpath ../../../../../dist/classes_DBG:/share/builds/components/jdk/1.1.5/OSF1/lib/classes.zip com.netscape.jss.crypto.PQGGen 512 + echo Testing \"jssjava_g\" on `uname` `uname -r`D DBG platform . . . + ../../../../../dist/OSF1V4.0D_DBG.OBJ/bin/jssjava_g -classpath ../../../../../dist/classes_DBG:/share/builds/components/jdk/1.1.5/OSF1/lib/classes.zip com.netscape.jss.crypto.PQGGen 512 + + + setenv LD_LIBRARY_PATH ../../../../../dist/OSF1V4.0D_OPT.OBJ/lib:/share/builds/components/jdk/1.1.6/OSF1/lib/alpha + echo Testing \"jssjava\" on `uname` `uname -r`D OPT platform . . . + ../../../../../dist/OSF1V4.0D_OPT.OBJ/bin/jssjava -classpath ../../../../../dist/classes:/share/builds/components/jdk/1.1.5/OSF1/lib/classes.zip com.netscape.jss.crypto.PQGGen 512 + + + + + +else if ( ( `uname` == "SunOS" ) && ( `uname -r` == "5.5.1" ) ) then + + setenv LD_LIBRARY_PATH ../../../../../dist/SunOS5.5.1_DBG.OBJ/lib:/share/builds/components/jdk/1.1.6/SunOS/lib/sparc/native_threads + echo Testing \"jssjava\" on `uname` `uname -r` DBG platform . . . + ../../../../../dist/SunOS5.5.1_DBG.OBJ/bin/jssjava -classpath ../../../../../dist/classes_DBG:/share/builds/components/jdk/1.1.6/SunOS/lib/classes.zip com.netscape.jss.crypto.PQGGen 512 + echo Testing \"jssjava_g\" on `uname` `uname -r` DBG platform . . . + ../../../../../dist/SunOS5.5.1_DBG.OBJ/bin/jssjava_g -classpath ../../../../../dist/classes_DBG:/share/builds/components/jdk/1.1.6/SunOS/lib/classes.zip com.netscape.jss.crypto.PQGGen 512 + + + setenv LD_LIBRARY_PATH ../../../../../dist/SunOS5.5.1_OPT.OBJ/lib:/share/builds/components/jdk/1.1.6/SunOS/lib/sparc/native_threads + echo Testing \"jssjava\" on `uname` `uname -r` OPT platform . . . + ../../../../../dist/SunOS5.5.1_OPT.OBJ/bin/jssjava -classpath ../../../../../dist/classes:/share/builds/components/jdk/1.1.6/SunOS/lib/classes.zip com.netscape.jss.crypto.PQGGen 512 + + + + + +else if ( ( `uname` == "SunOS" ) && ( `uname -r` == "5.6" ) ) then + + setenv LD_LIBRARY_PATH ../../../../../dist/SunOS5.6_DBG.OBJ/lib:/share/builds/components/jdk/1.1.6/SunOS/lib/sparc/native_threads + echo Testing \"jssjava\" on `uname` `uname -r` DBG platform . . . + ../../../../../dist/SunOS5.6_DBG.OBJ/bin/jssjava -classpath ../../../../../dist/classes_DBG:/share/builds/components/jdk/1.1.6/SunOS/lib/classes.zip com.netscape.jss.crypto.PQGGen 512 + echo Testing \"jssjava_g\" on `uname` `uname -r` DBG platform . . . + ../../../../../dist/SunOS5.6_DBG.OBJ/bin/jssjava_g -classpath ../../../../../dist/classes_DBG:/share/builds/components/jdk/1.1.6/SunOS/lib/classes.zip com.netscape.jss.crypto.PQGGen 512 + + + setenv LD_LIBRARY_PATH ../../../../../dist/SunOS5.6_OPT.OBJ/lib:/share/builds/components/jdk/1.1.6/SunOS/lib/sparc/native_threads + echo Testing \"jssjava\" on `uname` `uname -r` OPT platform . . . + ../../../../../dist/SunOS5.6_OPT.OBJ/bin/jssjava -classpath ../../../../../dist/classes:/share/builds/components/jdk/1.1.6/SunOS/lib/classes.zip com.netscape.jss.crypto.PQGGen 512 + + + + + +endif + diff --git a/mozilla/security/jss/org/mozilla/jss/util/Assert.java b/mozilla/security/jss/org/mozilla/jss/util/Assert.java new file mode 100644 index 00000000000..36dabe11828 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/util/Assert.java @@ -0,0 +1,94 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.util; + +import com.netscape.jss.util.*; + +/** + * C-style assertions in Java. + * These methods are only active in debug mode + * (com.netscape.jss.Debug.DEBUG==true). + * + * @see com.netscape.jss.util.Debug + * @see com.netscape.jss.util.AssertionException + * @version $Revision: 1.1 $ $Date: 2000-12-15 20:52:36 $ + */ +public class Assert { + /** + * Assert that a condition is true. If it is not true, abort by + * throwing an AssertionException. + * + * @param cond The condition that is being tested. + */ + public static void assert(boolean cond) { + if(Debug.DEBUG && !cond) { + throw new com.netscape.jss.util.AssertionException( + "assertion failure!"); + } + } + + /** + * Assert that a condition is true. If it is not true, abort by throwing + * an AssertionException. + * + * @param cond The condition that is being tested. + * @param msg A message describing what is wrong if the condition is false. + */ + public static void assert(boolean cond, String msg) { + if(Debug.DEBUG && !cond) { + throw new com.netscape.jss.util.AssertionException(msg); + } + } + + /** + * Throw an AssertionException if this statement is reached. + * + * @param msg A message describing what was reached. + */ + public static void notReached(String msg) { + if(Debug.DEBUG) { + throw new AssertionException("should not be reached: " + msg); + } + } + + /** + * Throw an AssertionException because functionlity is not yet implemented. + * + * @param msg A message describing what is not implemented. + */ + public static void notYetImplemented(String msg) { + if(Debug.DEBUG) { + throw new AssertionException("not yet implemented: " + msg); + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/util/AssertionException.java b/mozilla/security/jss/org/mozilla/jss/util/AssertionException.java new file mode 100644 index 00000000000..f6a8780b235 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/util/AssertionException.java @@ -0,0 +1,51 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package com.netscape.jss.util; + +/** + * Assertion exceptions are thrown when assertion code is invoked + * and fails to operate properly. They subclass Error, so they will + * not be caught by exception handlers. Instead, they will cause the + * VM to halt and print a stack trace. + * + * @see com.netscape.jss.util.Assert + * @see com.netscape.jss.util.Debug + * @version $Revision: 1.1 $ $Date: 2000-12-15 20:52:37 $ + */ +public class AssertionException extends RuntimeException { + public AssertionException() {} + + public AssertionException(String msg) { + super(msg); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/util/Base64OutputStream.java b/mozilla/security/jss/org/mozilla/jss/util/Base64OutputStream.java new file mode 100644 index 00000000000..164ce58cd81 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/util/Base64OutputStream.java @@ -0,0 +1,191 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +/* + * We would like to eventually use Sun's base64 encoder, but it is not + * public yet. It is in the sun.misc package in JDK1.2. + */ +package com.netscape.jss.util; + +import java.io.FilterOutputStream; +import java.io.PrintStream; +import java.io.IOException; + +/** + * An output stream filter that takes arbitrary bytes and outputs their + * base64 encoding. Call flush() or close() to write out the final padding. + * The class also automatically puts line breaks in the output stream. + */ +public class Base64OutputStream extends FilterOutputStream { + + /** + * Create a stream that does not insert line breaks. To have line + * breaks, use the other constructor. + */ + public Base64OutputStream(PrintStream out) { + super(out); + charsOnLine = 0; + inputCount = 0; + input = new byte[3]; + doLineBreaks = false; + } + + /** + * @param quadsPerLine Number of 4-character blocks to write before + * outputting a line break. For example, for 76-characters per line, + * pass in 76/4 = 19. + */ + public Base64OutputStream(PrintStream out, int quadsPerLine) { + this(out); + doLineBreaks = true; + Assert.assert(quadsPerLine>0, "quadsPerLine must be > 0"); + charsPerLine = quadsPerLine*4; + } + + + public void write(int oneByte) throws IOException { + input[inputCount++] = (byte)(0xff & oneByte); + if(inputCount==3) { + outputOneAtom(); + if(doLineBreaks) { + if(charsOnLine==charsPerLine) { + ((PrintStream)out).println(); + charsOnLine=0; + } + Assert.assert(charsOnLine < charsPerLine); + } + } + Assert.assert(inputCount < 3); + } + + /** + * This flushes the stream and closes the next stream downstream. + */ + public void close() throws IOException { + flush(); + out.close(); + } + + /** + * Calling this will put the ending padding on the base64 stream, + * so don't call it until you have no data left. The class does no + * unnecessary buffering, so you probably shouldn't call it at all. + */ + public void flush() throws IOException { + if(inputCount > 0) { + outputOneAtom(); + } + if(doLineBreaks) { + ((PrintStream)out).println(); + charsOnLine = 0; + } + } + + public void write(byte[] buffer) throws IOException { + write(buffer, 0, buffer.length); + } + + public void write(byte[] buffer, int offset, int count) throws IOException { + int i; + int byteCount; + + for(i=offset, byteCount=0; byteCount < count; i++, byteCount++) { + write(buffer[i]); + } + } + + private final static char encoding[] = { + // 0 1 2 3 4 5 6 7 + 'A','B','C','D','E','F','G','H', // 0 + 'I','J','K','L','M','N','O','P', // 1 + 'Q','R','S','T','U','V','W','X', // 2 + 'Y','Z','a','b','c','d','e','f', // 3 + 'g','h','i','j','k','l','m','n', // 4 + 'o','p','q','r','s','t','u','v', // 5 + 'w','x','y','z','0','1','2','3', // 6 + '4','5','6','7','8','9','+','/' // 7 + }; + + /** + * Output 3 bytes of input as 4 bytes of base-64 encoded output. + * If there are fewer than 3 bytes available, the output will be + * padded according to the spec. Padding should only happen at the end + * of the stream. + */ + private void outputOneAtom() throws IOException { + byte[] output = new byte[4]; + + if(inputCount==0) { + return; + } + + // If we have fewer than 3 bytes, pad the rest with zeroes + if(inputCount<3) { + input[2]=0; + if(inputCount<2) { + input[1]=0; + } + } + + // Do a base64 encoding + output[0] = (byte) encoding[ (input[0]>>>2) & 0x3f ]; + output[1] = (byte) encoding[ (input[0]<<4)&0x30 | (input[1]>>>4)&0xf ]; + output[2] = (byte) encoding[ (input[1]<<2)&0x3c | (input[2]>>>6)&0x3 ]; + output[3] = (byte) encoding[ input[2]&0x3f ]; + + // add padding + if(inputCount<3) { + output[3] = (byte)'='; + if(inputCount<2) { + output[2] = (byte)'='; + } + } + + out.write(output); + inputCount=0; + if(doLineBreaks) { + charsOnLine += 4; + } + } + + ////////////////////////////////////////////////////////////////////// + // Private data + ////////////////////////////////////////////////////////////////////// + private byte[] input; // buffered input, max 3 bytes (after 3 we write + // them out base64-encoded) + private short inputCount; // number of bytes in input buffer + private short charsOnLine; // number of bytes on the current line + private int charsPerLine; // maximum characters per line + private static final int DEFAULT_QUADS_PER_LINE=16; //64 chars + private boolean doLineBreaks; +} diff --git a/mozilla/security/jss/org/mozilla/jss/util/ConsolePasswordCallback.java b/mozilla/security/jss/org/mozilla/jss/util/ConsolePasswordCallback.java new file mode 100644 index 00000000000..1ba96627ae0 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/util/ConsolePasswordCallback.java @@ -0,0 +1,55 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.util; + +/** + * A password callback that obtains its password from the console. + * Asterisks are echoed at the prompt. + */ +public class ConsolePasswordCallback implements PasswordCallback { + public ConsolePasswordCallback() {} + public Password getPasswordFirstAttempt(PasswordCallbackInfo info) + throws PasswordCallback.GiveUpException + { + System.out.println("Enter password for "+info.getName()); + return Password.readPasswordFromConsole(); + } + + public Password getPasswordAgain(PasswordCallbackInfo token) + throws PasswordCallback.GiveUpException + { + System.out.println("Password incorrect, try again"); + return getPasswordFirstAttempt(token); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/util/Debug_debug.java b/mozilla/security/jss/org/mozilla/jss/util/Debug_debug.java new file mode 100644 index 00000000000..8284f666bc4 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/util/Debug_debug.java @@ -0,0 +1,149 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +/********************************************************************** + * --------------------------- W A R N I N G -------------------------- + * + * This file is the same as Debug_ship.java, except the static final + * constants have been set to enable debugging and tracing. You must + * double-edit any changes in this file into Debug_ship.java, and + * vice-versa. + * See debug_tweak.mk for how one of these two files is copied into + * Debug.java during the build. + **********************************************************************/ + +package com.netscape.jss.util; + +/** + * Controls debug-mode operation of JSS classes, and allows for printing + * trace statements to standard output. + * + * @see com.netscape.jss.util.Assert + * @version $Revision: 1.1 $ $Date: 2000-12-15 20:52:39 $ + */ +public class Debug +{ + /** + * Controls debug mode for JSS. If DEBUG==true, debugging + * code will be enabled. If DEBUG==false, debugging code will not be + * executed. This variable does not influence the printing of trace + * statements; their execution depends on the debug level, which can + * be accessed through setLevel and getLevel. + * + * @see com.netscape.jss.util.Assert + */ + public static final boolean DEBUG = true; + + public static final int OBNOXIOUS = 10; + public static final int VERBOSE = 5; + public static final int ERROR = 1; + public static final int QUIET = 0; + + /** + * The debug level of the application. This gives the level of detail + * trace messages will contain. A level of 0 means no debugging + * statements will be printed. + * + * !!If you change this, change it in the native code too!! + */ + private static int mDebugLevel = VERBOSE; + + /** + * Print a trace statement to standard output. + * + * @param level The detail level of the statement. + * The level must be greater than 0. + * @param str The trace statement. + */ + public synchronized static void trace(int level, String str) + { + // validate arguments in debug mode + if(DEBUG && (level < 0) ) { + throw new AssertionException("invalid debugging level "+level+ + " in trace"); + } + if (level <= mDebugLevel) + { + System.out.println(Thread.currentThread().getName() + ": " + str); + System.out.flush(); + } + } + + /** + * Print a trace statement to standard output. + * Uses the VERBOSE detail level. + * + * @param str The trace statement. + */ + public synchronized static void trace(String str) + { + trace(VERBOSE, str); + } + + /** + * Set the debugging level of the application. + * The level must not be negative. + */ + public synchronized static void setLevel(int level) + { + // In debugging mode, validate argument + if( DEBUG && (level < 0) ) { + throw new AssertionException("invalid debugging level set"); + } + + mDebugLevel = level; + setNativeLevel(level); + } + private static native void setNativeLevel(int level); + + /** + * Get debugging level of the application. + * + * @return The current debugging level of the application. + */ + public synchronized static int getLevel() { + return mDebugLevel; + } + + public synchronized static String getLevelStr() { + switch(mDebugLevel) { + case QUIET: return "QUIET"; + case ERROR: return "ERROR"; + case VERBOSE: return "VERBOSE"; + case OBNOXIOUS: return "OBNOXIOUS"; + default: + return String.valueOf(mDebugLevel); + } + } +} + diff --git a/mozilla/security/jss/org/mozilla/jss/util/Debug_ship.java b/mozilla/security/jss/org/mozilla/jss/util/Debug_ship.java new file mode 100644 index 00000000000..0497adf7d7e --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/util/Debug_ship.java @@ -0,0 +1,150 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +/********************************************************************** + * --------------------------- W A R N I N G -------------------------- + * + * This file is the same as Debug_debug.java, except the static final + * constants have been set to disable debugging and tracing. You must + * double-edit any changes in this file into Debug_debug.java, and + * vice-versa. + * See debug_tweak.mk for how one of these two files is copied into + * Debug.java during the build. + **********************************************************************/ + + +package com.netscape.jss.util; + +/** + * Controls debug-mode operation of JSS classes, and allows for printing + * trace statements to standard output. + * + * @see com.netscape.jss.util.Assert + * @version $Revision: 1.1 $ $Date: 2000-12-15 20:52:39 $ + */ +public class Debug +{ + /** + * Controls debug mode for JSS. If DEBUG==true, debugging + * code will be enabled. If DEBUG==false, debugging code will not be + * executed. This variable does not influence the printing of trace + * statements; their execution depends on the debug level, which can + * be accessed through setLevel and getLevel. + * + * @see com.netscape.jss.util.Assert + */ + public static final boolean DEBUG = false; + + public static final int OBNOXIOUS = 10; + public static final int VERBOSE = 5; + public static final int ERROR = 1; + public static final int QUIET = 0; + + /** + * The debug level of the application. This gives the level of detail + * trace messages will contain. A level of 0 means no debugging + * statements will be printed. + * + * !!If you change this, change it in the native code too!! + */ + private static int mDebugLevel = ERROR; + + /** + * Print a trace statement to standard output. + * + * @param level The detail level of the statement. + * The level must be greater than 0. + * @param str The trace statement. + */ + public synchronized static void trace(int level, String str) + { + // validate arguments in debug mode + if(DEBUG && (level < 0) ) { + throw new AssertionException("invalid debugging level "+level+ + " in trace"); + } + if (level <= mDebugLevel) + { + System.out.println(Thread.currentThread().getName() + ": " + str); + System.out.flush(); + } + } + + /** + * Print a trace statement to standard output. + * Uses the VERBOSE detail level. + * + * @param str The trace statement. + */ + public synchronized static void trace(String str) + { + trace(VERBOSE, str); + } + + /** + * Set the debugging level of the application. + * The level must not be negative. + */ + public synchronized static void setLevel(int level) + { + // In debugging mode, validate argument + if( DEBUG && (level < 0) ) { + throw new AssertionException("invalid debugging level set"); + } + + mDebugLevel = level; + setNativeLevel(level); + } + private static native void setNativeLevel(int level); + + /** + * Get debugging level of the application. + * + * @return The current debugging level of the application. + */ + public synchronized static int getLevel() { + return mDebugLevel; + } + + public synchronized static String getLevelStr() { + switch(mDebugLevel) { + case QUIET: return "QUIET"; + case ERROR: return "ERROR"; + case VERBOSE: return "VERBOSE"; + case OBNOXIOUS: return "OBNOXIOUS"; + default: + return String.valueOf(mDebugLevel); + } + } +} + diff --git a/mozilla/security/jss/org/mozilla/jss/util/IncorrectPasswordException.java b/mozilla/security/jss/org/mozilla/jss/util/IncorrectPasswordException.java new file mode 100644 index 00000000000..ddb446a8a7c --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/util/IncorrectPasswordException.java @@ -0,0 +1,39 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.util; + +public class IncorrectPasswordException extends Exception { + public IncorrectPasswordException() { super(); } + public IncorrectPasswordException(String mesg) { super(mesg); } +} diff --git a/mozilla/security/jss/org/mozilla/jss/util/InvalidNicknameException.java b/mozilla/security/jss/org/mozilla/jss/util/InvalidNicknameException.java new file mode 100644 index 00000000000..de4fd0309da --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/util/InvalidNicknameException.java @@ -0,0 +1,39 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.util; + +public class InvalidNicknameException extends Exception { + public InvalidNicknameException() { super(); } + public InvalidNicknameException(String mesg) { super(mesg); } +} diff --git a/mozilla/security/jss/org/mozilla/jss/util/Makefile b/mozilla/security/jss/org/mozilla/jss/util/Makefile new file mode 100644 index 00000000000..68815077e65 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/util/Makefile @@ -0,0 +1,80 @@ +#! gmake +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +####################################################################### +# (1) Include initial platform-independent assignments (MANDATORY). # +####################################################################### + +include manifest.mn + +####################################################################### +# (2) Include "global" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/config.mk + +####################################################################### +# (3) Include "component" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/$(MODULE)/config/config.mk + +####################################################################### +# (4) Include "local" platform-dependent assignments (OPTIONAL). # +####################################################################### + +include config.mk + +ALL_TRASH += Debug.java + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include debug_tweak.mk + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### + + + diff --git a/mozilla/security/jss/org/mozilla/jss/util/NativeProxy.c b/mozilla/security/jss/org/mozilla/jss/util/NativeProxy.c new file mode 100644 index 00000000000..ffe9e03cfb6 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/util/NativeProxy.c @@ -0,0 +1,126 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +/* This file does not contain native methods of NativeProxy; rather, it + * provides utility functions for using NativeProxys in C code */ + +#include +#include +#include "nativeUtil.h" + +/* + * Given a NativeProxy, extract the pointer and store it at the given + * address. + * + * nativeProxy: a JNI reference to a NativeProxy. + * ptr: address of a void* that will receive the pointer extracted from + * the NativeProxy. + * Returns: PR_SUCCESS on success, PR_FAILURE if an exception was thrown. + * + * Example: + * DataStructure *recovered; + * jobject proxy; + * JNIEnv *env; + * [...] + * if(JSS_getPtrFromProxy(env, proxy, (void**)&recovered) != PR_SUCCESS) { + * return; // exception was thrown! + * } + */ +PR_IMPLEMENT( PRStatus ) +JSS_getPtrFromProxy(JNIEnv *env, jobject nativeProxy, void **ptr) +{ + jclass nativeProxyClass; + jfieldID byteArrayField; + jbyteArray byteArray; + int size; + + PR_ASSERT(env!=NULL && nativeProxy != NULL && ptr != NULL); + + nativeProxyClass = (*env)->FindClass(env, "com/netscape/jss/util/NativeProxy"); + if(nativeProxyClass == NULL) { + ASSERT_OUTOFMEM(env); + return PR_FAILURE; + } + +#ifdef DEBUG + /* make sure what we got was really a NativeProxy object */ + PR_ASSERT( (*env)->IsInstanceOf(env, nativeProxy, nativeProxyClass) ); +#endif + + byteArrayField = (*env)->GetFieldID(env, nativeProxyClass, "mPointer", + "[B"); + if(byteArrayField==NULL) { + ASSERT_OUTOFMEM(env); + return PR_FAILURE; + } + + byteArray = (jbyteArray) (*env)->GetObjectField(env, nativeProxy, + byteArrayField); + PR_ASSERT(byteArray != NULL); + + size = sizeof(*ptr); + PR_ASSERT((*env)->GetArrayLength(env, byteArray) == size); + (*env)->GetByteArrayRegion(env, byteArray, 0, size, (void*)ptr); + if( (*env)->ExceptionOccurred(env) ) { + PR_ASSERT(PR_FALSE); + return PR_FAILURE; + } else { + return PR_SUCCESS; + } +} + +/* + * Turn a C pointer into a Java byte array. The byte array can be passed + * into a NativeProxy constructor. + * + * Returns a byte array containing the pointer, or NULL if an exception + * was thrown. + */ +PR_IMPLEMENT( jbyteArray ) +JSS_ptrToByteArray(JNIEnv *env, void *ptr) +{ + jbyteArray byteArray; + + /* Construct byte array from the pointer */ + byteArray = (*env)->NewByteArray(env, sizeof(ptr)); + if(byteArray==NULL) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + return NULL; + } + (*env)->SetByteArrayRegion(env, byteArray, 0, sizeof(ptr), (jbyte*)&ptr); + if((*env)->ExceptionOccurred(env) != NULL) { + PR_ASSERT(PR_FALSE); + return NULL; + } + return byteArray; +} diff --git a/mozilla/security/jss/org/mozilla/jss/util/NativeProxy.h b/mozilla/security/jss/org/mozilla/jss/util/NativeProxy.h new file mode 100644 index 00000000000..a846717e610 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/util/NativeProxy.h @@ -0,0 +1,76 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +#ifndef NATIVE_PROXY_H +#define NATIVE_PROXY_H + +/* Need to include these headers before this one: +#include +#include +*/ + +PR_BEGIN_EXTERN_C + +/* + * Given a NativeProxy, extract the pointer and store it at the given + * address. + * + * nativeProxy: a JNI reference to a NativeProxy. + * ptr: address of a void* that will receive the pointer extracted from + * the NativeProxy. + * Returns: PR_SUCCESS on success, PR_FAILURE if an exception was thrown. + * + * Example: + * DataStructure *recovered; + * jobject proxy; + * JNIEnv *env; + * [...] + * if(JSS_getPtrFromProxy(env, proxy, (void**)&recovered) != PR_SUCCESS) { + * return; // exception was thrown! + * } + */ +PR_EXTERN( PRStatus ) +JSS_getPtrFromProxy(JNIEnv *env, jobject nativeProxy, void **ptr); + +/* + * Turn a C pointer into a Java byte array. The byte array can be passed + * into a NativeProxy constructor. + * + * Returns a byte array containing the pointer, or NULL if an exception + * was thrown. + */ +PR_EXTERN( jbyteArray ) +JSS_ptrToByteArray(JNIEnv *env, void *ptr); + +PR_END_EXTERN_C + +#endif diff --git a/mozilla/security/jss/org/mozilla/jss/util/NativeProxy.java b/mozilla/security/jss/org/mozilla/jss/util/NativeProxy.java new file mode 100644 index 00000000000..242dff60bf5 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/util/NativeProxy.java @@ -0,0 +1,223 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.util; + +import com.netscape.jss.util.*; +import java.util.Hashtable; +import java.util.Random; +import java.util.Enumeration; + +/** + * NativeProxy, a superclass for Java classes that mirror C data structures. + * + * It contains some code to help make sure that native memory is getting + * freed properly. + * + * @author nicolson + * @version $Revision: 1.1 $ $Date: 2000-12-15 20:52:43 $ + */ +public abstract class NativeProxy +{ + + /** + * Default constructor. Should not be called. + */ + private NativeProxy() { + Assert.assert(false); + } + + /** + * Create a NativeProxy from a byte array representing a C pointer. + * This is the only way to create a NativeProxy, it should be called + * from the constructor of your subclass. + * + * @param pointer A byte array, created with JSS_ptrToByteArray, that + * contains a pointer pointing to a native data structure. The + * NativeProxy instance acts as a proxy for that native data structure. + */ + public NativeProxy(byte[] pointer) { + Assert.assert(pointer!=null); + if(Debug.DEBUG) { + registryIndex = register(); + } + mPointer = pointer; + } + + /** + * Deep comparison operator. + * @return true if obj has the same underlying native + * pointer. false if the obj is null or has + * a different underlying native pointer. + */ + public boolean equals(Object obj) { + if(obj==null) { + return false; + } + if( ! (obj instanceof NativeProxy) ) { + return false; + } + if( ((NativeProxy)obj).mPointer.length != mPointer.length) { + return false; + } + for(int i=0; i < mPointer.length; i++) { + if(mPointer[i] != ((NativeProxy)obj).mPointer[i]) { + return false; + } + } + return true; + } + + /** + * Release the native resources used by this proxy. + * Subclasses of NativeProxy must define this method to clean up + * data structures in C code that are referenced by this proxy. + * releaseNativeResources() will usually be implemented as a native method. + *

You don't call this method; NativeProxy.finalize() calls it for you. + *

You must declare a finalize() method which calls super.finalize(). + */ + protected abstract void releaseNativeResources(); + + /** + * Finalize this NativeProxy by releasing its native resources. + * The finalizer calls releaseNativeResources() so you don't have to. + * This finalizer should be called from the finalize() method of all + * subclasses: + * class MyProxy extends NativeProxy { + * [...] + * protected void finalize() throws Throwable { + * // do any object-specific finalization other than + * // releasing native resources + * [...] + * super.finalize(); + * } + * } + */ + protected void finalize() throws Throwable { + if(Debug.DEBUG) { + unregister(registryIndex); + } + releaseNativeResources(); + } + + /** + * Byte array containing native pointer bytes. + */ + private byte mPointer[]; + + /** + *

Native Proxy Registry + *

In debug mode, we keep track of all NativeProxy objects in a + * static registry. Whenever a NativeProxy is constructed, it + * registers. Whenever it finalizes, it unregisters. At the end of + * the game, we should be able to garbage collect and then assert that + * the registry is empty. This could be done, for example, in the + * jssjava JVM after main() completes. + * This registration process verifies that people are calling + * NativeProxy.finalize() from their subclasses of NativeProxy, so that + * releaseNativeResources() gets called. + */ + private long registryIndex; + static Hashtable registry; + static Random indexGenerator; + + static { + registry = new Hashtable(); + indexGenerator = new Random(); + } + + /** + * Register a NativeProxy instance. + * + * @return The unique index of this object in the registry. + */ + private synchronized static long register() { + Long index; + + // Get a unique index + do { + index = new Long(indexGenerator.nextLong()); + } while( registry.containsKey(index) ); + registry.put(index, index); + + return index.longValue(); + } + + /** + * Unregister a NativeProxy instance. + * + * @param index The index of this object in the registry, as returned + * from the previous call to register(). + */ + private synchronized static void unregister(long index) { + Long Lindex = new Long(index); + Long element; + + element = (Long) registry.remove(Lindex); + Assert.assert(element != null); + } + + /** + * @return A list of the indices in the registry. Each element is a Long. + * @see NativeProxy#getRegistryIndex + */ + public synchronized static Enumeration getRegistryIndices() { + return registry.keys(); + } + + /** + * @return The index of this NativeProxy in the NativeProxy registry. + * @see NativeProxy#getRegistryIndices + */ + public long getRegistryIndex() { + return registryIndex; + } + + /** + * Assert that the Registry is empty. Only works in debug mode; in + * ship mode, it is a no-op. If the Registry is not empty when this + * is called, an assertion (com.netscape.jss.util.AssertionException) + * is thrown. + */ + public synchronized static void assertRegistryEmpty() { + if( Debug.DEBUG ) { + if(! registry.isEmpty()) { + Debug.trace(Debug.VERBOSE, "Warning: "+ + String.valueOf(registry.size())+ + " NativeProxys are still registered."); + } else { + Debug.trace(Debug.OBNOXIOUS, "NativeProxy registry is empty"); + } + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/util/NotImplementedException.java b/mozilla/security/jss/org/mozilla/jss/util/NotImplementedException.java new file mode 100644 index 00000000000..865fef5c847 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/util/NotImplementedException.java @@ -0,0 +1,42 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.util; + +/** + * This exception is thrown whenever something isn't implemented. + */ +public class NotImplementedException extends Exception { + public NotImplementedException() { super(); } + public NotImplementedException(String mesg) { super(mesg); } +} diff --git a/mozilla/security/jss/org/mozilla/jss/util/NullPasswordCallback.java b/mozilla/security/jss/org/mozilla/jss/util/NullPasswordCallback.java new file mode 100644 index 00000000000..e37d5219f0f --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/util/NullPasswordCallback.java @@ -0,0 +1,57 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.util; + +/** + * A PasswordCallback that immediately gives up. This should be used + * when a user is not available to enter a password. Any operations + * that require a password will fail if this is used, unless the token + * has already been logged in manually. + * + * @see com.netscape.jss.crypto.CryptoToken#login + */ +public class NullPasswordCallback implements PasswordCallback { + + public Password getPasswordFirstAttempt(PasswordCallbackInfo info) + throws PasswordCallback.GiveUpException + { + throw new PasswordCallback.GiveUpException(); + } + + public Password getPasswordAgain(PasswordCallbackInfo info) + throws PasswordCallback.GiveUpException + { + throw new PasswordCallback.GiveUpException(); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/util/Password.java b/mozilla/security/jss/org/mozilla/jss/util/Password.java new file mode 100644 index 00000000000..6e8ecf07f4c --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/util/Password.java @@ -0,0 +1,271 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.util; + +import java.io.CharConversionException; + +/** + * Stores a password. clear should be + * called when the password is no longer needed so that the sensitive + * information is not left in memory. + *

A Password can be used as a hard-coded + * PasswordCallback. + * @see PasswordCallback + */ +public class Password implements PasswordCallback, Cloneable, + java.io.Serializable + { + + /** + * Don't use this if you aren't Password. + */ + private Password() { + cleared = true; + } + + /** + * Creates a Password from a char array, then wipes the char array. + * @param pw A char[] containing the password. This array will be + * cleared (set to zeroes) by the constructor. + */ + public Password(char[] pw) { + int i; + int length = pw.length; + + cleared = false; + + password = new char[length]; + for(i=0; i < length; i++) { + password[i] = pw[i]; + pw[i] = 0; + } + } + + /** + * An implementation of + * PasswordCallback.getPasswordFirstAttempt. This allows + * a Password object to be treated as a + * PasswordCallback. This method simply returns a clone + * of the password. + * + * @returns A copy of the password. The caller is responsible for + * clearing this copy. + */ + public synchronized Password + getPasswordFirstAttempt(PasswordCallbackInfo info) + throws PasswordCallback.GiveUpException { + if(cleared) { + throw new PasswordCallback.GiveUpException(); + } + return (Password)this.clone(); + } + + /** + * Compares this password to another and returns true if they + * are the same. + */ + public synchronized boolean + equals(Object obj) { + if(obj == null || !(obj instanceof Password)) { + return false; + } + Password pw = (Password)obj; + if( pw.password==null || password==null) { + return false; + } + if( pw.password.length != password.length ) { + return false; + } + for(int i=0; i < password.length; i++) { + if(pw.password[i] != password[i]) { + return false; + } + } + return true; + } + + /** + * An implementation of PasswordCallback.getPasswordAgain. + * This allows a Password object to be used as a + * PasswordCallback. This method is only called after + * a call to getPasswordFirstAttempt returned the wrong + * password. This means the password is incorrect and there's no + * sense returning it again, so a GiveUpException is thrown. + */ + public synchronized Password + getPasswordAgain(PasswordCallbackInfo info) + throws PasswordCallback.GiveUpException { + throw new PasswordCallback.GiveUpException(); + } + + /** + * Returns the char array underlying this password. It must not be + * modified in any way. + */ + public synchronized char[] getChars() { + return password; + } + + /** + * Returns a char array that is a copy of the password. + * The caller is responsible for wiping the returned array, + * for example using wipeChars. + */ + public synchronized char[] getCharCopy() { + return (char[]) password.clone(); + } + + /** + * Returns a null-terminated byte array that is the byte-encoding of + * this password. + * The returned array is a copy of the password. + * The caller is responsible for wiping the returned array, + * for example using wipeChars. + */ + synchronized byte[] getByteCopy() { + return charToByte( (char[]) password.clone() ); + } + + /** + * Clears the password so that sensitive data is no longer present + * in memory. This should be called as soon as the password is no + * longer needed. + */ + public synchronized void clear() { + int i; + int len = password.length; + + for(i=0; i < len; i++) { + password[i] = 0; + } + cleared = true; + } + + /** + * Clones the password. The resulting clone will be completely independent + * of the parent, which means it will have to be separately cleared. + */ + public synchronized Object clone() { + Password dolly = new Password(); + + dolly.password = (char[]) password.clone(); + dolly.cleared = cleared; + return dolly; + } + + + /** + * The finalizer clears the sensitive information before releasing + * it to the garbage collector, but it should have been cleared manually + * before this point anyway. + */ + protected void finalize() throws Throwable { + if(Debug.DEBUG && !cleared) { + System.err.println("ERROR: Password was garbage collected before"+ + " it was cleared."); + } + clear(); + } + + /** + * Converts a char array to a null-terminated byte array using a standard + * encoding, which is currently UTF8. The caller is responsible for + * clearing the copy (with wipeBytes, for example). + * + * @param charArray A character array, which should not be null. It will + * be wiped with zeroes. + * @returns A copy of the charArray, converted from Unicode to UTF8. It + * is the responsibility of the caller to clear the output byte array; + * wipeBytes is ideal for this purpose. + * @see Password#wipeBytes + */ + public static byte[] charToByte(char[] charArray) + { + byte[] byteArray; + Assert.assert(charArray != null); + try { + byteArray = UTF8Converter.UnicodeToUTF8NullTerm(charArray); + } catch(CharConversionException e) { + Assert.notReached("Password could not be converted from" + +" Unicode"); + byteArray = new byte[] {0}; + } finally { + wipeChars(charArray); + } + return byteArray; + } + + /** + * Wipes a byte array by setting all its elements to zero. + * null must not be passed in. + */ + public static void wipeBytes(byte[] byteArray) { + Assert.assert(byteArray != null); + UTF8Converter.wipeBytes(byteArray); + } + + /** + * Wipes a char array by setting all its elements to zero. + * null must not be passed in. + */ + public static void wipeChars(char[] charArray) { + int i; + Assert.assert(charArray != null); + for(i=0; i < charArray.length; i++) { + charArray[i] = 0; + } + } + + /** + * Reads a password from the console with echo disabled. This is a blocking + * call which will return after the user types a newline. + * It only works with ASCII password characters. + * The call is synchronized because it alters terminal settings in + * a way that is not thread-safe. + * + * @exception com.netscape.jss.util.PasswordCallback.GiveUpException + * If the user enters no password (just hits + * <enter>). + * @return The password the user entered at the command line. + */ + public synchronized static native Password readPasswordFromConsole() + throws PasswordCallback.GiveUpException; + + // The password, stored as a char[] so we can clear it. Passwords + // should never be stored in Strings because Strings can't be cleared. + private char[] password; + + // true if the char[] has been cleared of sensitive information + private boolean cleared; +} diff --git a/mozilla/security/jss/org/mozilla/jss/util/PasswordCallback.java b/mozilla/security/jss/org/mozilla/jss/util/PasswordCallback.java new file mode 100644 index 00000000000..196e49e435c --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/util/PasswordCallback.java @@ -0,0 +1,85 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.util; + +/** + * Represents a password callback, which is called to login to the key + * database and to PKCS #11 tokens. + *

The simplest implementation of a PasswordCallback is a Password object. + * + * @see com.netscape.jss.util.Password + * @see com.netscape.jss.util.NullPasswordCallback + * @see com.netscape.jss.util.ConsolePasswordCallback + * @see com.netscape.jss.CryptoManager#setPasswordCallback + */ +public interface PasswordCallback { + + /** + * This exception is thrown if the PasswordCallback + * wants to stop guessing passwords. + */ + public static class GiveUpException extends Exception { + public GiveUpException() { super(); } + public GiveUpException(String mesg) { super(mesg); } + } + + /** + * Supplies a password. This is called on the first attempt; if it + * returns the wrong password, getPasswordAgain will + * be called on subsequent attempts. + * + * @param info Information about the token that is being logged into. + * @return The password. This password object is owned by and will + * be cleared by the caller. + * @exception GiveUpException If the callback does not want to supply + * a password. + */ + public Password getPasswordFirstAttempt(PasswordCallbackInfo info) + throws GiveUpException; + + /** + * Tries supplying a password again. This callback will be called if + * the first callback returned an invalid password. It will be called + * repeatedly until it returns a correct password, or it gives up by + * throwing a GiveUpException. + * + * @param info Information about the token that is being logged into. + * @returns The password. This password object is owned by and will + * be cleared by the caller. + * @exception GiveUpException If the callback does not want to supply + * a password. This may often be the case if the first attempt failed. + */ + public Password getPasswordAgain(PasswordCallbackInfo info) + throws GiveUpException; +} diff --git a/mozilla/security/jss/org/mozilla/jss/util/PasswordCallbackInfo.java b/mozilla/security/jss/org/mozilla/jss/util/PasswordCallbackInfo.java new file mode 100644 index 00000000000..f74cb83d9d2 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/util/PasswordCallbackInfo.java @@ -0,0 +1,80 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.util; + +/** + * An object of this class is passed to a PasswordCallback to give it + * information about the token that is being logged into. + */ +public class PasswordCallbackInfo { + + /** + * @param name The name of the file or token that is being logged into. + * @param type The type of object (FILE or + * TOKEN) that is being logged into. + */ + public PasswordCallbackInfo(String name, int type) { + Assert.assert(type==FILE || type==TOKEN); + this.name = name; + this.type = type; + } + + /** + * The name of the file or token that is being logged into. + */ + public String getName() { + return name; + } + + /** + * The type of object that is being logged into, FILE + * or TOKEN. + */ + public int getType() { + return type; + } + + protected String name; + protected int type; + + /** + * Logging into a file. + */ + static public final int FILE = 0; + + /** + * Logging into a PKCS #11 token. + */ + static public final int TOKEN = 1; +} diff --git a/mozilla/security/jss/org/mozilla/jss/util/Tunnel.java b/mozilla/security/jss/org/mozilla/jss/util/Tunnel.java new file mode 100644 index 00000000000..830ce8d878e --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/util/Tunnel.java @@ -0,0 +1,45 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.util; + +/** + * A class to allow friendly functions access to other parts of JSS. + */ +public class Tunnel { + + protected static byte[] + GetPasswordByteCopy(Password pw) { + return pw.getByteCopy(); + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/util/UTF8Converter.java b/mozilla/security/jss/org/mozilla/jss/util/UTF8Converter.java new file mode 100644 index 00000000000..e245314228b --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/util/UTF8Converter.java @@ -0,0 +1,458 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +package com.netscape.jss.util; + +import java.io.*; + +/** + * Class for converting between char arrays and byte arrays. The conversion + * is guaranteed (in optimized mode only) not to leave any data hanging around + * in memory unless there is a catastrophic VM error, which is useful for + * encoding passwords. + */ +public class UTF8Converter { + + /** + * Creates a new UTF8-encoded byte array representing the + * char[] passed in. The output array will NOT be null-terminated. + * + *

This call is safe for passwords; all internal buffers are cleared. + * The output array is the owned by the caller, who has responsibility + * for clearing it. + * + *

See http://www.stonehard.com/unicode/standard/ for the UTF-16 + * and UTF-8 standards. + * + * @param unicode An array of Unicode characters, which may have UCS4 + * characters encoded in UTF-16. This array must not be null. + * @exception CharConversionException If the input characters are invalid. + */ + public static byte[] UnicodeToUTF8(char[] unicode) + throws CharConversionException + { + return UnicodeToUTF8(unicode, false); + } + + /** + * Creates a new null-terminated UTF8-encoded byte array representing the + * char[] passed in. + * + *

This call is safe for passwords; all internal buffers are cleared. + * The output array is the owned by the caller, who has responsibility + * for clearing it. + * + *

See http://www.stonehard.com/unicode/standard/ for the UTF-16 + * and UTF-8 standards. + * + * @param unicode An array of Unicode characters, which may have UCS4 + * characters encoded in UTF-16. This array must not be null. + * @exception CharConversionException If the input characters are invalid. + */ + public static byte[] UnicodeToUTF8NullTerm(char [] unicode) + throws CharConversionException + { + return UnicodeToUTF8(unicode, true); + } + + /** + * Do the work of the above functions. + */ + protected static byte[] UnicodeToUTF8(char[] unicode, boolean nullTerminate) + throws CharConversionException + { + int uni; // unicode index + int utf; // UTF8 index + int maxsize; // maximum size of UTF8 output + byte[] utf8 = null; // UTF8 output buffer + byte[] temp = null; // used to create an array of the correct size + char c; // Unicode character + int ucs4; // UCS4 encoding of a character + boolean failed = true; + boolean orphaned_low = false; + + Assert.assert(unicode != null); + if(unicode == null) { + return null; + } + + try { + + // Allocate worst-case size (UTF8 bytes == 1.5 times Unicode bytes) + maxsize = unicode.length * 3; //chars are 2 bytes each + if(nullTerminate) { + maxsize++; + } + utf8 = new byte[maxsize]; + + for(uni=0, utf=0; uni < unicode.length; uni++) { + + // + // Convert UCS2 to UCS4 + // + c = unicode[uni]; + if( c >= 0xd800 && c <= 0xdbff) { + // This is the high half of a UTF-16 char + ucs4 = (c-0xd800)<<10; + + // Now get the lower half + if(uni == unicode.length-1) { + //There is no lower half + throw new CharConversionException(); + } + c = unicode[++uni]; + if(c < 0xdc00 || c > 0xdfff) { + // not in the low-half zone + throw new CharConversionException(); + } + ucs4 |= c-0xdc00; + ucs4 += 0x00010000; + } else if(c >=0xdc00 && c <=0xdfff) { + // orphaned low-half char + orphaned_low = true; + throw new CharConversionException(); + } else { + // UCS2 char to UCS4 + ucs4 = unicode[uni]; + } + + + // + // UCS4 to UTF8 conversion + // + if(ucs4 < 0x80) { + // 0000 0000 - 0000 007f (ASCII) + utf8[utf++] = (byte)ucs4; + } else if(ucs4 < 0x800) { + // 0000 0080 - 0000 07ff + utf8[utf++] = (byte) (0xc0 | ucs4>>6); + utf8[utf++] = (byte) (0x80 | (ucs4 & 0x3f) ); + } else if(ucs4 < 0x0010000) { + // 0000 0800 - 0000 ffff + utf8[utf++] = (byte) (0xe0 | ucs4>>12); + utf8[utf++] = (byte) (0x80 | ((ucs4>>6) & 0x3f) ); + utf8[utf++] = (byte) (0x80 | (ucs4 & 0x3f) ); + } else if(ucs4 < 0x00200000) { + // 001 0000 - 001f ffff + utf8[utf++] = (byte) (0xf0 | ucs4>>18); + utf8[utf++] = (byte) (0x80 | ((ucs4>>12) & 0x3f) ); + utf8[utf++] = (byte) (0x80 | ((ucs4>>6) & 0x3f) ); + utf8[utf++] = (byte) (0x80 | (ucs4 & 0x3f) ); + } else if(ucs4 < 0x00200000) { + // 0020 0000 - 03ff ffff + utf8[utf++] = (byte) (0xf8 | ucs4>>24); + utf8[utf++] = (byte) (0x80 | ((ucs4>>18) & 0x3f) ); + utf8[utf++] = (byte) (0x80 | ((ucs4>>12) & 0x3f) ); + utf8[utf++] = (byte) (0x80 | ((ucs4>>6) & 0x3f) ); + utf8[utf++] = (byte) (0x80 | (ucs4 & 0x3f) ); + } else { + // 0400 0000 - 7fff ffff + utf8[utf++] = (byte) (0xfc | ucs4>>30); + utf8[utf++] = (byte) (0x80 | ((ucs4>>24) & 0x3f) ); + utf8[utf++] = (byte) (0x80 | ((ucs4>>18) & 0x3f) ); + utf8[utf++] = (byte) (0x80 | ((ucs4>>12) & 0x3f) ); + utf8[utf++] = (byte) (0x80 | ((ucs4>>6) & 0x3f) ); + utf8[utf++] = (byte) (0x80 | (ucs4 & 0x3f) ); + } + } + + if(nullTerminate) { + utf8[utf++] = 0; + } + + // + // Copy into a correct-sized array + // + try { + int i; + + // last index is the size of the UTF8 + temp = new byte[utf]; + + for(i=0; i < utf; i++) { + temp[i] = utf8[i]; + utf8[i] = 0; + } + utf8 = temp; + temp = null; + } finally { + if(temp != null) { + wipeBytes(temp); + } + } + + failed = false; + return utf8; + + } finally { + // Cleanup data locations where the password was written + if(failed && utf8 != null) { + wipeBytes(utf8); + utf8 = null; + } + ucs4 = 0; + c = 0; + + if(Debug.DEBUG) { + // Verify this operation by comparing its output + // to that of the standard Java conversion routines. + // WARNING: This means passwords will be left in memory, + // so Ninja is not secure in debugging mode! + try { + OutputStreamWriter writer; + ByteArrayOutputStream barray; + int i; + byte[] output; + + barray = new ByteArrayOutputStream(); + + writer = new OutputStreamWriter(barray, "UTF8"); + writer.write(unicode, 0, unicode.length); + writer.close(); + + output = barray.toByteArray(); + + // My class rejects orphaned low-half characters, but the Java + // class allows them. I think they really are bogus, so + // let's pretend the Java class rejects them too. + if(orphaned_low) { + throw new IOException(); + } + + // It worked with the Java class, so it should have worked + // with my class + Assert.assert(utf8 != null); + + // Compare the arrays + if(nullTerminate) { + Assert.assert(utf8.length-1 == output.length); + } else { + Assert.assert(utf8.length == output.length); + } + for(i=0; i "+utf8.length+ + " bytes of utf8\n"); + + // + // empty array + // + System.out.println("Empty input test:"); + unicode = new char[0]; + utf8 = UnicodeToUTF8(unicode); + Assert.assert(utf8 != null); + Assert.assert(utf8.length == 0); + System.out.println("given 0 bytes Unicode, produces 0 length utf8\n"); + + // + // UCS4 + // + System.out.println("UCS4 Test:"); + unicode = new char[] {'\ud800', '\udc00', '\uda85', '\ude47', + '\udbff', '\udfff'}; + utf8 = UnicodeToUTF8(unicode); + for(i=0; i < 6; i++) { + System.out.print( Integer.toHexString(unicode[i]) + " "); + } + System.out.println(); + for(i=0; i < utf8.length; i++) { + System.out.print( Integer.toHexString(utf8[i]) + " "); + } + System.out.println("\n"); + + // + // high half with no low half + // + System.out.println("high half at end of input:"); + try { + unicode = new char[] {'\ud800'}; + utf8 = UnicodeToUTF8(unicode); + Assert.notReached("should have failed on bad UCS4"); + } catch (CharConversionException e) { + System.out.println("Correctly caught bad UCS4\n"); + } + + // + // high half with something else + // + System.out.println("high half with something other than low half:"); + try { + unicode = new char[] {'\ud800', '\u007f'}; + utf8 = UnicodeToUTF8(unicode); + Assert.notReached("should have failed on bad UCS4"); + } catch (CharConversionException e) { + System.out.println("Correctly caught bad UCS4\n"); + } + + // + // orphaned low half + // + System.out.println("orphaned low half test:"); + try { + unicode = new char[] {'\u0032', '\udc01', '\u0033'}; + utf8 = UnicodeToUTF8(unicode); + Assert.notReached("should have failed on bad UCS4"); + } catch (CharConversionException e) { + System.out.println("Correctly caught bad UCS4\n"); + } + + // + // null-terminated + // + System.out.println("null-terminating:"); + unicode = new char[] {'f', 'o', 'o', 'b', 'a', 'r'}; + utf8 = UnicodeToUTF8NullTerm(unicode); + for(i=0; i < unicode.length; i++) { + System.out.print(unicode[i] + " "); + } + System.out.println(); + for(i=0; i < utf8.length; i++) { + System.out.print(utf8[i] + " "); + } + System.out.println("\n"); + + + } catch(CharConversionException e) { + System.out.println("Error converting Unicode "+e); + } finally { + if(!Debug.DEBUG) { + System.out.println("***WARNING***"); + System.out.println("Debugging mode is disabled. This code only"+ + " checks itself in debug mode. The test is almost worthless"+ + " in optimized mode." + ); + } + } + } +} diff --git a/mozilla/security/jss/org/mozilla/jss/util/config.mk b/mozilla/security/jss/org/mozilla/jss/util/config.mk new file mode 100644 index 00000000000..948f177baf1 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/util/config.mk @@ -0,0 +1,58 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +####################################################################### +# Set the LD_LIBS value to encompass all static JSS, security, and # +# dbm libraries # +####################################################################### + +LD_LIBS += $(LIBSECUTIL) \ + $(NULL) + +####################################################################### +# Append additional LD_LIBS value to encompass all dynamic NSPR 2.0, # +# java, and system libraries # +####################################################################### + +ifeq ($(OS_ARCH), WINNT) + LD_LIBS += $(DLLPLDS) $(DLLPLC) $(DLLPR) $(DLLSYSTEM) +else + LD_LIBS += -L$(SOURCE_LIB_DIR) -lplds3 -lplc3 -lnspr3 $(DLLSYSTEM) +endif + +####################################################################### +# Turn off any Export Control Policy for these libraries # +####################################################################### + +POLICY = + diff --git a/mozilla/security/jss/org/mozilla/jss/util/debug_tweak.mk b/mozilla/security/jss/org/mozilla/jss/util/debug_tweak.mk new file mode 100644 index 00000000000..6e58e7598c6 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/util/debug_tweak.mk @@ -0,0 +1,59 @@ + +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +# Since Java doesn't support preprocessing, we need to make two versions +# of Debug.java: one has debugging enabled, the other has debugging +# disabled. Since the class is called Debug, the file must be called +# Debug.java. So we actually have two versions of the file, and we +# copy one of them to Debug.java depending on whether we are building +# debuggable or not. A hack, to be sure, and I'm open to better ideas. +# (nicolson) + +ifdef BUILD_OPT + JSS_DEBUG_SOURCE_FILE = Debug_ship.java +else + JSS_DEBUG_SOURCE_FILE = Debug_debug.java +endif + +# Since we're introducing new rules before the global rules.mk, we will +# wipe out the default rule. So put this here to keep "all" the default. +jss_util_all: all + +export:: + @echo "Copying $(JSS_DEBUG_SOURCE_FILE) to Debug.java" + cp $(JSS_DEBUG_SOURCE_FILE) Debug.java + chmod 0644 Debug.java + +clean:: + rm -f Debug.java diff --git a/mozilla/security/jss/org/mozilla/jss/util/java_ids.h b/mozilla/security/jss/org/mozilla/jss/util/java_ids.h new file mode 100644 index 00000000000..45669b9973f --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/util/java_ids.h @@ -0,0 +1,276 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +#ifndef JAVA_IDS_H +#define JAVA_IDS_H + +PR_BEGIN_EXTERN_C + +/* +** JNI uses strings to identity Java classes, fields, and methods. Rather +** than put lots of string constants in our JNI code, we define them once +** here. This has two benefits: it reduces the probability of typos +** (we only have to type the names once), and it allows us to more +** easily change these identifiers. +*/ + +#define PLAIN_CONSTRUCTOR "" +#define PLAIN_CONSTRUCTOR_SIG "()V" + +/* + * Algorithm + */ +#define ALGORITHM_CLASS_NAME "com/netscape/jss/crypto/Algorithm" +#define OID_INDEX_FIELD_NAME "oidIndex" +#define OID_INDEX_FIELD_SIG "I" + +/* + * BigInteger + */ +#define BIG_INTEGER_CLASS_NAME "java/math/BigInteger" +#define BIG_INTEGER_CONSTRUCTOR_NAME "" +#define BIG_INTEGER_CONSTRUCTOR_SIG "([B)V" + +/* + * CipherContextProxy + */ +#define CIPHER_CONTEXT_PROXY_CLASS_NAME "com/netscape/jss/pkcs11/CipherContextProxy" +#define CIPHER_CONTEXT_PROXY_CONSTRUCTOR_SIG "([B)V" + +/* + * Debug + */ +#define DEBUG_CLASS_NAME "com/netscape/jss/util/Debug" +#define DEBUG_TRACE_NAME "trace" +#define DEBUG_TRACE_SIG "(ILjava/lang/String;)V" + +/* + * KeyPair + */ +#define KEY_PAIR_CLASS_NAME "java/security/KeyPair" +#define KEY_PAIR_CONSTRUCTOR_NAME "" +#define KEY_PAIR_CONSTRUCTOR_SIG "(Ljava/security/PublicKey;Ljava/security/PrivateKey;)V" + +/* + * KeyProxy + */ +#define KEY_PROXY_FIELD "keyProxy" +#define KEY_PROXY_SIG "Lcom/netscape/jss/pkcs11/KeyProxy;" + +/* + * KeyType + */ +#define KEYTYPE_CLASS_NAME "com/netscape/jss/pkcs11/KeyType" +#define NULL_KEYTYPE_FIELD "NULL" +#define RSA_KEYTYPE_FIELD "RSA" +#define DSA_KEYTYPE_FIELD "DSA" +#define FORTEZZA_KEYTYPE_FIELD "FORTEZZA" +#define DH_KEYTYPE_FIELD "DH" +#define KEA_KEYTYPE_FIELD "KEA" +#define KEYTYPE_FIELD_SIG "Lcom/netscape/jss/pkcs11/KeyType;" +#define DES_KEYTYPE_FIELD "DES" +#define DES3_KEYTYPE_FIELD "DES3" +#define RC4_KEYTYPE_FIELD "RC4" +#define RC2_KEYTYPE_FIELD "RC2" +#define SHA1_HMAC_KEYTYPE_FIELD "SHA1_HMAC" + +/* + * NativeProxy + */ +#define NATIVE_PROXY_CLASS_NAME "com/netscape/jss/util/NativeProxy" +#define NATIVE_PROXY_POINTER_FIELD "mPointer" +#define NATIVE_PROXY_POINTER_SIG "[B" + +/* + * NSSInit + */ +#define NSSINIT_CLASS_NAME "com/netscape/jss/NSSInit" +#define NSSINIT_ISINITIALIZED_NAME "isInitialized" +#define NSSINIT_ISINITIALIZED_SIG "()Z" + +/* + * Password + */ +#define PASSWORD_CLASS_NAME "com/netscape/jss/util/Password" +#define PASSWORD_CONSTRUCTOR_SIG "([C)V" +#define PW_GET_BYTE_COPY_NAME "getByteCopy" +#define PW_GET_BYTE_COPY_SIG "()[B" +#define PW_CLEAR_NAME "clear" +#define PW_CLEAR_SIG "()V" + +/* + * PasswordCallback + */ +#define PW_CALLBACK_GET_PW_FIRST_NAME "getPasswordFirstAttempt" +#define PW_CALLBACK_GET_PW_FIRST_SIG "(Lcom/netscape/jss/util/PasswordCallbackInfo;)Lcom/netscape/jss/util/Password;" +#define PW_CALLBACK_GET_PW_AGAIN_NAME "getPasswordAgain" +#define PW_CALLBACK_GET_PW_AGAIN_SIG "(Lcom/netscape/jss/util/PasswordCallbackInfo;)Lcom/netscape/jss/util/Password;" + +/* + * PK11Cert + */ +#define CERT_CLASS_NAME "com/netscape/jss/pkcs11/PK11Cert" +#define CERT_CONSTRUCTOR_NAME "" +#define CERT_CONSTRUCTOR_SIG "([B)V" +#define CERT_PROXY_FIELD "certProxy" +#define CERT_PROXY_SIG "Lcom/netscape/jss/pkcs11/CertProxy;" + +/* + * PK11InternalCert + */ +#define INTERNAL_CERT_CLASS_NAME "com/netscape/jss/pkcs11/PK11InternalCert" + +/* + * PK11TokenCert + */ +#define TOKEN_CERT_CLASS_NAME "com/netscape/jss/pkcs11/PK11TokenCert" + +/* + * PK11InternalTokenCert + */ +#define INTERNAL_TOKEN_CERT_CLASS_NAME "com/netscape/jss/pkcs11/PK11InternalTokenCert" + +/* + * PK11DSAPublicKey + */ +#define PK11_DSA_PUBKEY_CLASS_NAME "com/netscape/jss/pkcs11/PK11DSAPublicKey" + +/* + * PK11Module + */ +#define PK11MODULE_CLASS_NAME "com/netscape/jss/pkcs11/PK11Module" +#define PK11MODULE_CONSTRUCTOR_SIG "([B)V" +#define PK11MODULE_PROXY_FIELD "moduleProxy" +#define PK11MODULE_PROXY_SIG "Lcom/netscape/jss/pkcs11/ModuleProxy;" + +/* + * PK11PrivKey + */ +#define PK11PRIVKEY_CLASS_NAME "com/netscape/jss/pkcs11/PK11PrivKey" +#define PK11PRIVKEY_CONSTRUCTOR_NAME "" +#define PK11PRIVKEY_CONSTRUCTOR_SIG "([B)V" + +/* + * PK11PubKey + */ +#define PK11PUBKEY_CLASS_NAME "com/netscape/jss/pkcs11/PK11PubKey" +#define PK11PUBKEY_CONSTRUCTOR_NAME "" +#define PK11PUBKEY_CONSTRUCTOR_SIG "([B)V" + +/* + * PK11RSAPublicKey + */ +#define PK11_RSA_PUBKEY_CLASS_NAME "com/netscape/jss/pkcs11/PK11RSAPublicKey" + +/* + * PK11Signature + */ +#define PK11SIGNATURE_CLASS_NAME "com/netscape/jss/pkcs11/PK11Signature" +#define SIG_CONTEXT_PROXY_FIELD "sigContext" +#define SIG_CONTEXT_PROXY_SIG "Lcom/netscape/jss/pkcs11/SigContextProxy;" +#define SIG_ALGORITHM_FIELD "algorithm" +#define SIG_ALGORITHM_SIG "Lcom/netscape/jss/crypto/Algorithm;" +#define SIG_PW_FIELD "pwExtractor" +#define SIG_PW_SIG "Lcom/netscape/jss/crypto/PasswordExtractor;" +#define SIG_KEY_FIELD "key" +#define SIG_KEY_SIG "Lcom/netscape/jss/pkcs11/PK11Key;" + +/* + * PK11Store + */ +#define PK11STORE_PROXY_FIELD "storeProxy" +#define PK11STORE_PROXY_SIG "Lcom/netscape/jss/pkcs11/TokenProxy;" + +/* + * PK11SymKey + */ +#define PK11SYMKEY_CLASS_NAME "com/netscape/jss/pkcs11/PK11SymKey" +#define PK11SYMKEY_CONSTRUCTOR_SIG "([B)V" + +/* + * PK11Token + */ +#define PK11TOKEN_PROXY_FIELD "tokenProxy" +#define PK11TOKEN_PROXY_SIG "Lcom/netscape/jss/pkcs11/TokenProxy;" +#define PK11TOKEN_CLASS_NAME "com/netscape/jss/pkcs11/PK11Token" +#define PK11TOKEN_CONSTRUCTOR_NAME "" +#define PK11TOKEN_CONSTRUCTOR_SIG "([BZZ)V" + +/* + * PrivateKey.KeyType + */ +#define PRIVKEYTYPE_CLASS_NAME "com/netscape/jss/crypto/PrivateKey$Type" +#define PRIVKEYTYPE_SIG "Lcom/netscape/jss/crypto/PrivateKey$Type;" +#define RSA_PRIVKEYTYPE_FIELD "RSA" +#define DSA_PRIVKEYTYPE_FIELD "DSA" + +/* + * PQGParams + */ +#define PQG_PARAMS_CONSTRUCTOR_NAME "" +#define PQG_PARAMS_CONSTRUCTOR_SIG "(Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;ILjava/math/BigInteger;)V" + +/* + * SigContextProxy + */ +#define SIG_CONTEXT_PROXY_CLASS_NAME "com/netscape/jss/pkcs11/SigContextProxy" +#define SIG_CONTEXT_PROXY_CONSTRUCTOR_NAME "" +#define SIG_CONTEXT_PROXY_CONSTRUCTOR_SIG "([B)V" + +/* + * SymKeyProxy + */ +#define SYM_KEY_PROXY_FIELD "keyProxy" +#define SYM_KEY_PROXY_SIG "Lcom/netscape/jss/pkcs11/SymKeyProxy;" + +/* + * TokenCallbackInfo + */ +#define TOKEN_CBINFO_CLASS_NAME "com/netscape/jss/pkcs11/TokenCallbackInfo" +#define TOKEN_CBINFO_CONSTRUCTOR_NAME "" +#define TOKEN_CBINFO_CONSTRUCTOR_SIG "(Ljava/lang/String;)V" + + +/* + * Vector + */ +#define VECTOR_ADD_ELEMENT_NAME "addElement" +#define VECTOR_ADD_ELEMENT_SIG "(Ljava/lang/Object;)V" + +/* + * X509Certificate + */ +#define X509_CERT_CLASS "com/netscape/jss/crypto/X509Certificate" + +PR_END_EXTERN_C + +#endif diff --git a/mozilla/security/jss/org/mozilla/jss/util/jss_bigint.h b/mozilla/security/jss/org/mozilla/jss/util/jss_bigint.h new file mode 100644 index 00000000000..11083294a26 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/util/jss_bigint.h @@ -0,0 +1,79 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +/* Need to include these first: +#include +#include +*/ + +#ifndef JSS_BIG_INT_H +#define JSS_BIG_INT_H + +PR_BEGIN_EXTERN_C + +/*********************************************************************** + * + * J S S _ O c t e t S t r i n g T o B y t e A r r a y + * + * Converts a representation of an integer as a big-endian octet string + * stored in a SECItem (as used by the low-level crypto functions) to a + * representation of an integer as a big-endian Java byte array. Prepends + * a zero byte to force it to be positive. + */ +PR_IMPLEMENT( jbyteArray ) +JSS_OctetStringToByteArray(JNIEnv *env, SECItem *item); + +/*********************************************************************** + * + * J S S _ B y t e A r r a y T o O c t e t S t r i n g + * + * Converts an integer represented as a big-endian Java byte array to + * an integer represented as a big-endian octet string in a SECItem. + * + * INPUTS + * byteArray + * A Java byte array containing an integer represented in + * big-endian format. Must not be NULL. + * item + * Pointer to a SECItem that will be filled with the integer + * from the byte array, in big-endian format. + * RETURNS + * PR_SUCCESS if the operation was successful, PR_FAILURE if an exception + * was thrown. + */ +PR_IMPLEMENT( PRStatus ) +JSS_ByteArrayToOctetString(JNIEnv *env, jbyteArray byteArray, SECItem *item); + +PR_END_EXTERN_C + +#endif diff --git a/mozilla/security/jss/org/mozilla/jss/util/jss_exceptions.h b/mozilla/security/jss/org/mozilla/jss/util/jss_exceptions.h new file mode 100644 index 00000000000..75ba85092c7 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/util/jss_exceptions.h @@ -0,0 +1,108 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +/* These are class names suitable for passing to JSS_nativeThrow or +** JSS_nativeThrowMsg. They are the fully qualified class name of the +** exception, separated by slashes instead of periods. +*/ +#ifndef JSS_EXCEPTIONS_H +#define JSS_EXCEPTIONS_H + + +PR_BEGIN_EXTERN_C + + +#define ALREADY_INITIALIZED_EXCEPTION "com/netscape/jss/crypto/AlreadyInitializedException" + +#define BAD_PADDING_EXCEPTION "com/netscape/jss/crypto/BadPaddingException" + +#define CERT_DATABASE_EXCEPTION "com/netscape/jss/CertDatabaseException" + +#define CERTIFICATE_EXCEPTION "java/security/cert/CertificateException" + +#define CERTIFICATE_ENCODING_EXCEPTION "java/security/cert/CertificateEncodingException" + +#define CRL_IMPORT_EXCEPTION "com/netscape/jss/CRLImportException" + +#define DIGEST_EXCEPTION "java/security/DigestException" + +#define GENERAL_SECURITY_EXCEPTION "java/security/GeneralSecurityException" + +#define GENERIC_EXCEPTION "java/lang/Exception" + +#define GIVE_UP_EXCEPTION "com/netscape/jss/util/PasswordCallback$GiveUpException" + +#define ILLEGAL_ARGUMENT_EXCEPTION "java/lang/IllegalArgumentException" + +#define ILLEGAL_BLOCK_SIZE_EXCEPTION "com/netscape/jss/crypto/IllegalBlockSizeException" + +#define INCORRECT_PASSWORD_EXCEPTION "com/netscape/jss/util/IncorrectPasswordException" + +#define INVALID_KEY_FORMAT_EXCEPTION "com/netscape/jss/crypto/InvalidKeyFormatException" + +#define INVALID_PARAMETER_EXCEPTION "java/security/InvalidParameterException" + +#define KEY_DATABASE_EXCEPTION "com/netscape/jss/KeyDatabaseException" + +#define KEY_EXISTS_EXCEPTION "com/netscape/jss/crypto/KeyAlreadyImportedException" + +#define NICKNAME_CONFLICT_EXCEPTION "com/netscape/jss/CryptoManager$NicknameConflictException" + +#define NO_SUCH_ITEM_ON_TOKEN_EXCEPTION "com/netscape/jss/crypto/NoSuchItemOnTokenException" + +#define NO_SUCH_TOKEN_EXCEPTION "com/netscape/jss/NoSuchTokenException" + +#define NOT_EXTRACTABLE_EXCEPTION "com/netscape/jss/crypto/SymmetricKey$NotExtractableException" + +#define NULL_POINTER_EXCEPTION "java/lang/NullPointerException" + +#define OBJECT_NOT_FOUND_EXCEPTION "com/netscape/jss/crypto/ObjectNotFoundException" + +#define OUT_OF_MEMORY_ERROR "java/lang/OutOfMemoryError" + +#define PQG_PARAM_GEN_EXCEPTION "com/netscape/jss/crypto/PQGParamGenException" + +/* This is a RuntimeException */ +#define SECURITY_EXCEPTION "java/lang/SecurityException" + +#define SIGNATURE_EXCEPTION "java/security/SignatureException" + +#define TOKEN_EXCEPTION "com/netscape/jss/crypto/TokenException" + +#define TOKEN_NOT_INITIALIZED_EXCEPTION "com/netscape/jss/pkcs11/PK11Token$NotInitializedException" + +#define USER_CERT_CONFLICT_EXCEPTION "com/netscape/jss/CryptoManager$UserCertConflictException" + +PR_END_EXTERN_C + +#endif diff --git a/mozilla/security/jss/org/mozilla/jss/util/jssutil.c b/mozilla/security/jss/org/mozilla/jss/util/jssutil.c new file mode 100644 index 00000000000..b78b3d92120 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/util/jssutil.c @@ -0,0 +1,802 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +#include +#include +#include +#include +#include +#include "jssutil.h" +#include "jss_bigint.h" +#include +#include "java_ids.h" + +#include "_jni/com_netscape_jss_util_Password.h" + +/*********************************************************************** +** +** J S S _ t h r o w M s g +** +** Throw an exception in native code. You should return right after +** calling this function. +** +** throwableClassName is the name of the throwable you are throwing in +** JNI class name format (xxx/xx/xxx/xxx). It must not be NULL. +** +** message is the message parameter of the throwable. It must not be NULL. +** If you don't have a message, call JSS_throw. +** +** Example: +** JSS_throwMsg(env, ILLEGAL_ARGUMENT_EXCEPTION, +** "Bogus argument, you ninny"); +** return -1; +*/ +PR_IMPLEMENT( void ) +JSS_throwMsg(JNIEnv *env, char *throwableClassName, char *message) { + + jclass throwableClass; + jint result; + + /* validate arguments */ + PR_ASSERT(env!=NULL && throwableClassName!=NULL && message!=NULL); + + throwableClass = NULL; + if(throwableClassName) { + throwableClass = (*env)->FindClass(env, throwableClassName); + + /* make sure the class was found */ + PR_ASSERT(throwableClass != NULL); + } + if(throwableClass == NULL) { + throwableClass = (*env)->FindClass(env, GENERIC_EXCEPTION); + } + PR_ASSERT(throwableClass != NULL); + + result = (*env)->ThrowNew(env, throwableClass, message); + PR_ASSERT(result == 0); +} + +/*********************************************************************** +** +** J S S _ t h r o w +** +** Throw an exception in native code. You should return right after +** calling this function. +** +** throwableClassName is the name of the throwable you are throwing in +** JNI class name format (xxx/xx/xxx/xxx). It must not be NULL. +** +** Example: +** JSS_throw(env, ILLEGAL_ARGUMENT_EXCEPTION); +** return -1; +*/ +PR_IMPLEMENT( void ) +JSS_throw(JNIEnv *env, char *throwableClassName) +{ + jclass throwableClass; + jobject throwable; + jmethodID constructor; + jint result; + + PR_ASSERT( (*env)->ExceptionOccurred(env) == NULL ); + + /* Lookup the class */ + throwableClass = NULL; + if(throwableClassName) { + throwableClass = (*env)->FindClass(env, throwableClassName); + + /* make sure the class was found */ + PR_ASSERT(throwableClass != NULL); + } + if(throwableClass == NULL) { + throwableClass = (*env)->FindClass(env, GENERIC_EXCEPTION); + } + PR_ASSERT(throwableClass != NULL); + + /* Lookup up the plain vanilla constructor */ + constructor = (*env)->GetMethodID( + env, + throwableClass, + PLAIN_CONSTRUCTOR, + PLAIN_CONSTRUCTOR_SIG); + if(constructor == NULL) { + /* Anything other than OutOfMemory is a bug */ + ASSERT_OUTOFMEM(env); + return; + } + + /* Create an instance of the throwable */ + throwable = (*env)->NewObject(env, throwableClass, constructor); + if(throwable == NULL) { + /* Anything other than OutOfMemory is a bug */ + ASSERT_OUTOFMEM(env); + return; + } + + /* Throw the new instance */ + result = (*env)->Throw(env, throwable); + PR_ASSERT(result == 0); +} + +/*********************************************************************** +** +** J S S _ g e t P t r F r o m P r o x y +** +** Given a NativeProxy, extract the pointer and store it at the given +** address. +** +** nativeProxy: a JNI reference to a NativeProxy. +** ptr: address of a void* that will receive the pointer extracted from +** the NativeProxy. +** Returns: PR_SUCCESS on success, PR_FAILURE if an exception was thrown. +** +** Example: +** DataStructure *recovered; +** jobject proxy; +** JNIEnv *env; +** [...] +** if(JSS_getPtrFromProxy(env, proxy, (void**)&recovered) != PR_SUCCESS) { +** return; // exception was thrown! +** } +*/ +PR_IMPLEMENT( PRStatus ) +JSS_getPtrFromProxy(JNIEnv *env, jobject nativeProxy, void **ptr) +{ + jclass nativeProxyClass; + jclass proxyClass; + jfieldID byteArrayField; + jbyteArray byteArray; + int size; + + PR_ASSERT(env!=NULL && nativeProxy != NULL && ptr != NULL); + + proxyClass = (*env)->GetObjectClass(env, nativeProxy); + PR_ASSERT(proxyClass != NULL); + +#ifdef DEBUG + nativeProxyClass = (*env)->FindClass( + env, + NATIVE_PROXY_CLASS_NAME); + if(nativeProxyClass == NULL) { + ASSERT_OUTOFMEM(env); + return PR_FAILURE; + } + + /* make sure what we got was really a NativeProxy object */ + PR_ASSERT( (*env)->IsInstanceOf(env, nativeProxy, nativeProxyClass) ); +#endif + + byteArrayField = (*env)->GetFieldID( + env, + proxyClass, + NATIVE_PROXY_POINTER_FIELD, + NATIVE_PROXY_POINTER_SIG); + if(byteArrayField==NULL) { + ASSERT_OUTOFMEM(env); + return PR_FAILURE; + } + + byteArray = (jbyteArray) (*env)->GetObjectField(env, nativeProxy, + byteArrayField); + PR_ASSERT(byteArray != NULL); + + size = sizeof(*ptr); + PR_ASSERT((*env)->GetArrayLength(env, byteArray) == size); + (*env)->GetByteArrayRegion(env, byteArray, 0, size, (void*)ptr); + if( (*env)->ExceptionOccurred(env) ) { + PR_ASSERT(PR_FALSE); + return PR_FAILURE; + } else { + return PR_SUCCESS; + } +} + +/*********************************************************************** +** +** J S S _ g e t P t r F r o m P r o x y O w n e r +** +** Given an object which contains a NativeProxy, extract the pointer +** from the NativeProxy and store it at the given address. +** +** proxyOwner: an object which contains a NativeProxy member. +** proxyFieldName: the name of the NativeProxy member. +** proxyFieldSig: the signature of the NativeProxy member. +** ptr: address of a void* that will receive the extract pointer. +** Returns: PR_SUCCESS for success, PR_FAILURE if an exception was thrown. +** +** Example: +** +** public class Owner { +** protected MyProxy myProxy; +** [...] +** } +** +** +** DataStructure *recovered; +** jobject owner; +** JNIEnv *env; +** [...] +** if(JSS_getPtrFromProxyOwner(env, owner, "myProxy", (void**)&recovered) +** != PR_SUCCESS) { +** return; // exception was thrown! +** } +*/ +PR_IMPLEMENT( PRStatus ) +JSS_getPtrFromProxyOwner(JNIEnv *env, jobject proxyOwner, char* proxyFieldName, + char *proxyFieldSig, void **ptr) +{ + jclass ownerClass; + jfieldID proxyField; + jobject proxyObject; + + PR_ASSERT(env!=NULL && proxyOwner!=NULL && proxyFieldName!=NULL && + ptr!=NULL); + + /* + * Get proxy object + */ + ownerClass = (*env)->GetObjectClass(env, proxyOwner); + proxyField = (*env)->GetFieldID(env, ownerClass, proxyFieldName, + proxyFieldSig); + if(proxyField == NULL) { + return PR_FAILURE; + } + proxyObject = (*env)->GetObjectField(env, proxyOwner, proxyField); + PR_ASSERT(proxyObject != NULL); + + /* + * Get the pointer from the Native Reference object + */ + return JSS_getPtrFromProxy(env, proxyObject, ptr); +} + + +/*********************************************************************** +** +** J S S _ p t r T o B y t e A r r a y +** +** Turn a C pointer into a Java byte array. The byte array can be passed +** into a NativeProxy constructor. +** +** Returns a byte array containing the pointer, or NULL if an exception +** was thrown. +*/ +PR_IMPLEMENT( jbyteArray ) +JSS_ptrToByteArray(JNIEnv *env, void *ptr) +{ + jbyteArray byteArray; + + /* Construct byte array from the pointer */ + byteArray = (*env)->NewByteArray(env, sizeof(ptr)); + if(byteArray==NULL) { + PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); + return NULL; + } + (*env)->SetByteArrayRegion(env, byteArray, 0, sizeof(ptr), (jbyte*)&ptr); + if((*env)->ExceptionOccurred(env) != NULL) { + PR_ASSERT(PR_FALSE); + return NULL; + } + return byteArray; +} + + + +/*********************************************************************** + * + * J S S _ O c t e t S t r i n g T o B y t e A r r a y + * + * Converts a representation of an integer as a big-endian octet string + * stored in a SECItem (as used by the low-level crypto functions) to a + * representation of an integer as a big-endian Java byte array. Prepends + * a zero byte to force it to be positive. Returns NULL if an exception + * occurred. + * + */ +PR_IMPLEMENT( jbyteArray ) +JSS_OctetStringToByteArray(JNIEnv *env, SECItem *item) +{ + jbyteArray array; + jbyte *bytes; + int size; /* size of the resulting byte array */ + + PR_ASSERT(env != NULL && item->len>0); + + /* allow space for extra zero byte */ + size = item->len+1; + + array = (*env)->NewByteArray(env, size); + if(array == NULL) { + ASSERT_OUTOFMEM(env); + return NULL; + } + + bytes = (*env)->GetByteArrayElements(env, array, NULL); + if(bytes == NULL) { + ASSERT_OUTOFMEM(env); + return NULL; + } + + /* insert a 0 as the MSByte to force the string to be positive */ + bytes[0] = 0; + + /* now insert the rest of the bytes */ + memcpy(bytes+1, item->data, size-1); + + (*env)->ReleaseByteArrayElements(env, array, bytes, 0); + + return array; +} + +#define ZERO_SECITEM(item) {(item).data=NULL; (item).len=0;} + +/*********************************************************************** + * + * J S S _ B y t e A r r a y T o O c t e t S t r i n g + * + * Converts an integer represented as a big-endian Java byte array to + * an integer represented as a big-endian octet string in a SECItem. + * + * INPUTS + * byteArray + * A Java byte array containing an integer represented in + * big-endian format. Must not be NULL. + * item + * Pointer to a SECItem that will be filled with the integer + * from the byte array, in big-endian format. + * RETURNS + * PR_SUCCESS if the operation was successful, PR_FAILURE if an exception + * was thrown. + */ +PR_IMPLEMENT( PRStatus ) +JSS_ByteArrayToOctetString(JNIEnv *env, jbyteArray byteArray, SECItem *item) +{ + jbyte *bytes=NULL; + PRStatus status=PR_FAILURE; + jsize size; + + PR_ASSERT(env!=NULL && byteArray!=NULL && item!=NULL); + + ZERO_SECITEM(*item); + + size = (*env)->GetArrayLength(env, byteArray); + PR_ASSERT(size > 0); + + bytes = (*env)->GetByteArrayElements(env, byteArray, NULL); + if(bytes==NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + item->data = (unsigned char*) PR_Malloc(size); + if(item->data == NULL) { + JSS_throw(env, OUT_OF_MEMORY_ERROR); + goto finish; + } + item->len = size; + + memcpy(item->data, bytes, size); + + status = PR_SUCCESS; + +finish: + if(bytes) { + (*env)->ReleaseByteArrayElements(env, byteArray, bytes, JNI_ABORT); + } + if(status != PR_SUCCESS) { + SECITEM_FreeItem(item, PR_FALSE); + } + return status; +} + +/************************************************************************ + * + * J S S _ w i p e C h a r A r r a y + * + * Given a string, set it to all zeroes. Be a chum and don't pass in NULL. + */ +PR_IMPLEMENT( void ) +JSS_wipeCharArray(char* array) +{ + PR_ASSERT(array != NULL); + if(array == NULL) { + return; + } + + for(; *array != '\0'; array++) { + *array = '\0'; + } +} + +/*********************************************************************** + * platform-dependent definitions for getting passwords from console. + ***********************************************************************/ + +#ifdef XP_UNIX + +#include +#include +#define GETCH getchar +#define PUTCH putchar + +#else + +#include +#define GETCH _getch +#define PUTCH _putch + +#endif + +/*********************************************************************** + * g e t P W F r o m C o n s o l e + * + * Does platform-dependent stuff to retrieve a char* from the console. + * Retrieves up to the first newline character, but does not return + * the newline. Maximum length is 200 chars. + * Stars (*) are echoed to the screen. Backspacing works. + * WARNING: This function is NOT thread-safe!!! This should be OK because + * the Java method that calls it is synchronized. + * + * RETURNS + * The password in a buffer owned by the caller, or NULL if the + * user did not enter a password (just hit ). + */ +static char* getPWFromConsole() +{ + char c; + char *ret; + int i; + char buf[200]; /* no buffer overflow: we bail after 200 chars */ + int length=200; +#ifdef XP_UNIX + int fd = fileno(stdin); + struct termios save_tio; + struct termios tio; +#endif + + + /* + * In Win32, the default is for _getch to not echo and to not be buffered. + * In UNIX, we have to set this explicitly. + */ +#ifdef XP_UNIX + if ( isatty(fd) ) { + tcgetattr(fd, &save_tio); + tio = save_tio; + tio.c_lflag &= ~(ECHO|ICANON); /* no echo, non-canonical mode */ + tio.c_cc[VMIN] = 1; /* 1 char at a time */ + tio.c_cc[VTIME] = 0; /* wait forever */ + tcsetattr(fd, TCSAFLUSH, &tio); + } else { + /* no reading from a file allowed. Windows enforces this automatically*/ + return NULL; + } +#endif + + /* + * Retrieve up to length characters, or the first newline character. + */ + for(i=0; i < length-1; i++) { + PR_ASSERT(i >= 0); + c = GETCH(); + if( c == '\b' ) { + /* + * backspace. Back up the buffer and the cursor. + */ + if( i==0 ) { + /* backspace is first char, do nothing */ + i--; + } else { + /* backspace is not first char, backup one */ + i -= 2; + PUTCH('\b'); PUTCH(' '); PUTCH('\b'); + } + } else if( c == '\r' || c == '\n' ) { + /* newline, we're done */ + break; + } else { + /* normal password char. Echo an asterisk. */ + buf[i] = c; + PUTCH('*'); + } + } + buf[i] = '\0'; + PUTCH('\n'); + + /* + * Restore the saved terminal settings. + */ +#ifdef XP_UNIX + tcsetattr(fd, TCSAFLUSH, &save_tio); +#endif + + /* If password is empty, return NULL to signal the user giving up */ + if(buf[0] == '\0') { + ret = NULL; + } else { + ret = PL_strdup(buf); + } + + /* Clear the input buffer */ + memset(buf, 0, length); + + return ret; +} + + +/*********************************************************************** + * Class: com_netscape_jss_util_Password + * Method: readPasswordFromConsole + * Signature: ()Lcom/netscape/jss/util/Password; + */ +JNIEXPORT jobject JNICALL Java_com_netscape_jss_util_Password_readPasswordFromConsole + (JNIEnv *env, jclass clazz) +{ + char *pw=NULL; + int pwlen; + jclass pwClass; + jmethodID pwConstructor; + jcharArray pwCharArray=NULL; + jchar *pwChars=NULL; + jobject password=NULL; + jboolean pwIsCopy; + int i; + + /*************************************************** + * Get JNI IDs + ***************************************************/ + pwClass = (*env)->FindClass(env, PASSWORD_CLASS_NAME); + if(pwClass == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + pwConstructor = (*env)->GetMethodID(env, + pwClass, + PLAIN_CONSTRUCTOR, + PASSWORD_CONSTRUCTOR_SIG); + if(pwConstructor == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + /*************************************************** + * Get the password from the console + ***************************************************/ + pw = getPWFromConsole(); + + if(pw == NULL) { + JSS_throw(env, GIVE_UP_EXCEPTION); + goto finish; + } + pwlen = strlen(pw); + PR_ASSERT(pwlen > 0); + + /*************************************************** + * Put the password into a char array + ***************************************************/ + pwCharArray = (*env)->NewCharArray(env, pwlen); + if(pwCharArray == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + pwChars = (*env)->GetCharArrayElements(env, pwCharArray, &pwIsCopy); + if(pwChars == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + for(i=0; i < pwlen; i++) { + /* YUK! Only works for ASCII. */ + pwChars[i] = pw[i]; + } + + (*env)->ReleaseCharArrayElements(env, pwCharArray, pwChars, 0); + + /*************************************************** + * Construct a new Password from the char array + ***************************************************/ + password = (*env)->NewObject(env, pwClass, pwConstructor, pwCharArray); + if(password == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; + } + +finish: + if(pw != NULL) { + memset(pw, 0, strlen(pw)); + PR_Free(pw); + } + if(pwChars != NULL) { + PR_ASSERT(pwCharArray != NULL); + if(pwIsCopy || password==NULL) { + /* clear if it's a copy, or if we are going to clear the array */ + memset(pwChars, 0, pwlen); + } + } + return password; +} + +#ifdef DEBUG +static int debugLevel = JSS_TRACE_VERBOSE; +#else +static int debugLevel = JSS_TRACE_ERROR; +#endif + +/********************************************************************** + * + * J S S _ t r a c e + * + * Sends a trace message. + * + * INPUTS + * level + * The trace level, from com.netscape.jss.util.Debug. + * mesg + * The trace message. Must not be NULL. + */ +PR_IMPLEMENT( void ) +JSS_trace(JNIEnv *env, jint level, char *mesg) +{ + PR_ASSERT(env!=NULL && mesg!=NULL); + + if(level <= debugLevel) { + printf("%s\n", mesg); + fflush(stdout); + } +} + +/*********************************************************************** + * A S S E R T _ O U T O F M E M + * + * In most JNI calls that throw Exceptions, OutOfMemoryError is the only + * one that doesn't indicate a bug in the code. If a JNI function throws + * an exception (or returns an unexpected NULL), you can call this to + * PR_ASSERT that it is due to an OutOfMemory condition. It takes a JNIEnv*, + * which better not be NULL. + */ +PR_IMPLEMENT( void ) +JSS_assertOutOfMem(JNIEnv *env) +{ + jclass memErrClass; + jthrowable excep; + + PR_ASSERT(env != NULL); + + /* Make sure an exception has been thrown, and save it */ + excep = (*env)->ExceptionOccurred(env); + PR_ASSERT(excep != NULL); + + /* Clear the exception so we can call JNI exceptions */ + (*env)->ExceptionClear(env); + + + /* See if the thrown exception was an OutOfMemoryError */ + memErrClass = (*env)->FindClass(env, "java/lang/OutOfMemoryError"); + PR_ASSERT(memErrClass != NULL); + PR_ASSERT( (*env)->IsInstanceOf(env, excep, memErrClass) ); + + /* Re-throw the exception */ + (*env)->Throw(env, excep); +} + +/*********************************************************************** + * Debug.setNativeLevel + * + * If the debug level is changed in Java code, change it in native + * code as well. + */ +JNIEXPORT void JNICALL +Java_com_netscape_jss_util_Debug_setNativeLevel + (JNIEnv *env, jclass clazz, jint level) +{ + debugLevel = level; +} + +/*********************************************************************** + * Copies the contents of a SECItem into a new Java byte array. + * + * item + * A SECItem. Must not be NULL. + * RETURNS + * A Java byte array. NULL will be returned if an exception was + * thrown. + */ +PR_IMPLEMENT( jbyteArray ) +JSS_SECItemToByteArray(JNIEnv *env, SECItem *item) +{ + jbyteArray array=NULL; + jbyte* bytes=NULL; + + PR_ASSERT(env!=NULL && item!=NULL); + PR_ASSERT(item->len >= 0); + PR_ASSERT(item->len == 0 || item->data != NULL); + + array = (*env)->NewByteArray(env, item->len); + if( array == NULL ) { + ASSERT_OUTOFMEM(env); + goto finish; + } + + bytes = (*env)->GetByteArrayElements(env, array, NULL); + if(bytes == NULL) { + ASSERT_OUTOFMEM(env); + array = NULL; /* so the caller knows there was an error */ + goto finish; + } + + memcpy(bytes, item->data, item->len); + +finish: + if(bytes!=NULL) { + (*env)->ReleaseByteArrayElements(env, array, bytes, 0); + } + return array; +} +/*********************************************************************** + * J S S _ B y t e A r r a y T o S E C I t e m + * + * Copies the contents of a Java byte array into a new SECItem. + * + * byteArray + * A Java byte array. Must not be NULL. + * RETURNS + * A newly allocated SECItem, or NULL iff an exception was thrown. + */ +PR_IMPLEMENT( SECItem* ) +JSS_ByteArrayToSECItem(JNIEnv *env, jbyteArray byteArray) +{ + SECItem *item = NULL; + + PR_ASSERT(env!=NULL && byteArray!=NULL); + + /* Create a new SECItem */ + item = PR_NEW(SECItem); + if( item == NULL ) { + JSS_throw(env, OUT_OF_MEMORY_ERROR); + goto finish; + } + + /* Setup the length, allocate the buffer */ + item->len = (*env)->GetArrayLength(env, byteArray); + item->data = PR_Malloc(item->len); + + /* copy the bytes from the byte array into the SECItem */ + (*env)->GetByteArrayRegion(env, byteArray, 0, item->len, + (jbyte*)item->data); + if( (*env)->ExceptionOccurred(env) ) { + SECITEM_FreeItem(item, PR_TRUE /*freeit*/); + item = NULL; + } + +finish: + return item; +} diff --git a/mozilla/security/jss/org/mozilla/jss/util/jssutil.h b/mozilla/security/jss/org/mozilla/jss/util/jssutil.h new file mode 100644 index 00000000000..ac773ac99a2 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/util/jssutil.h @@ -0,0 +1,240 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +#ifndef JSS_NATIVE_UTIL_H +#define JSS_NATIVE_UTIL_H + +/* Need to include these first. + * #include + * #include + */ + +PR_BEGIN_EXTERN_C + +/**** NSPR private thread functions ****/ +/* +PR_EXTERN(PRThread*) PR_AttachThread(PRThreadType type, + PRThreadPriority priority, + PRThreadStack *stack); + +PR_EXTERN(void) PR_DetachThread(void); +*/ +#define PR_AttachThread(a, b, c) ((PRThread*)1) +#define PR_DetachThread() + + +/*********************************************************************** + * J S S _ t h r o w M s g + * + * Throw an exception in native code. You should return right after + * calling this function. + * + * throwableClassName is the name of the throwable you are throwing in + * JNI class name format (xxx/xx/xxx/xxx). It must not be NULL. + * + * message is the message parameter of the throwable. It must not be NULL. + * If you don't have a message, call JSS_nativeThrow. + * + * Example: + * JSS_nativeThrowMsg(env, "java/lang/IllegalArgumentException", + * "Bogus argument, you ninny"); + * return -1; + */ +PR_EXTERN( void ) +JSS_throwMsg(JNIEnv *env, char *throwableClassName, char *message); + +#define JSS_nativeThrowMsg JSS_throwMsg + + +/*********************************************************************** + * J S S _ t h r o w + * + * Throw an exception in native code. You should return right after + * calling this function. + * + * throwableClassName is the name of the throwable you are throwing in + * JNI class name format (xxx/xx/xxx/xxx). It must not be NULL. + * + * Example: + * JSS_nativeThrow(env, "java/lang/IllegalArgumentException"); + * return -1; + */ +PR_EXTERN( void ) +JSS_throw(JNIEnv *env, char *throwableClassName); + +#define JSS_nativeThrow JSS_throw + +/*********************************************************************** + * A S S E R T _ O U T O F M E M + * + * In most JNI calls that throw Exceptions, OutOfMemoryError is the only + * one that doesn't indicate a bug in the code. If a JNI function throws + * an exception (or returns an unexpected NULL), you can call this to + * PR_ASSERT that it is due to an OutOfMemory condition. It takes a JNIEnv*, + * which better not be NULL. + */ +PR_EXTERN( void ) +JSS_assertOutOfMem(JNIEnv *env); + +#ifdef DEBUG +#define ASSERT_OUTOFMEM(env) JSS_assertOutOfMem(env) +#else +#define ASSERT_OUTOFMEM(env) +#endif + +/*********************************************************************** +** +** J S S _ g e t P t r F r o m P r o x y +** +** Given a NativeProxy, extract the pointer and store it at the given +** address. +** +** nativeProxy: a JNI reference to a NativeProxy. +** ptr: address of a void* that will receive the pointer extracted from +** the NativeProxy. +** Returns: PR_SUCCESS on success, PR_FAILURE if an exception was thrown. +** +** Example: +** DataStructure *recovered; +** jobject proxy; +** JNIEnv *env; +** [...] +** if(JSS_getPtrFromProxy(env, proxy, (void**)&recovered) != PR_SUCCESS) { +** return; // exception was thrown! +** } +*/ +PR_EXTERN( PRStatus ) +JSS_getPtrFromProxy(JNIEnv *env, jobject nativeProxy, void **ptr); + +/*********************************************************************** +** +** J S S _ g e t P t r F r o m P r o x y O w n e r +** +** Given an object which contains a NativeProxy, extract the pointer +** from the NativeProxy and store it at the given address. +** +** proxyOwner: an object which contains a NativeProxy member. +** proxyFieldName: the name of the NativeProxy member. +** proxyFieldSig: the signature of the NativeProxy member. +** ptr: address of a void* that will receive the extract pointer. +** Returns: PR_SUCCESS for success, PR_FAILURE if an exception was thrown. +** +** Example: +** +** public class Owner { +** protected MyProxy myProxy; +** [...] +** } +** +** +** DataStructure *recovered; +** jobject owner; +** JNIEnv *env; +** [...] +** if(JSS_getPtrFromProxyOwner(env, owner, "myProxy", (void**)&recovered) +** != PR_SUCCESS) { +** return; // exception was thrown! +** } +*/ +PR_EXTERN( PRStatus ) +JSS_getPtrFromProxyOwner(JNIEnv *env, jobject proxyOwner, char* proxyFieldName, + char *proxyFieldSig, void **ptr); + +/* + * Turn a C pointer into a Java byte array. The byte array can be passed + * into a NativeProxy constructor. + * + * Returns a byte array containing the pointer, or NULL if an exception + * was thrown. + */ +PR_EXTERN( jbyteArray ) +JSS_ptrToByteArray(JNIEnv *env, void *ptr); + +/************************************************************************ + * + * J S S _ w i p e C h a r A r r a y + * + * Given a string, set it to all zeroes. Don't pass in NULL. + */ +PR_EXTERN( void ) +JSS_wipeCharArray(char* array); + +/********************************************************************** + * + * J S S _ t r a c e + * + * Sends a trace message. + * + * INPUTS + * level + * The trace level (see below for constants). Must be > 0. + * mesg + * The trace message. Must not be NULL. + */ +PR_EXTERN( void ) +JSS_trace(JNIEnv *env, jint level, char *mesg); + +/* trace levels */ +#define JSS_TRACE_ERROR 1 +#define JSS_TRACE_VERBOSE 5 +#define JSS_TRACE_OBNOXIOUS 10 + +/*********************************************************************** + * J S S _ S E C I t e m T o B y t e A r r a y + * + * Copies the contents of a SECItem into a new Java byte array. + * + * item + * A SECItem. Must not be NULL. + * RETURNS + * A Java byte array. NULL will be returned if an exception was + * thrown. + */ +PR_EXTERN( jbyteArray ) +JSS_SECItemToByteArray(JNIEnv *env, SECItem *item); + +/*********************************************************************** + * J S S _ B y t e A r r a y T o S E C I t e m + * + * Copies the contents of a Java byte array into a new SECItem. + * + * byteArray + * A Java byte array. Must not be NULL. + * RETURNS + * A newly allocated SECItem, or NULL iff an exception was thrown. + */ +PR_EXTERN( SECItem* ) +JSS_ByteArrayToSECItem(JNIEnv *env, jbyteArray byteArray); + +PR_END_EXTERN_C + +#endif diff --git a/mozilla/security/jss/org/mozilla/jss/util/manifest.mn b/mozilla/security/jss/org/mozilla/jss/util/manifest.mn new file mode 100644 index 00000000000..a817cf6838d --- /dev/null +++ b/mozilla/security/jss/org/mozilla/jss/util/manifest.mn @@ -0,0 +1,96 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +CORE_DEPTH = ../../../../.. + +MODULE = ninja + +NS_USE_JDK = 1 + +REQUIRES = nspr20 dbm security + +PACKAGE = com/netscape/jss/util + +PRIVATE_EXPORTS = jssutil.h \ + jss_exceptions.h \ + java_ids.h \ + jss_bigint.h \ + $(NULL) + +JNI_GEN = \ + com.netscape.jss.util.Debug \ + com.netscape.jss.util.Password \ + $(NULL) + +JSRCS = \ + Assert.java \ + AssertionException.java \ + Base64OutputStream.java \ + ConsolePasswordCallback.java \ + Debug.java \ + IncorrectPasswordException.java \ + InvalidDERException.java \ + InvalidNicknameException.java \ + NativeProxy.java \ + NotImplementedException.java \ + NullPasswordCallback.java \ + ObjectNotFoundException.java \ + Password.java \ + PasswordCallback.java \ + PasswordCallbackInfo.java \ + Tunnel.java \ + UTF8Converter.java \ + $(NULL) + +CLASSES = \ + Assert \ + AssertionException \ + Base64OutputStream \ + ConsolePasswordCallback \ + Debug \ + IncorrectPasswordException \ + InvalidNicknameException \ + NativeProxy \ + NotImplementedException \ + NullPasswordCallback \ + Password \ + PasswordCallback \ + PasswordCallbackInfo \ + Tunnel \ + UTF8Converter \ + $(NULL) + +CSRCS = jssutil.c \ + $(NULL) + +LIBRARY_NAME = jssutil diff --git a/mozilla/security/jss/org/mozilla/manifest.mn b/mozilla/security/jss/org/mozilla/manifest.mn new file mode 100644 index 00000000000..42ef4d8dc60 --- /dev/null +++ b/mozilla/security/jss/org/mozilla/manifest.mn @@ -0,0 +1,40 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +CORE_DEPTH = ../../.. + +MODULE = ninja + +DIRS = jss \ + $(NULL) + diff --git a/mozilla/security/jss/samples/DeleteKeys.java b/mozilla/security/jss/samples/DeleteKeys.java new file mode 100644 index 00000000000..2bc494b3159 --- /dev/null +++ b/mozilla/security/jss/samples/DeleteKeys.java @@ -0,0 +1,115 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + + +/** This class will delete all the private keys from your + * Key3.db - please make sure you know what you are doing + * before you run this. + */ + +import com.netscape.jss.CryptoManager; +import com.netscape.jss.util.ConsolePasswordCallback; +import com.netscape.jss.util.Debug; +import com.netscape.jss.crypto.*; +import java.math.BigInteger; + +public class DeleteKeys { + + public static void main(String args[]) { + int i; + if(args.length!=1) { + System.out.println("Usage: java DeleteKeys "); + return; + } + + try { + + CryptoManager.InitializationValues vals = + new CryptoManager.InitializationValues( + args[0]+"/secmodule.db", + args[0]+"/key3.db", + args[0]+"/cert7.db"); + CryptoManager.initialize(vals); + CryptoManager manager = CryptoManager.getInstance(); + CryptoStore store; + + CryptoToken token = manager.getInternalKeyStorageToken(); + + // Generate a few keys + KeyPairGenerator gen = + token.getKeyPairGenerator(KeyPairAlgorithm.RSA); + gen.initialize(512); + gen.genKeyPair(); + gen.genKeyPair(); + + + store = token.getCryptoStore(); + PrivateKey[] keys = store.getPrivateKeys(); + System.out.println(keys.length+" Keys:"); + for(i=0; i < keys.length; i++) { + PrivateKey key = (PrivateKey)keys[i]; + byte[] keyID = key.getUniqueID(); + if(keyID.length!=20) { + System.out.println("ERROR: keyID length != 20"); + } + BigInteger bigint = new BigInteger(keyID); + System.out.println("UniqueID: "+ bigint); + } + + System.out.println("Now we shall delete all the keys!"+ + " Hope you backed up..."); + keys = store.getPrivateKeys(); + for(i=0; i < keys.length; i ++) { + PrivateKey key = (PrivateKey)keys[i]; + store.deletePrivateKey(key); + } + + System.out.println("Now here's all the keys:"); + keys = store.getPrivateKeys(); + for(i=0; i < keys.length; i ++) { + PrivateKey key = (PrivateKey)keys[i]; + byte[] keyID = key.getUniqueID(); + if(keyID.length!=20) { + System.out.println("ERROR: keyID length != 20"); + } + BigInteger bigint = new BigInteger(keyID); + System.out.println("UniqueID: "+ bigint); + } + + System.out.println("done."); + + } catch( Exception e) { + e.printStackTrace(); + } + } +} diff --git a/mozilla/security/jss/samples/Makefile b/mozilla/security/jss/samples/Makefile new file mode 100644 index 00000000000..eed9ae10c82 --- /dev/null +++ b/mozilla/security/jss/samples/Makefile @@ -0,0 +1,98 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Security Services for Java. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +# edit CLASSPATH to point to the rt.jar from your JDK 1.2 installation + +CLASSPATH = .:../../dist/classes_DBG:/share/builds/components/jdk/1.2.2_05a/SunOS/jre/lib/rt.jar + +JAVAC = javac -g -classpath $(CLASSPATH) + +#JRE = java -Djava.compiler=NONE -classpath $(CLASSPATH) +JRE = java -Djava.compiler=NONE -classpath $(CLASSPATH) + + +#define implicit rule for making classes from java +%.class : %.java + $(JAVAC) $< + + +all : \ + TestCryptoStore.class \ + TestKeyGen.class \ + TokenAccessTest.class \ + TestCertImport.class \ + SigTest.class \ + PQGGen.class \ + DeleteKeys.class \ + SSLClient.class \ + SSLServer.class \ + TestCRLImport.class \ + pkcs12.class + + +TestCryptoStore : TestCryptoStore.class + $(JRE) $@ . "TestCryptoStore Key Token" + +TestKeyGen : TestKeyGen.class + $(JRE) $@ . + +pkcs12: pkcs12.class + $(JRE) $@ . inputfile.pfx outputfile.pfx + +TokenAccessTest : TokenAccessTest.class + $(JRE) $@ . + +TestCertImport: TestCertImport.class + $(JRE) $@ . certtest + +SigTest : SigTest.class + $(JRE) $@ . "Internal Key Storage Token" + +PQGGen : PQGGen.class + $(JRE) $@ 512 + +DeleteKeys: DeleteKeys.class + $(JRE) $@ . + +SSLClient : SSLClient.class + $(JRE) $@ hostname=level port=444 ocsp_on=on + #$(JRE) $@ hostname=level port=444 ocsp_on=on ocsp_url=http://level:1025/ocsp ocsp_nickname=ocsp + +SSLServer : SSLServer.class + $(JRE) $@ + +TestCRLImport : TestCRLImport.class + $(JRE) $@ . crl.der + + + diff --git a/mozilla/security/jss/samples/PQGGen.java b/mozilla/security/jss/samples/PQGGen.java new file mode 100644 index 00000000000..a2a25eca2ac --- /dev/null +++ b/mozilla/security/jss/samples/PQGGen.java @@ -0,0 +1,88 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + + +import com.netscape.jss.*; +import com.netscape.jss.crypto.*; + +/** + * A command-line utility for generating PQG parameters for DSA + * Key operations. Can be used for testing. + * Takes the keysize as the sole argument. + */ +public class PQGGen { + public static void main(String args[]) { + int size; + PQGParams pqg; + + try { + + if(args.length != 1) { + throw new Exception("Usage: java PQGGen "); + } + + size = Integer.parseInt(args[0]); + + System.out.println("Generating PQG parameters for "+size+ + "-bit keypairs. This could take hours..."); + + CryptoManager.initialize(); + + pqg = PQGParams.generate(size); + + System.out.println("Generated PQG Parameters."); + System.out.println("Verifying PQG Parameters. "+ + "This could take a few minutes..."); + if( ! pqg.paramsAreValid() ) { + throw new Exception("ERROR: Generated parameters are invalid."); + } + + System.out.println("Parameters are valid!"); + System.out.println("P: "+pqg.getP()); + System.out.println("Q: "+pqg.getQ()); + System.out.println("G: "+pqg.getG()); + System.out.println("H: "+pqg.getH()); + System.out.println("seed: "+pqg.getSeed()); + System.out.println("counter: "+pqg.getCounter()); + + } catch(NumberFormatException e) { + System.err.println("Invalid key size: "+e); + } catch(PQGParamGenException e) { + System.err.println(e); + } catch(java.security.InvalidParameterException e) { + System.err.println("Invalid key size: "+e); + } catch(Exception e) { + System.err.println(e); + } + } +} diff --git a/mozilla/security/jss/samples/SSLClient.java b/mozilla/security/jss/samples/SSLClient.java new file mode 100644 index 00000000000..cabff2c33c0 --- /dev/null +++ b/mozilla/security/jss/samples/SSLClient.java @@ -0,0 +1,495 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +// This demonstrates the SSL client-side support +// + +import com.netscape.jss.ssl.*; + +import java.io.*; +import java.util.*; +import java.net.*; +import com.netscape.jss.*; +import com.netscape.jss.crypto.AlreadyInitializedException; + +/** + * Parameters supported by this socket test: + * SSLClient + * + * + */ + +public class SSLClient implements + SSLCertificateApprovalCallback, SSLClientCertificateSelectionCallback +{ + boolean handshakeEventHappened = false; + boolean doClientAuth = false; + PrintStream results; + + Hashtable args; // command line arguments are store here + + public static Hashtable initArgs() { + Hashtable args = new Hashtable(); + + args.put("hostname","localhost"); + args.put("port","10443"); + return args; + } + + public String getArgument(String key) { + return (String)args.get(key); + } + + + + public void run() + { + try { + SSLHandshakeCompletedListener listener = null; + + SSLSocket s; + String hostname; + int port; + + String msg = "GET /index.html"; + + String portstr = getArgument("port"); + if (portstr == null) { + port = 443; + } + else { + port = Integer.valueOf(portstr).intValue(); + } + + /* the argument 'cert' specifies the nickname of + a client-auth-cert to use if asked by the server */ + + String nickname = getArgument("cert"); + + hostname = getArgument("hostname"); + + results.println("Connecting to " + hostname + + " on port " + port ); + + s = new SSLSocket(InetAddress.getByName(hostname), + port, + null, /* local addr */ + 0, /* local port */ + true, /* stream */ + this, /* approvalCallback */ + this /* certSelectionCallback */ + ); + + results.println("Connected."); + + // If you pass null for the certSelectionCallback argument + // above, you can provide the name of the client-auth- + // cert ahead of time, by using the setClientCertNickname + // API + // select the cert for client auth + + // s.setClientCertNickname("cert"); + + + // Setup a handshake callback. This listener will get invoked + // When the SSL handshake is completed on this socket. + + listener = new ClientHandshakeCB(this); + s.addHandshakeCompletedListener(listener); + + OutputStream o = s.getOutputStream(); + PrintOutputStreamWriter out = new PrintOutputStreamWriter(o); + + results.println("Sending: " + msg + " to " + hostname + + ", " + port ); + + // send HTTP GET message across SSL connection + out.println(msg + "\r"); + + InputStream in = s.getInputStream(); + byte[] bytes = new byte[4096]; + int totalBytes = 0; + int numReads = 0; + String lastBytes = null; + + + // now try to read data back from the SSL connection + try { + for(;;) { + results.println("Calling Read."); + int n = in.read(bytes, 0, bytes.length); + if(n == -1) { + results.println("EOF found."); + break; + } + + if (n == 0) { + results.println("Zero bytes read?"); + break; + } + numReads++; + + if(totalBytes == 0) { + // don't print forever... + String data = new String(bytes, 0, 30, "8859_1"); + results.println("Read " + n + " bytes of data"); + results.println("First 30 bytes: " + escapeHTML(data)); + } + + totalBytes += n; + lastBytes = new String(bytes, n-31, 30, "8859_1"); + } + } catch (IOException e) { + results.println("IOException while reading from pipe? "+ + "Actually got "+ totalBytes + " bytes total"); + e.printStackTrace(results); + results.println(""); + throw e; + } finally { + results.println("Last 30 bytes: " + lastBytes); + results.println("Number of read() calls: " + numReads ); + results.println("\nDiagnostics"); + + + results.println("Total bytes read: " + totalBytes ); + results.println("Security status of session:"); + SSLSecurityStatus status = s.getStatus(); + results.println(status.toString()); + + } + + // Got here, so no exception thrown above. + // Try to clean up. + o.close(); + o = null; + in.close(); + in = null; + if (listener != null) { + s.removeHandshakeCompletedListener(listener); + listener = null; + } + s.close(); + s = null; + + } catch(Exception e) { + results.println("***** TEST FAILED *****"); + e.printStackTrace(results); + } + + results.println("END OF TEST"); + } + + /** + * given an input string, convert less-than, greater-than, and ampersand + * from raw characters to escaped characters + * (< becomes `&lt;', etc.) + */ + private String escapeHTML(String s) + { + StringBuffer result = new StringBuffer(); + + for(int i=0; i': result.append(">"); break; + case '&': result.append("&"); break; + default: result.append(c); break; + } + } + + return result.toString(); + } + + +/* CONSTRUCTOR */ + + public SSLClient( PrintStream ps, String verStr, Hashtable myargs) + throws Exception + { + + this.args = myargs; + this.results = ps; + int i; + + String ocsp = (String)myargs.get("ocsp_on"); + boolean ocsp_on = false; + if (ocsp != null) { + if (ocsp.equals("on") ) { + ocsp_on = true; + } + else if (ocsp.equals("off")) { + ocsp_on = false; + } + else { + throw new Exception("Error: invalid argument '"+ + ocsp+ "' must be 'on' or 'off'"); + } + } + + + try { + CryptoManager.InitializationValues vals = + new CryptoManager.InitializationValues + ("secmod.db", "key3.db", "cert7.db"); + vals.ocspCheckingEnabled = ocsp_on; + vals.ocspResponderURL = (String)myargs.get("ocsp_url"); + vals.ocspResponderCertNickname = (String)myargs.get( + "ocsp_nickname"); + CryptoManager.initialize(vals); + } + catch (KeyDatabaseException kdbe) { + System.out.println("Couldn't open the key database"); + return; + } + catch (CertDatabaseException cdbe) { + System.out.println("Couldn't open the certificate database"); + return; + } + catch (AlreadyInitializedException aie) { + System.out.println("CryptoManager already initialized???"); + return; + } + + /* enable all the SSL2 cipher suites */ + for (i = SSLSocket.SSL2_RC4_128_WITH_MD5; + i <= SSLSocket.SSL2_DES_192_EDE3_CBC_WITH_MD5; ++i) { + SSLSocket.setCipherPreference( i, true); + } + + /* enable all the SSL3 cipher suites */ + for (i = 0; cipherSuites[i] != 0; ++i) { + SSLSocket.setCipherPreference( cipherSuites[i], true); + } + } + + static final int cipherSuites[] = { + SSLSocket.SSL3_RSA_WITH_RC4_128_MD5, + SSLSocket.SSL3_RSA_WITH_3DES_EDE_CBC_SHA, + SSLSocket.SSL3_RSA_WITH_DES_CBC_SHA, + SSLSocket.SSL3_RSA_EXPORT_WITH_RC4_40_MD5, + SSLSocket.SSL3_RSA_EXPORT_WITH_RC2_CBC_40_MD5, + SSLSocket.SSL3_RSA_WITH_NULL_MD5, + 0 + }; + + public static void main(String argv[]) + { + + Hashtable myargs = initArgs(); + int i; + + for (i=0;i 0) { + msg = new String(bytes, 0, totalBytes, "8859_1"); + results.println("Request received:"); + results.println(msg); + results.println(""); + } + + + SSLSecurityStatus status = s.getStatus(); + results.println("Security status of session:"); + results.println(status.toString()); + + results.println("Handshake callback event happened: " + + ((handshakeEventHappened) ? okay : failed)); + + OutputStream os = s.getOutputStream(); + PrintOutputStreamWriter out = new PrintOutputStreamWriter(os); + os = null; // don't keep this reference lying around + + String reply = "HTTP/1.0 200 OK\r\n" + + "Server: Netscape-Enterprise/2.0a\r\n" + + "Date: Tue, 01 Apr 1998 22:10:05 GMT\r\n" + + "Content-type: text/plain\r\n" + + "\r\n" + + msg; + out.println(reply); + + // Got here, so no exception thrown above. + // Try to clean up. + in.close(); + in = null; + + if (listener != null) { + s.removeHandshakeCompletedListener(listener); + listener = null; + } + + out.close(); + out = null; + + s.close(); + s = null; + } + + /** + * given an input string, convert less-than, greater-than, and ampersand + * from raw characters to escaped characters + * (< becomes `&lt;', etc.) + */ + private String escapeHTML(String s) + { + StringBuffer result = new StringBuffer(); + + // this is inefficient, but I don't care + for(int i=0; i': result.append(">"); break; + case '&': result.append("&"); break; + default: result.append(c); break; + } + } + + return result.toString(); + } + + public SSLServer( PrintStream ps, String verStr) + { + this.args = new Hashtable(); + this.results = ps; + this.versionStr = verStr; + + for(int i=0; i "); + } + + public static void main(String args[]) { + CryptoToken token; + CryptoManager manager; + byte[] data = new byte[] {1,2,3,4,5,6,7,8,9}; + byte[] signature; + Signature signer; + PublicKey pubk; + KeyPairGenerator kpgen; + KeyPair keyPair; + + if(args.length != 2) { + usage(); + return; + } + String dbdir = args[0]; + String tokenname = args[1]; + + try { + CryptoManager.InitializationValues vals = new + CryptoManager.InitializationValues + ( args[0]+"/secmod.db", + args[0]+"/key3.db", + args[0]+"/cert7.db" ); + CryptoManager.initialize(vals); + manager = CryptoManager.getInstance(); + + /* Print out list of available tokens */ + Enumeration en = manager.getAllTokens(); + System.out.println("Available tokens:"); + while (en.hasMoreElements()) { + PK11Token p = (PK11Token)en.nextElement(); + System.out.println(" token : "+p.getName()); + } + + token = manager.getTokenByName(tokenname); + + // Generate an RSA keypair + kpgen = token.getKeyPairGenerator(KeyPairAlgorithm.RSA); + kpgen.initialize(1024); + keyPair = kpgen.genKeyPair(); + + // RSA MD5 + signer = token.getSignatureContext( + SignatureAlgorithm.RSASignatureWithMD5Digest); + System.out.println("Created a signing context"); + signer.initSign( + (com.netscape.jss.crypto.PrivateKey)keyPair.getPrivate()); + System.out.println("initialized the signing operation"); + + signer.update(data); + System.out.println("updated signature with data"); + signature = signer.sign(); + System.out.println("Successfully signed!"); + + signer.initVerify(keyPair.getPublic()); + System.out.println("initialized verification"); + signer.update(data); + System.out.println("updated verification with data"); + if( signer.verify(signature) ) { + System.out.println("Signature Verified Successfully!"); + } else { + System.out.println("ERROR: Signature failed to verify."); + } + + } catch(Exception e) { + e.printStackTrace(); + } + } +} diff --git a/mozilla/security/jss/samples/TestCRLImport.java b/mozilla/security/jss/samples/TestCRLImport.java new file mode 100644 index 00000000000..cda29277cdb --- /dev/null +++ b/mozilla/security/jss/samples/TestCRLImport.java @@ -0,0 +1,78 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +/* usage: + java TestCertImport [] + + - importfile is the DER encoded binary CRL + */ + +import com.netscape.jss.*; + +import java.io.FileInputStream; +import com.netscape.jss.util.ConsolePasswordCallback; +import com.netscape.jss.crypto.*; +import com.netscape.jss.util.Assert; + +public class TestCRLImport { + + public static void main(String args[]) { + String url = null; + if(args.length == 3) { + url = args[2]; + } else if(args.length != 2) { + System.out.println("Usage: java TestCRLImport" + +" []"); + return; + } + + try { + CryptoManager.InitializationValues vals = + new CryptoManager.InitializationValues( args[0]+"/secmodule.db", + args[0]+"/key3.db", + args[0]+"/cert7.db"); + CryptoManager.initialize(vals); + CryptoManager manager = CryptoManager.getInstance(); + + FileInputStream fin = new FileInputStream( args[1] ); + byte[] pkg = new byte[fin.available()]; + + fin.read(pkg); + + manager.importCRL(pkg, url); + + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/mozilla/security/jss/samples/TestCertImport.java b/mozilla/security/jss/samples/TestCertImport.java new file mode 100644 index 00000000000..36446949a59 --- /dev/null +++ b/mozilla/security/jss/samples/TestCertImport.java @@ -0,0 +1,90 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +/* usage: + java TestCertImport [] + + - importfile is the base-64 encoded certificate + - nickname is an optional to refer to the certificate. + [if not specified, one is created] + */ + +import com.netscape.jss.*; + +import java.io.FileInputStream; +import com.netscape.jss.util.ConsolePasswordCallback; +import com.netscape.jss.crypto.*; +import com.netscape.jss.util.Assert; + +public class TestCertImport { + + public static void main(String args[]) { + String password = null; + if(args.length == 3) { + password = args[2]; + } else if(args.length != 2) { + System.out.println("Usage: java TestCertImport" + +" []"); + return; + } + + try { + CryptoManager.InitializationValues vals = + new CryptoManager.InitializationValues( args[0]+"/secmodule.db", + args[0]+"/key3.db", + args[0]+"/cert7.db"); + CryptoManager.initialize(vals); + CryptoManager manager = CryptoManager.getInstance(); + + FileInputStream fin = new FileInputStream( args[1] ); + byte[] pkg = new byte[fin.available()]; + + fin.read(pkg); + + X509Certificate cert = manager.importCertPackage(pkg, password); + + if(cert instanceof TokenCertificate) { + System.out.println("Imported user cert!"); + } else { + Assert.assert( cert instanceof InternalCertificate ); + System.out.println("Imported CA cert chain. Setting trust bits."); + ((InternalCertificate)cert).setSSLTrust( + InternalCertificate.VALID_CA | + InternalCertificate.TRUSTED_CA); + } + + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/mozilla/security/jss/samples/TestCryptoStore.java b/mozilla/security/jss/samples/TestCryptoStore.java new file mode 100644 index 00000000000..309ae665081 --- /dev/null +++ b/mozilla/security/jss/samples/TestCryptoStore.java @@ -0,0 +1,152 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +import com.netscape.jss.CryptoManager; +import com.netscape.jss.util.ConsolePasswordCallback; +import com.netscape.jss.util.Debug; +import com.netscape.jss.crypto.*; +import java.math.BigInteger; + +public class TestCryptoStore { + + public static void main(String args[]) { + int i; + if(args.length!=2) { + System.out.println("Usage: jre TestCryptoStore "); + return; + } + + try { + + CryptoManager.InitializationValues vals = new + CryptoManager.InitializationValues( args[0]+"/secmodule.db", + args[0]+"/key3.db", + args[0]+"/cert7.db" ); + try { + vals.setInternalTokenDescription + ("TestCryptoStore Internal Token "); // too long + System.out.println("ERROR: accepted invalid token description"); + return; + } catch(CryptoManager.InvalidLengthException e) { + } + vals.setInternalKeyStorageTokenDescription + ("TestCryptoStore Key Token "); + vals.setInternalSlotDescription +("TestCryptoStore Internal Slot Description "); + CryptoManager.initialize(vals); + CryptoManager manager = CryptoManager.getInstance(); + CryptoStore store; + + System.out.println("Opening token : "+args[1]); + CryptoToken token = manager.getTokenByName(args[1]); + + store = token.getCryptoStore(); + PrivateKey[] keys = store.getPrivateKeys(); + System.out.println("Keys:"); + for(i=0; i < keys.length; i++) { + PrivateKey key = (PrivateKey)keys[i]; + byte[] keyID = key.getUniqueID(); + if(keyID.length!=20) { + System.out.println("ERROR: keyID length != 20"); + } + BigInteger bigint = new BigInteger(keyID); + System.out.println("UniqueID: "+ bigint); + } + + X509Certificate[] certs = store.getCertificates(); + System.out.println("\n====================\nCerts:"); + for(i=0; i < certs.length; i++) { + X509Certificate cert = (X509Certificate)certs[i]; + System.out.println("Name: "+cert.getNickname()); + System.out.println("Subject: "+cert.getSubjectDN()); + System.out.println("Issuer: "+cert.getIssuerDN()); + System.out.println("Serial Number: "+cert.getSerialNumber()); + System.out.println("Version: "+cert.getVersion()); + + if(cert instanceof TokenCertificate) { + TokenCertificate tcert = (TokenCertificate)cert; + byte[] id = tcert.getUniqueID(); + if(id.length != 20) { + System.out.println("ERROR: cert ID length != 20"); + } + BigInteger bigint = new BigInteger(id); + System.out.println("UniqueID: "+bigint); + } + + if(cert instanceof InternalCertificate) { + InternalCertificate icert = (InternalCertificate)cert; + System.out.println("SSL Trust bitmask: "+icert.getSSLTrust()); + System.out.println("Email Trust bitmask: "+icert.getEmailTrust()); + System.out.println("ObjSign Trust bitmask: "+icert.getObjectSigningTrust()); + } + System.out.println(); + } + + certs = manager.getCACerts(); + System.out.println("\n====================\nCA Certs:"); + for(i=0; i < certs.length; i++) { + X509Certificate cert = (X509Certificate)certs[i]; + System.out.println("Name: "+cert.getNickname()); + System.out.println("Subject: "+cert.getSubjectDN()); + System.out.println("Issuer: "+cert.getIssuerDN()); + System.out.println("Serial Number: "+cert.getSerialNumber()); + System.out.println("Version: "+cert.getVersion()); + + if(cert instanceof TokenCertificate) { + TokenCertificate tcert = (TokenCertificate)cert; + byte[] id = tcert.getUniqueID(); + if(id.length != 20) { + System.out.println("ERROR: cert ID length != 20"); + } + BigInteger bigint = new BigInteger(id); + System.out.println("UniqueID: "+bigint); + } + + + if(cert instanceof InternalCertificate) { + InternalCertificate icert = (InternalCertificate)cert; + System.out.println("SSL Trust: "+icert.getSSLTrust()); + System.out.println("Email Trust: "+icert.getEmailTrust()); + System.out.println("OS Trust: "+icert.getObjectSigningTrust()); + } + System.out.println(); + } + + System.out.println("done."); + + } catch( Exception e) { + e.printStackTrace(); + } + } + +} diff --git a/mozilla/security/jss/samples/TestKeyGen.java b/mozilla/security/jss/samples/TestKeyGen.java new file mode 100644 index 00000000000..9e8564cc080 --- /dev/null +++ b/mozilla/security/jss/samples/TestKeyGen.java @@ -0,0 +1,167 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +/* This file demonstrates the use of JSS api to generate RSA and + * DSA keys. The key pairs are stored in key3.db + */ + +/** + * Note: when this program is run, it must have a key3.db WITH A PASSWORD + * SET in the directory specified by the argument. The first time the + * program is run, a key3.db file will be created, but it will not have + * a password. This will result in the error: + * Token error: com.netscape.jss.crypto.TokenException: unable to login to token + * + * To create a database with a password, you can: + * use the modutil or keyutil tool, + * use the JSS API CryptoToken.changePassword() to set the password + * run the test 'TokenAccessTest' + * which will create db with the password 'netscape'. + */ + + +import com.netscape.jss.pkcs11.*; + +import com.netscape.jss.util.*; +import com.netscape.jss.crypto.*; +import com.netscape.jss.*; +import java.io.*; +import java.awt.*; +import java.security.cert.*; +import java.security.interfaces.*; +import java.math.BigInteger; + +public class TestKeyGen { + + public static void main(String[] args) throws Throwable { + CryptoToken token; + CryptoManager manager; + KeyPairGenerator keyPairGenerator; + java.security.KeyPair keyPair; + Base64OutputStream base64; + + if(args.length != 1) { + System.err.println( + "Usage: java com.netscape.jss.pkcs11.TestKeyGen "); + return; + } + + CryptoManager.InitializationValues vals = new + CryptoManager.InitializationValues( + args[0]+"/secmodule.db", + args[0]+"/key3.db", + args[0]+"/cert7.db" ); + CryptoManager.initialize(vals); + manager = CryptoManager.getInstance(); + + java.util.Enumeration tokens = + manager.getTokensSupportingAlgorithm(KeyPairAlgorithm.RSA); + System.out.println("The following tokens support RSA keygen:"); + while(tokens.hasMoreElements()) { + System.out.println("\t"+ + ((CryptoToken)tokens.nextElement()).getName() ); + } + tokens = manager.getTokensSupportingAlgorithm(KeyPairAlgorithm.DSA); + System.out.println("The following tokens support DSA keygen:"); + while(tokens.hasMoreElements()) { + System.out.println("\t"+ + ((CryptoToken)tokens.nextElement()).getName() ); + } + + try { + RSAPublicKey rsaPubKey; + DSAPublicKey dsaPubKey; + DSAParams dsaParams; + RSAParameterSpec rsaParams; + + token = manager.getInternalKeyStorageToken(); + keyPairGenerator = token.getKeyPairGenerator(KeyPairAlgorithm.RSA); + + // 512-bit RSA with default exponent + keyPairGenerator.initialize(512); + keyPair = keyPairGenerator.genKeyPair(); + Assert.assert( keyPair.getPublic() instanceof RSAPublicKey); + rsaPubKey = (RSAPublicKey) keyPair.getPublic(); + System.out.println("Generated 512-bit RSA KeyPair!"); + System.out.println("Modulus: "+rsaPubKey.getModulus()); + System.out.println("Exponent: "+rsaPubKey.getPublicExponent()); + + // 1024-bit RSA with default exponent + keyPairGenerator.initialize(1024); + keyPair = keyPairGenerator.genKeyPair(); + Assert.assert( keyPair.getPublic() instanceof RSAPublicKey); + rsaPubKey = (RSAPublicKey) keyPair.getPublic(); + System.out.println("Generated 1024-bit RSA KeyPair!"); + System.out.println("Modulus: "+rsaPubKey.getModulus()); + System.out.println("Exponent: "+rsaPubKey.getPublicExponent()); + + // 512-bit RSA with exponent = 3 + rsaParams = new RSAParameterSpec(512, BigInteger.valueOf(3)); + keyPairGenerator.initialize(rsaParams); + keyPair = keyPairGenerator.genKeyPair(); + Assert.assert( keyPair.getPublic() instanceof RSAPublicKey); + rsaPubKey = (RSAPublicKey) keyPair.getPublic(); + System.out.println("Generated 512-bit RSA KeyPair with public exponent=3!"); + System.out.println("Modulus: "+rsaPubKey.getModulus()); + System.out.println("Exponent: "+rsaPubKey.getPublicExponent()); + + // 512-bit DSA + keyPairGenerator = token.getKeyPairGenerator(KeyPairAlgorithm.DSA); + keyPairGenerator.initialize(512); + keyPair = keyPairGenerator.genKeyPair(); + Assert.assert( keyPair.getPublic() instanceof DSAPublicKey); + dsaPubKey = (DSAPublicKey) keyPair.getPublic(); + System.out.println("Generated 512-bit DSA KeyPair!"); + dsaParams = dsaPubKey.getParams(); + System.out.println("P: "+dsaParams.getP()); + System.out.println("Q: "+dsaParams.getQ()); + System.out.println("G: "+dsaParams.getG()); + System.out.println("Y: "+dsaPubKey.getY()); + + // 1024-bit DSA + keyPairGenerator.initialize(1024); + keyPair = keyPairGenerator.genKeyPair(); + Assert.assert( keyPair.getPublic() instanceof DSAPublicKey); + dsaPubKey = (DSAPublicKey) keyPair.getPublic(); + System.out.println("Generated 1024-bit DSA KeyPair!"); + dsaParams = dsaPubKey.getParams(); + System.out.println("P: "+dsaParams.getP()); + System.out.println("Q: "+dsaParams.getQ()); + System.out.println("G: "+dsaParams.getG()); + System.out.println("Y: "+dsaPubKey.getY()); + + } catch (TokenException e) { + System.out.println("Token error: " + e); + } + } +} diff --git a/mozilla/security/jss/samples/TokenAccessTest.java b/mozilla/security/jss/samples/TokenAccessTest.java new file mode 100644 index 00000000000..04a5fa6ecdd --- /dev/null +++ b/mozilla/security/jss/samples/TokenAccessTest.java @@ -0,0 +1,256 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + + +/* This program demonstrates how to use JSS to enumerate + * crypto tokens, how to login and logout of tokens, and how + * to change the password on a token + */ + +import com.netscape.jss.pkcs11.*; + +import com.netscape.jss.util.*; +import com.netscape.jss.crypto.*; +import com.netscape.jss.*; +import java.io.*; +import java.awt.*; +import java.security.cert.*; + +public class TokenAccessTest { + + public static void main(String[] args) throws Throwable { + CryptoToken tok; + CryptoToken intTok; + CryptoManager manager; + Password pass1=null, pass2=null; + KeyPairGenerator keyPairGenerator; + java.security.KeyPair keyPair; + java.util.Enumeration items; + char[] passchar1 = {'f', 'o', 'o', 'b', 'a', 'r'}; + char[] passchar2 = {'n', 'e', 't', 's', 'c', 'a', 'p', 'e'}; + + if(args.length != 1) { + System.err.println("Usage: java TokenAccessTest "); + return; + } + + CryptoManager.InitializationValues vals = new + CryptoManager.InitializationValues( args[0]+"/secmodule.db", + args[0]+"/key3.db", + args[0]+"/cert7.db"); + CryptoManager.initialize(vals); + try { + manager = CryptoManager.getInstance(); + } catch( CryptoManager.NotInitializedException e ) { + System.out.println("CryptoManager not initialized"); + return; + } + + try { + tok = manager.getTokenByName("asdffda"); + System.out.println("ERROR: found a nonexistent token"); + } catch (NoSuchTokenException e) { + System.out.println("Good, could not find non-existent token"); + } + + try { + + items = manager.getModules(); + System.out.println("Modules:"); + while(items.hasMoreElements()) { + System.out.println("\t"+ + ((PK11Module)items.nextElement()).getName() ); + } + + items = manager.getAllTokens(); + System.out.println("All Tokens:"); + while(items.hasMoreElements()) { + System.out.println("\t"+ + ((CryptoToken)items.nextElement()).getName() ); + } + + items = manager.getExternalTokens(); + System.out.println("External Tokens:"); + while(items.hasMoreElements()) { + System.out.println("\t"+ + ((CryptoToken)items.nextElement()).getName() ); + } + + + tok = manager.getTokenByName("Internal Key Storage Token"); + System.out.println("Good, found internal DB token"); + + if( tok.equals(manager.getInternalKeyStorageToken()) ) { + System.out.println("Good, it really is the key storage token"); + } else { + System.out.println("ERROR: it's not the same as the key "+ + "storage token!"); + } + if( ((PK11Token)tok).isInternalKeyStorageToken() ) { + System.out.println("Good, "+tok.getName()+" knows "+ + "what it is"); + } else { + System.out.println("ERROR: "+tok.getName()+" doesn't know"+ + " it is key storage token"); + } + + intTok = manager.getInternalCryptoToken(); + if( ((PK11Token)intTok).isInternalCryptoToken() ) { + System.out.println("Good, "+tok.getName()+ + " knows it is the internal token"); + } else { + System.out.println("ERROR: "+tok.getName()+ + " doesn't know what that it is the internal token"); + } + + + if(tok.isLoggedIn() == false) { + System.out.println("Good, isLoggedIn correctly says we're"+ + " not logged in"); + } else { + System.out.println("ERROR: isLoggedIn incorrectly says we're"+ + " logged in"); + } + + System.out.println("Good, successfully opened token \""+ + tok.getName()+"\""); + + pass1 = new Password( (char[]) passchar1.clone()); + pass2 = new Password( new char[]{0} ); + tok.initPassword(pass2, pass1); + pass1.clear(); + pass2.clear(); + System.out.println("Good, initialized PIN"); + tok.logout(); + + try { + pass1 = new Password( (char[]) passchar2.clone()); + tok.login(pass1); + System.out.println("ERROR: Successfully logged in with wrong"+ + " PIN"); + } catch (IncorrectPasswordException e) { + System.out.println("Good, unable to login with wrong PIN"); + } finally { + pass1.clear(); + } + + pass1 = new Password( (char[]) passchar1.clone()); + tok.login(pass1); + pass1.clear(); + System.out.println("Good, logged in"); + + if(tok.isLoggedIn() == true) { + System.out.println("Good, isLoggedIn correctly says we're"+ + " logged in"); + } else { + System.out.println("ERROR: isLoggedIn incorrectly says we're"+ + " not logged in"); + } + + pass1 = new Password( (char[]) passchar1.clone()); + pass2 = new Password( (char[]) passchar2.clone()); + tok.changePassword(pass1, pass2); + pass1.clear(); pass2.clear(); + System.out.println("Good, changed PIN"); + + try { + pass1 = new Password( (char[]) passchar1.clone()); + tok.login(pass1); + // Should still be logged in + System.out.println("Good, logging in with wrong PIN ok if "+ + " already logged in"); + } catch (IncorrectPasswordException e) { + System.out.println("ERROR: logged in second time with wrong"+ + "PIN, but we should still be logged in"); + } finally { + pass1.clear(); + } + + try { + tok.logout(); + System.out.println("Good, logged out successfully."); + } catch (TokenException e) { + System.out.println("ERROR: failed to logout from token"); + } + + if(tok.isLoggedIn() == false) { + System.out.println("Good, isLoggedIn correctly says we're"+ + " not logged in"); + } else { + System.out.println("ERROR: isLoggedIn incorrectly says we're"+ + " logged in"); + } + + try { + tok.logout(); + System.out.println("ERROR: logged out twice in a row"); + } catch (TokenException e) { + System.out.println("Good, got an exception when we tried"+ + " to log out twice in a row"); + } + try { + pass1 = new Password( (char[]) passchar1.clone()); + tok.login(pass1); + pass1.clear(); + System.out.println("ERROR: logged in with wrong pw"); + } catch (IncorrectPasswordException e) { + System.out.println("Good, logging in with wrong PIN gave err"); + } + + System.out.println("Test completed"); + + tok = null; + + } catch (IncorrectPasswordException e) { + System.out.println("Got an incorrect PIN: "+e); + } catch (AlreadyInitializedException e) { + System.out.println( + "ERROR: This test only works with uninitialized databases"); + } catch (TokenException e) { + System.out.println("Token error: " + e); + } catch (NoSuchTokenException e) { + System.out.println("ERROR: could not find internal DB token"); + } finally { + if(pass1 != null) { + pass1.clear(); + } + if(pass2 != null) { + pass2.clear(); + } + } + + //System.gc(); + //NativeProxy.assertRegistryEmpty(); + //System.runFinalization(); + } +} diff --git a/mozilla/security/jss/samples/inputfile.pfx b/mozilla/security/jss/samples/inputfile.pfx new file mode 100644 index 00000000000..8ac3c40219d Binary files /dev/null and b/mozilla/security/jss/samples/inputfile.pfx differ diff --git a/mozilla/security/jss/samples/pkcs12.java b/mozilla/security/jss/samples/pkcs12.java new file mode 100644 index 00000000000..3666e5a2544 --- /dev/null +++ b/mozilla/security/jss/samples/pkcs12.java @@ -0,0 +1,277 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +/** + * This program reads in a PKCS #12 file and dumps its contents to the screen. + * At the same time, it creates a new PKCS #12 file. As it reads through the + * old file, it writes its contents into the new file. Then the new file + * is encrypted and MACed with a new, different password. + */ + +/* note that this code still has some problems reading PKCS12 file + * generated with Communicator. + */ + + +import java.io.*; +import com.netscape.jss.*; +import com.netscape.jss.pkcs12.*; +import com.netscape.jss.crypto.*; +import com.netscape.jss.asn1.*; +import com.netscape.jss.util.*; +import com.netscape.jss.pkix.*; +import com.netscape.jss.pkix.primitive.*; +import com.netscape.jss.pkix.cert.*; + + +public class pkcs12 { + + public static void main(String []args) { + + try { + + // Read arguments + if( args.length != 3 ) { + System.out.println("Usage: PFX "); + System.exit(-1); + } + + // open input file for reading + FileInputStream infile=null; + try { + infile = new FileInputStream(args[1]); + } + catch (FileNotFoundException f) { + System.out.println("Cannot open file "+args[1]+ + " for reading: "+f.getMessage()); + return; + } + int certfile = 0; + + // initialize CryptoManager. This is necessary because there is + // crypto involved with decoding a PKCS #12 file + CryptoManager.initialize( args[0]+"/secmod.db", + args[0]+"/key3.db", args[0]+"/cert7.db"); + CryptoManager manager = CryptoManager.getInstance(); + + // Decode the P12 file + PFX.Template pfxt = new PFX.Template(); + PFX pfx = (PFX) pfxt.decode(new BufferedInputStream(infile, 2048)); + System.out.println("Decoded PFX"); + + // print out information about the top-level PFX structure + System.out.println("Version: "+pfx.getVersion()); + AuthenticatedSafes authSafes = pfx.getAuthSafes(); + SEQUENCE safeContentsSequence = authSafes.getSequence(); + System.out.println("AuthSafes has "+ + safeContentsSequence.size()+" SafeContents"); + + // Get the password for the old file + System.out.println("Enter password: "); + Password pass = Password.readPasswordFromConsole(); + + // get new password, which will be used for the new file we create + // later + System.out.println("Enter new password:"); + Password newPass = Password.readPasswordFromConsole(); + + + // Verify the MAC on the PFX. This is important to be sure + // it hasn't been tampered with. + StringBuffer sb = new StringBuffer(); + if( pfx.verifyAuthSafes(pass, sb) ) { + System.out.println("AuthSafes verifies correctly."); + } else { + System.out.println("AuthSafes failed to verify because: "+ + sb); + } + + // Create a new AuthenticatedSafes. As we read the contents of the + // old authSafes, we will store them into the new one. After we have + // cycled through all the contents, they will all have been copied into + // the new authSafes. + AuthenticatedSafes newAuthSafes = new AuthenticatedSafes(); + + // Loop over contents of the old authenticated safes + //for(int i=0; i < asSeq.size(); i++) { + for(int i=0; i < safeContentsSequence.size(); i++) { + + // The safeContents may or may not be encrypted. We always send + // the password in. It will get used if it is needed. If the + // decryption of the safeContents fails for some reason (like + // a bad password), then this method will throw an exception + SEQUENCE safeContents = authSafes.getSafeContentsAt(pass, i); + + System.out.println("\n\nSafeContents #"+i+" has "+ + safeContents.size()+" bags"); + + // Go through all the bags in this SafeContents + for(int j=0; j < safeContents.size(); j++) { + SafeBag safeBag = (SafeBag) safeContents.elementAt(j); + + // The type of the bag is an OID + System.out.println("\nBag "+j+" has type "+ + safeBag.getBagType() ); + + + // look for bag attributes + SET attribs = safeBag.getBagAttributes(); + if( attribs == null ) { + System.out.println("Bag has no attributes"); + } else { + for(int b=0; b < attribs.size(); b++) { + Attribute a = (Attribute) attribs.elementAt(b); + if( a.getType().equals(SafeBag.FRIENDLY_NAME)) { + // the friendly name attribute is a nickname + BMPString bs = (BMPString) ((ANY)a.getValues(). + elementAt(0)).decodeWith( + BMPString.getTemplate()); + System.out.println("Friendly Name: "+bs); + } else if(a.getType().equals(SafeBag.LOCAL_KEY_ID)){ + // the local key id is used to match a key + // to its cert. The key id is the SHA-1 hash of + // the DER-encoded cert. + OCTET_STRING os =(OCTET_STRING) + ((ANY)a.getValues(). + elementAt(0)).decodeWith( + OCTET_STRING.getTemplate()); + System.out.println("LocalKeyID:"); + /* + AuthenticatedSafes. + print_byte_array(os.toByteArray()); + */ + } else { + System.out.println("Unknown attribute type: "+ + a.getType().toString()); + } + } + } + + // now look at the contents of the bag + ASN1Value val = safeBag.getInterpretedBagContent(); + + if( val instanceof PrivateKeyInfo ) { + // A PrivateKeyInfo contains an unencrypted private key + System.out.println("content is PrivateKeyInfo"); + } else if( val instanceof EncryptedPrivateKeyInfo ) { + // An EncryptedPrivateKeyInfo is, well, an encrypted + // PrivateKeyInfo. Usually, strong crypto is used in + // an EncryptedPrivateKeyInfo. + EncryptedPrivateKeyInfo epki = + ((EncryptedPrivateKeyInfo)val); + System.out.println( + "content is EncryptedPrivateKeyInfo, algoid:" + + epki.getEncryptionAlgorithm().getOID()); + + // Because we are in a PKCS #12 file, the passwords are + // char-to-byte converted in a special way. We have to + // use the special converter class instead of the default. + PrivateKeyInfo pki = epki.decrypt(pass, + new com.netscape.jss.pkcs12.PasswordConverter() ); + + // import the key into the key3.db + CryptoToken tok = manager.getTokenByName("Internal Key Storage Token"); + CryptoStore store = tok.getCryptoStore(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + pki.encode(baos); + store.importPrivateKey(baos.toByteArray(), + PrivateKey.RSA); + + + // re-encrypt the PrivateKeyInfo with the new password + // and random salt + byte[] salt = new byte[ + PBEAlgorithm.PBE_SHA1_DES3_CBC.getSaltLength()]; + JSSSecureRandom rand = CryptoManager.getInstance(). + getSecureRNG(); + rand.nextBytes(salt); + epki = EncryptedPrivateKeyInfo.createPBE( + PBEAlgorithm.PBE_SHA1_DES3_CBC, newPass, + salt, 1, new PasswordConverter(), pki); + + // Overwrite the previous EncryptedPrivateKeyInfo with + // this new one we just created using the new password. + // This is what will get put in the new PKCS #12 file + // we are creating. + safeContents.insertElementAt( + new SafeBag( safeBag.getBagType(), + epki, safeBag.getBagAttributes()), i); + safeContents.removeElementAt(i+1); + + } else if( val instanceof CertBag ) { + System.out.println("content is CertBag"); + CertBag cb = (CertBag) val; + if( cb.getCertType().equals(CertBag.X509_CERT_TYPE)) { + // this is an X.509 certificate + OCTET_STRING os = (OCTET_STRING)cb.getInterpretedCert(); + Certificate cert = (Certificate) + ASN1Util.decode(Certificate.getTemplate(), + os.toByteArray()); + cert.getInfo().print(System.out); + } else { + System.out.println("Unrecognized cert type"); + } + } else { + System.out.println("content is ANY"); + } + } + + // Add the new safe contents to the new authsafes + if( authSafes.safeContentsIsEncrypted(i) ) { + newAuthSafes.addEncryptedSafeContents( + authSafes.DEFAULT_KEY_GEN_ALG, newPass, + null, authSafes.DEFAULT_ITERATIONS, safeContents); + } else { + newAuthSafes.addSafeContents( safeContents ); + } + } + + // Create new PFX from the new authsafes + PFX newPfx = new PFX(newAuthSafes); + + // Add a MAC to the new PFX + newPfx.computeMacData(newPass, null, PFX.DEFAULT_ITERATIONS); + + // write the new PFX out to a file + FileOutputStream fos = new FileOutputStream(args[2]); + newPfx.encode(fos); + fos.close(); + + + } catch( Exception e ) { + e.printStackTrace(); + } + } + + + +}