diff options
author | relyea%netscape.com <devnull@localhost> | 2000-03-31 20:13:40 +0000 |
---|---|---|
committer | relyea%netscape.com <devnull@localhost> | 2000-03-31 20:13:40 +0000 |
commit | 9502869e82d4f3ce26b292263e1c626dca3a34f3 (patch) | |
tree | 4d0f8ab157505b57c13a5e2bdf979560ab751527 /security/nss/lib/fortcrypt/swfort | |
parent | 222a52dab759085f56dcb6588b69a6a937d82aa2 (diff) | |
download | nss-hg-9502869e82d4f3ce26b292263e1c626dca3a34f3.tar.gz |
Initial NSS Open Source checkin
Diffstat (limited to 'security/nss/lib/fortcrypt/swfort')
20 files changed, 4410 insertions, 0 deletions
diff --git a/security/nss/lib/fortcrypt/swfort/.cvsignore b/security/nss/lib/fortcrypt/swfort/.cvsignore new file mode 100644 index 000000000..46d9697ae --- /dev/null +++ b/security/nss/lib/fortcrypt/swfort/.cvsignore @@ -0,0 +1 @@ +nslib.c diff --git a/security/nss/lib/fortcrypt/swfort/Makefile b/security/nss/lib/fortcrypt/swfort/Makefile new file mode 100644 index 000000000..80b91c768 --- /dev/null +++ b/security/nss/lib/fortcrypt/swfort/Makefile @@ -0,0 +1,82 @@ +#! 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 libraries. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1994-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. 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). # +####################################################################### + +include config.mk + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### + + +nslib.c:: swflib.c nsmap.h + rm -f nslib.c + cat nsmap.h swflib.c > nslib.c + +export:: private_export + + diff --git a/security/nss/lib/fortcrypt/swfort/config.mk b/security/nss/lib/fortcrypt/swfort/config.mk new file mode 100644 index 000000000..a73a1086e --- /dev/null +++ b/security/nss/lib/fortcrypt/swfort/config.mk @@ -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 libraries. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1994-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +# +# Override TARGETS variable so that only static libraries +# are specifed as dependencies within rules.mk. +# + +TARGETS = $(LIBRARY) +SHARED_LIBRARY = +IMPORT_LIBRARY = +PURE_LIBRARY = +PROGRAM = + diff --git a/security/nss/lib/fortcrypt/swfort/manifest.mn b/security/nss/lib/fortcrypt/swfort/manifest.mn new file mode 100644 index 000000000..5445af13b --- /dev/null +++ b/security/nss/lib/fortcrypt/swfort/manifest.mn @@ -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 libraries. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1994-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. 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 = security +LIBRARY_NAME = swfci +#LIBRARY_VERSION = 12 + +CSRCS = swfalg.c \ + swfparse.c \ + swflib.c \ + nslib.c \ + swfutl.c \ + $(NULL) + +DIRS = pkcs11 + + +EXPORTS = swfort.h swfortt.h +PRIVATE_EXPORTS = swforti.h swfortti.h + +REQUIRES = security dbm nspr + +GARBAGE = nslib.c + + diff --git a/security/nss/lib/fortcrypt/swfort/nsmap.h b/security/nss/lib/fortcrypt/swfort/nsmap.h new file mode 100644 index 000000000..b5e1c2cda --- /dev/null +++ b/security/nss/lib/fortcrypt/swfort/nsmap.h @@ -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 libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +#define MACI_ChangePIN NSCI_ChangePIN +#define MACI_CheckPIN NSCI_CheckPIN +#define MACI_Close NSCI_Close +#define MACI_Decrypt NSCI_Decrypt +#define MACI_DeleteCertificate NSCI_DeleteCertificate +#define MACI_DeleteKey NSCI_DeleteKey +#define MACI_Encrypt NSCI_Encrypt +#define MACI_ExtractX NSCI_ExtractX +#define MACI_FirmwareUpdate NSCI_FirmwareUpdate +#define MACI_GenerateIV NSCI_GenerateIV +#define MACI_GenerateMEK NSCI_GenerateMEK +#define MACI_GenerateRa NSCI_GenerateRa +#define MACI_GenerateRandom NSCI_GenerateRandom +#define MACI_GenerateTEK NSCI_GenerateTEK +#define MACI_GenerateX NSCI_GenerateX +#define MACI_GetCertificate NSCI_GetCertificate +#define MACI_GetConfiguration NSCI_GetConfiguration +#define MACI_GetHash NSCI_GetHash +#define MACI_GetPersonalityList NSCI_GetPersonalityList +#define MACI_GetSessionID NSCI_GetSessionID +#define MACI_GetState NSCI_GetState +#define MACI_GetStatus NSCI_GetStatus +#define MACI_GetTime NSCI_GetTime +#define MACI_Hash NSCI_Hash +#define MACI_Initialize NSCI_Initialize +#define MACI_InitializeHash NSCI_InitializeHash +#define MACI_InstallX NSCI_InstallX +#define MACI_LoadCertificate NSCI_LoadCertificate +#define MACI_LoadDSAParameters NSCI_LoadDSAParameters +#define MACI_LoadInitValues NSCI_LoadInitValues +#define MACI_LoadIV NSCI_LoadIV +#define MACI_LoadX NSCI_LoadX +#define MACI_Lock NSCI_Lock +#define MACI_Open NSCI_Open +#define MACI_RelayX NSCI_RelayX +#define MACI_Reset NSCI_Reset +#define MACI_Restore NSCI_Restore +#define MACI_Save NSCI_Save +#define MACI_Select NSCI_Select +#define MACI_SetConfiguration NSCI_SetConfiguration +#define MACI_SetKey NSCI_SetKey +#define MACI_SetMode NSCI_SetMode +#define MACI_SetPersonality NSCI_SetPersonality +#define MACI_SetTime NSCI_SetTime +#define MACI_Sign NSCI_Sign +#define MACI_Terminate NSCI_Terminate +#define MACI_TimeStamp NSCI_TimeStamp +#define MACI_Unlock NSCI_Unlock +#define MACI_UnwrapKey NSCI_UnwrapKey +#define MACI_VerifySignature NSCI_VerifySignature +#define MACI_VerifyTimeStamp NSCI_VerityTimeStap +#define MACI_WrapKey NSCI_WrapKey +#define MACI_Zeroize NSCI_Zeroize + diff --git a/security/nss/lib/fortcrypt/swfort/pkcs11/.cvsignore b/security/nss/lib/fortcrypt/swfort/pkcs11/.cvsignore new file mode 100644 index 000000000..6532d294d --- /dev/null +++ b/security/nss/lib/fortcrypt/swfort/pkcs11/.cvsignore @@ -0,0 +1,15 @@ +forsock.c +cryptint.h +fmutex.h +fortsock.h +fpkcs11.h +fpkcs11f.h +fpkcs11i.h +fpkcs11t.h +fpkmem.h +fpkstrs.h +genci.h +maci.h +fortpk11.c +fmutex.c + diff --git a/security/nss/lib/fortcrypt/swfort/pkcs11/Makefile b/security/nss/lib/fortcrypt/swfort/pkcs11/Makefile new file mode 100644 index 000000000..afb11cf6f --- /dev/null +++ b/security/nss/lib/fortcrypt/swfort/pkcs11/Makefile @@ -0,0 +1,164 @@ +#! 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 libraries. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1994-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. 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 manifest.mn +include $(CORE_DEPTH)/coreconf/config.mk + + +#SWCILIB = ../$(OBJDIR)/$(LIB_PREFIX)swfci.$(LIB_SUFFIX) +# can't do this in manifest.mn because OS_ARCH isn't defined there. +ifeq ($(OS_ARCH), WINNT) + +# $(DIST)/lib/dbm.lib +# $(DIST)/lib/$(NSPR31_LIB_PREFIX)nspr4.lib +EXTRA_LIBS = \ + $(DIST)/lib/swfci.lib \ + $(DIST)/lib/softoken.lib \ + $(DIST)/lib/freebl.lib \ + $(DIST)/lib/crypto.lib \ + $(DIST)/lib/secutil.lib \ + $(DIST)/lib/$(NSPR31_LIB_PREFIX)plc4_s.lib \ + $(DIST)/lib/$(NSPR31_LIB_PREFIX)plds4_s.lib \ + wsock32.lib \ + winmm.lib \ + $(NULL) +else + +# $(DIST)/lib/libdbm.a +# $(DIST)/lib/libnspr3.a +# OSF 1 linker is very agressive. It includes the entire archive, +# not just the .o's that we need from that archive. +# +ifneq ($(OS_ARCH), OSF1) +EXTRA_LIBS += \ + $(DIST)/lib/libswfci.a \ + $(DIST)/lib/libsoftoken.a \ + $(DIST)/lib/libfreebl.a \ + $(DIST)/lib/libcrypto.a \ + $(DIST)/lib/libsecutil.a \ + $(DIST)/lib/libplc4.a \ + $(DIST)/lib/libplds4.a \ + $(NULL) +endif +endif + +#ifeq ($(OS_TARGET), WIN16) +#W16LIBS += $(SWCILIB) +#else +#OBJS += $(SWCILIB) +#endif + +INST_JS = inst.js +LIBCI_JAR = $(OBJDIR)/lib$(LIBRARY_NAME).jar +LIBCI_JAR_SRC = $(INST_JS) pk11inst $(SHARED_LIBRARY) + +ifneq ($(OS_TARGET), WIN16) +TARGETS : $(LIBCI_JAR) +endif + +ifeq ($(OS_TARGET), WIN16) +# note that rules.mk is not included below for WIN16 +all: + @echo Skipping fortcrypt directory for 16-bit windows builds + +all_platforms alltags clean clobber clobber_all realclean: all + +boot export install libs program release: all + +endif + +#$(SHARED_LIBRARY): $(SWCILIB) + +forsock.c: ../../forsock.c $(CP_INCLUDES) + cp ../../forsock.c $(CP_INCLUDES) . + +fortpk11.c: ../../fortpk11.c + cp ../../fortpk11.c . + +fmutex.c: ../../fmutex.c + cp ../../fmutex.c . + + +# +# The following rules packages the shared library into a JAR, +# ready to be signed +# +$(OBJDIR)/replace: replace.c + $(CC) -o $@ $< + +# ZIP options: +# -5 means medium compression +# -q means quiet +# -j means do not store tree structure, all files go into one dir +# +$(LIBCI_JAR): $(LIBCI_JAR_SRC) + @echo +++ building $@ from $(LIBCI_JAR_SRC) + @rm -f $@ + zip -5qj $@ $(LIBCI_JAR_SRC) + +$(LIBSWCI_JAR): $(LIBSWCI_JAR_SRC) + @echo +++ building $@ from $(LIBSWCI_JAR_SRC) + @rm -f $@ + zip -5qj $@ $(LIBSWCI_JAR_SRC) + + +MD_FILES += $(LIBCI_JAR) $(LIBSWCI_JAR) + +# coreconf doesn't build the AIX shared library for FORTEZZA, +# so I'm going to override their shared library command and build the shared +# library the way config used to. +# + + +ifeq ($(OS_ARCH)$(OS_RELEASE), AIX4.1) +DSO_LDOPTS = -bM:SRE -bh:4 -bnoentry +EXTRA_DSO_LDOPTS = -lc +MKSHLIB = xlC $(DSO_LDOPTS) + +$(SHARED_LIBRARY): $(OBJS) + @$(MAKE_OBJDIR) + rm -f $@ + $(MKSHLIB) -o $@ $(OBJS) $(EXTRA_LIBS) $(EXTRA_DSO_LDOPTS) + chmod +x $@ + +endif + +ifeq ($(OS_ARCH)$(OS_RELEASE), AIX4.2) +LD += -G +endif + +ifneq ($(OS_TARGET), WIN16) +include $(CORE_DEPTH)/coreconf/rules.mk +endif + diff --git a/security/nss/lib/fortcrypt/swfort/pkcs11/config.mk b/security/nss/lib/fortcrypt/swfort/pkcs11/config.mk new file mode 100644 index 000000000..9b1a488d2 --- /dev/null +++ b/security/nss/lib/fortcrypt/swfort/pkcs11/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 libraries. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1994-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +# +# Override TARGETS variable so that only static libraries +# are specifed as dependencies within rules.mk. +# + +ifeq ($(OS_TARGET), WIN16) +TARGETS = all +else +TARGETS = $(SHARED_LIBRARY) $(SHARED_SW_LIBRARY) $(LIBCI_JAR) $(LIBCI_SW_JAR) +endif +LIBRARY = +PURE_LIBRARY = +PROGRAM = + + +ifeq ($(OS_TARGET), WIN16) +dummy: + @echo $(TARGETS) +endif diff --git a/security/nss/lib/fortcrypt/swfort/pkcs11/inst.js b/security/nss/lib/fortcrypt/swfort/pkcs11/inst.js new file mode 100644 index 000000000..2f7574717 --- /dev/null +++ b/security/nss/lib/fortcrypt/swfort/pkcs11/inst.js @@ -0,0 +1,189 @@ +// +// The contents of this file are subject to the Mozilla Public +// License Version 1.1 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of +// the License at http://www.mozilla.org/MPL/ +// +// Software distributed under the License is distributed on an "AS +// IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +// implied. See the License for the specific language governing +// rights and limitations under the License. +// +// The Original Code is the Netscape security libraries. +// +// The Initial Developer of the Original Code is Netscape +// Communications Corporation. Portions created by Netscape are +// Copyright (C) 1994-2000 Netscape Communications Corporation. All +// Rights Reserved. +// +// Contributor(s): +// +// Alternatively, the contents of this file may be used under the +// terms of the GNU General Public License Version 2 or later (the +// "GPL"), in which case the provisions of the GPL are applicable +// instead of those above. If you wish to allow use of your +// version of this file only under the terms of the GPL and not to +// allow others to use your version of this file under the MPL, +// indicate your decision by deleting the provisions above and +// replace them with the notice and other provisions required by +// the GPL. 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 Mechanism Flags +PKCS11_MECH_RSA_FLAG = 0x1<<0; +PKCS11_MECH_DSA_FLAG = 0x1<<1; +PKCS11_MECH_RC2_FLAG = 0x1<<2; +PKCS11_MECH_RC4_FLAG = 0x1<<3; +PKCS11_MECH_DES_FLAG = 0x1<<4; +PKCS11_MECH_DH_FLAG = 0x1<<5; //Diffie-Hellman +PKCS11_MECH_SKIPJACK_FLAG = 0x1<<6; //SKIPJACK algorithm as in Fortezza cards +PKCS11_MECH_RC5_FLAG = 0x1<<7; +PKCS11_MECH_SHA1_FLAG = 0x1<<8; +PKCS11_MECH_MD5_FLAG = 0x1<<9; +PKCS11_MECH_MD2_FLAG = 0x1<<10; +PKCS11_MECH_RANDOM_FLAG = 0x1<<27; //Random number generator +PKCS11_PUB_READABLE_CERT_FLAG = 0x1<<28; //Stored certs can be read off the token w/o logging in +PKCS11_DISABLE_FLAG = 0x1<<30; //tell Navigator to disable this slot by default + +// Important: +// 0x1<<11, 0x1<<12, ... , 0x1<<26, 0x1<<29, and 0x1<<31 are reserved +// for internal use in Navigator. +// Therefore, these bits should always be set to 0; otherwise, +// Navigator might exhibit unpredictable behavior. + +// These flags indicate which mechanisms should be turned on by +var pkcs11MechanismFlags = 0; + +//////////////////////////////////////////////////////////////////////////////////////// +// Ciphers that support SSL or S/MIME +PKCS11_CIPHER_FORTEZZA_FLAG = 0x1<<0; + +// Important: +// 0x1<<1, 0x1<<2, ... , 0x1<<31 are reserved +// for internal use in Navigator. +// Therefore, these bits should ALWAYS be set to 0; otherwise, +// Navigator might exhibit unpredictable behavior. + +// These flags indicate which SSL ciphers are supported +var pkcs11CipherFlags = PKCS11_CIPHER_FORTEZZA_FLAG; + +//////////////////////////////////////////////////////////////////////////////////////// +// Return values of pkcs11.addmodule() & pkcs11.delmodule() +// success codes +JS_OK_ADD_MODULE = 3; // Successfully added a module +JS_OK_DEL_EXTERNAL_MODULE = 2; // Successfully deleted ext. module +JS_OK_DEL_INTERNAL_MODULE = 1; // Successfully deleted int. module + +// failure codes +JS_ERR_OTHER = -1; // Other errors than the followings +JS_ERR_USER_CANCEL_ACTION = -2; // User abort an action +JS_ERR_INCORRECT_NUM_OF_ARGUMENTS= -3; // Calling a method w/ incorrect # of arguments +JS_ERR_DEL_MODULE = -4; // Error deleting a module +JS_ERR_ADD_MODULE = -5; // Error adding a module +JS_ERR_BAD_MODULE_NAME = -6; // The module name is invalid +JS_ERR_BAD_DLL_NAME = -7; // The DLL name is bad +JS_ERR_BAD_MECHANISM_FLAGS = -8; // The mechanism flags are invalid +JS_ERR_BAD_CIPHER_ENABLE_FLAGS = -9; // The SSL, S/MIME cipher flags are invalid + + +//////////////////////////////////////////////////////////////////////////////////////// +// Find out which library is to be installed depending on the platform + +// pathname seperator is platform specific +var sep = "/"; +var vendor = "netscape"; +var moduleName = "not_supported"; + +// platform-independent relative path +var dir = "pkcs11/" + vendor + "/"; + +var plat = navigator.platform; + +bAbort = false; +progName = "instinit"; +if (plat == "Win32") { + moduleName = "swft32.dll"; + // progName = "instinit.exe"; + sep = "\\"; +} else if (plat == "AIX4.1") { + moduleName = "libswft.so"; +} else if (plat == "SunOS4.1.3_U1") { + moduleName = "libswft.so.1.0"; +} else if ((plat == "SunOS5.4") || (plat == "SunOS5.5.1")){ + moduleName = "libswft.so"; +} else if ((plat == "HP-UXA.09") || (plat == "HP-UXB.10")){ + moduleName = "libswft.sl"; +} else { + window.alert("Sorry, platform "+plat+" is not supported."); + bAbort = true; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// Installation Begins... +if (!bAbort) { +if (confirm("This script will install and configure a security module, do you want to continue?")) { + // Step 1. Create a version object and a software update object + vi = new netscape.softupdate.VersionInfo(1, 5, 0, 0); + su = new netscape.softupdate.SoftwareUpdate(this, "Fortezza Card PKCS#11 Module"); + // "Fortezza ... Module" is the logical name of the bundle + + //////////////////////////////////////// + // Step 2. Start the install process + bAbort = false; + err = su.StartInstall("NSfortezza", // NSfortezza is the component folder (logical) + vi, + netscape.softupdate.SoftwareUpdate.FULL_INSTALL); + + bAbort = bAbort || (err !=0); + + if (err == 0) { + //////////////////////////////////////// + // Step 3. Find out the physical location of the Program dir + Folder = su.GetFolder("Program"); + + //////////////////////////////////////// + // Step 4. Install the files. Unpack them and list where they go + err = su.AddSubcomponent("FortezzaLibrary", //component name (logical) + vi, // version info + moduleName, // source file in JAR (physical) + Folder, // target folder (physical) + dir + moduleName, // target path & filename (physical) + this.force); // forces update + bAbort = bAbort || (err !=0); + if (err != 0) window.alert("Add sub err= "+ err); + } + + if (err == 0) { + /// Try installing the init program + err = su.AddSubcomponent("FortezzaInitProg", vi, progName, Folder, progName, this.force); + // don't fail because it didn't install, may just not be part of the package +} + + //////////////////////////////////////// + // Step 5. Unless there was a problem, move files to final location + // and update the Client Version Registry + if (bAbort) { + window.alert("Aborting, Folder="+Folder+" module="+dir+moduleName); + su.AbortInstall(); + } else { + err = su.FinalizeInstall(); + // Platform specific full path + fullpath = Folder + "pkcs11" + sep + vendor + sep + moduleName; + + //////////////////////////////////////// + // Step 6: Call pkcs11.addmodule() to register the newly downloaded module + result = pkcs11.addmodule("Netscape Software FORTEZZA Module", + fullpath, + pkcs11MechanismFlags, + pkcs11CipherFlags); + + if ( result < 0) { + window.alert("New module setup failed. Error code: " + result); + } else { + window.alert("New module setup completed."); + } + } +} +} diff --git a/security/nss/lib/fortcrypt/swfort/pkcs11/manifest.mn b/security/nss/lib/fortcrypt/swfort/pkcs11/manifest.mn new file mode 100644 index 000000000..eca9b5ab3 --- /dev/null +++ b/security/nss/lib/fortcrypt/swfort/pkcs11/manifest.mn @@ -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 libraries. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1994-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. 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 = security +LIBRARY_NAME = swft +#LIBRARY_VERSION = 32 + +COPIED_CSRCS = forsock.c \ + fortpk11.c \ + fmutex.c \ + $(NULL) + +CSRCS = \ + $(COPIED_CSRCS) \ + stub.c \ + $(NULL) + +EXPORTS = + +REQUIRES = security dbm + +CP_INCLUDES = \ + ../../cryptint.h \ + ../../fmutex.h \ + ../../fortsock.h \ + ../../fpkcs11.h \ + ../../fpkcs11f.h \ + ../../fpkcs11i.h \ + ../../fpkcs11t.h \ + ../../fpkmem.h \ + ../../fpkstrs.h \ + ../../genci.h \ + ../../maci.h \ + $(NULL) + +CFLAGS += -DSWFORT + +GARBAGE = $(COPIED_CSRCS) cryptint.h fmutex.h fortsock.h fpkcs11.h \ + fpkcs11f.h fpkcs11i.h fpkcs11t.h fpkmem.h fpkstrs.h genci.h maci.h + + diff --git a/security/nss/lib/fortcrypt/swfort/pkcs11/pk11inst b/security/nss/lib/fortcrypt/swfort/pkcs11/pk11inst new file mode 100755 index 000000000..31d73eb4a --- /dev/null +++ b/security/nss/lib/fortcrypt/swfort/pkcs11/pk11inst @@ -0,0 +1,49 @@ +ForwardCompatible { HPUX:10:hppa1.1 Solaris:5.5.1:sparc AIX:4.1:rs6000 } + Platforms { + WINNT::x86 { + ModuleName { "Netscape Software FORTEZZA Module" } + ModuleFile { %root%/pkcs11/netscape/swft32.dll } + DefaultMechanismFlags{0x0000} + DefaultCipherFlags{0x0001} + Files { + swft32.dll { + RelativePath { %root%/pkcs11/netscape/swft32.dll } + } + } + WIN95::x86 { + EquivalentPlatform {WINNT::x86} + } + Solaris:5.5.1:sparc { + ModuleName { "Netscape Software FORTEZZA Module" } + ModuleFile { %root%/pkcs11/netscape/libswft.so } + DefaultMechanismFlags{0x0000} + DefaultCipherFlags{0x0001} + Files { + libswft.so { + RelativePath { %root%/pkcs11/netscape/libswft.so } + } + } + } + AIX:4.1:rs6000 { + ModuleName { "Netscape Software FORTEZZA Module" } + ModuleFile { %root%/pkcs11/netscape/libswft.so } + DefaultMechanismFlags{0x0000} + DefaultCipherFlags{0x0001} + Files { + libswft.so { + RelativePath { %root%/pkcs11/netscape/libswft.so } + } + } + } + HPUX:10:hppa1.1 { + ModuleName { "Netscape Software FORTEZZA Module" } + ModuleFile { %root%/pkcs11/netscape/libswft.sl } + DefaultMechanismFlags{0x0000} + DefaultCipherFlags{0x0001} + Files { + libswft.so { + RelativePath { %root%/pkcs11/netscape/libswft.sl } + } + } + } + } diff --git a/security/nss/lib/fortcrypt/swfort/pkcs11/stub.c b/security/nss/lib/fortcrypt/swfort/pkcs11/stub.c new file mode 100644 index 000000000..917eff386 --- /dev/null +++ b/security/nss/lib/fortcrypt/swfort/pkcs11/stub.c @@ -0,0 +1,344 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +/* + * secport.c - portability interfaces for security libraries + * + * This file abstracts out libc functionality that libsec depends on + * + * NOTE - These are not public interfaces. These stubs are to allow the + * SW FORTEZZA to link with some low level security functions without dragging + * in NSPR. + * + * $Id$ + */ + +#include "seccomon.h" +#include "prmem.h" +#include "prerror.h" +#include "plarena.h" +#include "secerr.h" +#include "prmon.h" +#include "prbit.h" + +unsigned long port_allocFailures; + +/* locations for registering Unicode conversion functions. + * Is this the appropriate location? or should they be + * moved to client/server specific locations? + */ +PORTCharConversionFunc ucs4Utf8ConvertFunc; +PORTCharConversionFunc ucs2Utf8ConvertFunc; +PORTCharConversionWSwapFunc ucs2AsciiConvertFunc; + +void * +PORT_Alloc(size_t bytes) +{ + void *rv; + + /* Always allocate a non-zero amount of bytes */ + rv = (void *)malloc(bytes ? bytes : 1); + if (!rv) { + ++port_allocFailures; + } + return rv; +} + +void * +PORT_Realloc(void *oldptr, size_t bytes) +{ + void *rv; + + rv = (void *)realloc(oldptr, bytes); + if (!rv) { + ++port_allocFailures; + } + return rv; +} + +void * +PORT_ZAlloc(size_t bytes) +{ + void *rv; + + /* Always allocate a non-zero amount of bytes */ + rv = (void *)calloc(1, bytes ? bytes : 1); + if (!rv) { + ++port_allocFailures; + } + return rv; +} + +void +PORT_Free(void *ptr) +{ + if (ptr) { + free(ptr); + } +} + +void +PORT_ZFree(void *ptr, size_t len) +{ + if (ptr) { + memset(ptr, 0, len); + free(ptr); + } +} + +void +PORT_SetError(int value) +{ + return; +} + +int +PORT_GetError(void) +{ + return(1); +} + +/********************* Arena code follows *****************************/ + + +PLArenaPool * +PORT_NewArena(unsigned long chunksize) +{ + PLArenaPool *arena; + + arena = (PLArenaPool*)PORT_ZAlloc(sizeof(PLArenaPool)); + if ( arena != NULL ) { + PR_InitArenaPool(arena, "security", chunksize, sizeof(double)); + } + return(arena); +} + +void * +PORT_ArenaAlloc(PLArenaPool *arena, size_t size) +{ + void *p; + + PL_ARENA_ALLOCATE(p, arena, size); + if (p == NULL) { + ++port_allocFailures; + } + + return(p); +} + +void * +PORT_ArenaZAlloc(PLArenaPool *arena, size_t size) +{ + void *p; + + PL_ARENA_ALLOCATE(p, arena, size); + if (p == NULL) { + ++port_allocFailures; + } else { + PORT_Memset(p, 0, size); + } + + return(p); +} + +/* need to zeroize!! */ +void +PORT_FreeArena(PLArenaPool *arena, PRBool zero) +{ + PR_FinishArenaPool(arena); + PORT_Free(arena); +} + +void * +PORT_ArenaGrow(PLArenaPool *arena, void *ptr, size_t oldsize, size_t newsize) +{ + PORT_Assert(newsize >= oldsize); + + PL_ARENA_GROW(ptr, arena, oldsize, ( newsize - oldsize ) ); + + return(ptr); +} + +void * +PORT_ArenaMark(PLArenaPool *arena) +{ + void * result; + + result = PL_ARENA_MARK(arena); + return result; +} + +void +PORT_ArenaRelease(PLArenaPool *arena, void *mark) +{ + PL_ARENA_RELEASE(arena, mark); +} + +void +PORT_ArenaUnmark(PLArenaPool *arena, void *mark) +{ + /* do nothing */ +} + +char * +PORT_ArenaStrdup(PLArenaPool *arena,char *str) { + int len = PORT_Strlen(str)+1; + char *newstr; + + newstr = (char*)PORT_ArenaAlloc(arena,len); + if (newstr) { + PORT_Memcpy(newstr,str,len); + } + return newstr; +} + +PR_IMPLEMENT(void) +PR_Assert(const char *expr, const char *file, int line) { + return; +} + +PR_IMPLEMENT(void *) +PR_Alloc(PRUint32 bytes) { return malloc(bytes); } + +PR_IMPLEMENT(void *) +PR_Malloc(PRUint32 bytes) { return malloc(bytes); } + +PR_IMPLEMENT(void *) +PR_Calloc(PRUint32 blocks, PRUint32 bytes) { return calloc(blocks,bytes); } + +PR_IMPLEMENT(void) +PR_Free(void *ptr) { free(ptr); } + + +/* Old template; want to expunge it eventually. */ +#include "secasn1.h" +#include "secoid.h" + +const SEC_ASN1Template SECOID_AlgorithmIDTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(SECAlgorithmID) }, + { SEC_ASN1_OBJECT_ID, + offsetof(SECAlgorithmID,algorithm), }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_ANY, + offsetof(SECAlgorithmID,parameters), }, + { 0, } +}; + +/* now make the RNG happy */ /* This is not atomic! */ +PR_IMPLEMENT(PRInt32) PR_AtomicIncrement(PRInt32 *val) { return ++(*val); } +/* This is not atomic! */ +PR_IMPLEMENT(PRInt32) PR_AtomicDecrement(PRInt32 *val) { return --(*val); } + +PR_IMPLEMENT(PRStatus) PR_Sleep(PRIntervalTime ticks) { return PR_SUCCESS; } + +#include "prlock.h" +#include "fmutex.h" +PR_IMPLEMENT(PRLock *) +PR_NewLock(void) { + PRLock *lock = NULL; + + FMUTEX_Create(&lock); + + /* if we don't have a lock, FMUTEX can deal with things */ + if (lock == NULL) lock=(PRLock *) 1; + return lock; +} + +PR_IMPLEMENT(void) +PR_DestroyLock(PRLock *lock) { + FMUTEX_Destroy(lock); +} + +PR_IMPLEMENT(void) +PR_Lock(PRLock *lock) { + FMUTEX_Lock(lock); +} + +PR_IMPLEMENT(PRStatus) +PR_Unlock(PRLock *lock) { + FMUTEX_Unlock(lock); + return PR_SUCCESS; +} + +/* this implementation is here to satisfy the PRMonitor use in plarena.c. +** It appears that it doesn't need re-entrant locks. It could have used +** PRLock instead of PRMonitor. So, this implementation just uses +** PRLock for a PRMonitor. +*/ +PR_IMPLEMENT(PRMonitor*) +PR_NewMonitor(void) +{ + return (PRMonitor *) PR_NewLock(); +} + + +PR_IMPLEMENT(void) +PR_EnterMonitor(PRMonitor *mon) +{ + PR_Lock( (PRLock *)mon ); +} + +PR_IMPLEMENT(PRStatus) +PR_ExitMonitor(PRMonitor *mon) +{ + return PR_Unlock( (PRLock *)mon ); +} + +#include "prinit.h" + +/* This is NOT threadsafe. It is merely a pseudo-functional stub. +*/ +PR_IMPLEMENT(PRStatus) PR_CallOnce( + PRCallOnceType *once, + PRCallOnceFN func) +{ + /* This is not really atomic! */ + if (1 == PR_AtomicIncrement(&once->initialized)) { + once->status = (*func)(); + } else { + /* Should wait to be sure that func has finished before returning. */ + } + return once->status; +} + + +/* +** Compute the log of the least power of 2 greater than or equal to n +*/ +PRIntn PR_CeilingLog2(PRUint32 i) { + PRIntn log2; + PR_CEILING_LOG2(log2,i); + return log2; +} + +/********************** end of arena functions ***********************/ + diff --git a/security/nss/lib/fortcrypt/swfort/swfalg.c b/security/nss/lib/fortcrypt/swfort/swfalg.c new file mode 100644 index 000000000..6f8ab9f6c --- /dev/null +++ b/security/nss/lib/fortcrypt/swfort/swfalg.c @@ -0,0 +1,506 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +/* + * Software implementation of FORTEZZA skipjack primatives + */ +#include "maci.h" +#include "seccomon.h" +#include "swforti.h" + +/* + * Xor the IV into the plaintext buffer either just before encryption, or + * just after decryption. + */ +static void +fort_XorIV(unsigned char *obuffer, unsigned char *buffer, unsigned char *iv) { + int i; +#ifdef USE_INT32 + if ((buffer & 0x3) == 0) && ((iv & 0x3) == 0)) { + int32 *ibuffer = (int32 *)buffer; + int32 *iobuffer = (int32 *)obuffer; + int32 *iiv = (int32 *)iv; + + iobuffer[0] = ibuffer[0] ^ iiv[0]; + iobuffer[1] = ibuffer[1] ^ iiv[1]; + return; + } +#endif + + for (i=0; i < SKIPJACK_BLOCK_SIZE; i++) { + obuffer[i] = buffer[i] ^ iv[i]; + } +} + + +/* the F-table for Skipjack */ +unsigned char F[256] = { + 0xa3, 0xd7, 0x09, 0x83, 0xf8, 0x48, 0xf6, 0xf4, + 0xb3, 0x21, 0x15, 0x78, 0x99, 0xb1, 0xaf, 0xf9, + 0xe7, 0x2d, 0x4d, 0x8a, 0xce, 0x4c, 0xca, 0x2e, + 0x52, 0x95, 0xd9, 0x1e, 0x4e, 0x38, 0x44, 0x28, + 0x0a, 0xdf, 0x02, 0xa0, 0x17, 0xf1, 0x60, 0x68, + 0x12, 0xb7, 0x7a, 0xc3, 0xe9, 0xfa, 0x3d, 0x53, + 0x96, 0x84, 0x6b, 0xba, 0xf2, 0x63, 0x9a, 0x19, + 0x7c, 0xae, 0xe5, 0xf5, 0xf7, 0x16, 0x6a, 0xa2, + 0x39, 0xb6, 0x7b, 0x0f, 0xc1, 0x93, 0x81, 0x1b, + 0xee, 0xb4, 0x1a, 0xea, 0xd0, 0x91, 0x2f, 0xb8, + 0x55, 0xb9, 0xda, 0x85, 0x3f, 0x41, 0xbf, 0xe0, + 0x5a, 0x58, 0x80, 0x5f, 0x66, 0x0b, 0xd8, 0x90, + 0x35, 0xd5, 0xc0, 0xa7, 0x33, 0x06, 0x65, 0x69, + 0x45, 0x00, 0x94, 0x56, 0x6d, 0x98, 0x9b, 0x76, + 0x97, 0xfc, 0xb2, 0xc2, 0xb0, 0xfe, 0xdb, 0x20, + 0xe1, 0xeb, 0xd6, 0xe4, 0xdd, 0x47, 0x4a, 0x1d, + 0x42, 0xed, 0x9e, 0x6e, 0x49, 0x3c, 0xcd, 0x43, + 0x27, 0xd2, 0x07, 0xd4, 0xde, 0xc7, 0x67, 0x18, + 0x89, 0xcb, 0x30, 0x1f, 0x8d, 0xc6, 0x8f, 0xaa, + 0xc8, 0x74, 0xdc, 0xc9, 0x5d, 0x5c, 0x31, 0xa4, + 0x70, 0x88, 0x61, 0x2c, 0x9f, 0x0d, 0x2b, 0x87, + 0x50, 0x82, 0x54, 0x64, 0x26, 0x7d, 0x03, 0x40, + 0x34, 0x4b, 0x1c, 0x73, 0xd1, 0xc4, 0xfd, 0x3b, + 0xcc, 0xfb, 0x7f, 0xab, 0xe6, 0x3e, 0x5b, 0xa5, + 0xad, 0x04, 0x23, 0x9c, 0x14, 0x51, 0x22, 0xf0, + 0x29, 0x79, 0x71, 0x7e, 0xff, 0x8c, 0x0e, 0xe2, + 0x0c, 0xef, 0xbc, 0x72, 0x75, 0x6f, 0x37, 0xa1, + 0xec, 0xd3, 0x8e, 0x62, 0x8b, 0x86, 0x10, 0xe8, + 0x08, 0x77, 0x11, 0xbe, 0x92, 0x4f, 0x24, 0xc5, + 0x32, 0x36, 0x9d, 0xcf, 0xf3, 0xa6, 0xbb, 0xac, + 0x5e, 0x6c, 0xa9, 0x13, 0x57, 0x25, 0xb5, 0xe3, + 0xbd, 0xa8, 0x3a, 0x01, 0x05, 0x59, 0x2a, 0x46 +}; + +typedef unsigned char fort_keysched[32*4]; + +/* do the key schedule work once for efficency */ +static void +fort_skipKeySchedule(FORTSkipjackKeyPtr key,fort_keysched keysched) +{ + unsigned char *keyptr = key; + unsigned char *first = keyptr +sizeof(FORTSkipjackKey)-1; + int i; + + keyptr = first; + + for (i=0; i < (32*4); i++) { + keysched[i] = *keyptr--; + if (keyptr < key) keyptr = first; + } + return; +} + +static void +fort_clearShedule(fort_keysched keysched) +{ + PORT_Memset(keysched, 0, sizeof(keysched)); +} + + +static unsigned int +G(fort_keysched cv, int k, unsigned int wordIn) +{ + unsigned char g1, g2, g3, g4, g5, g6; + + g1 = (unsigned char) (wordIn >> 8) & 0xff; + g2 = (unsigned char) wordIn & 0xff; + + g3 = F[g2^cv[4*k]]^g1; + g4 = F[g3^cv[4*k+1]]^g2; + g5 = F[g4^cv[4*k+2]]^g3; + g6 = F[g5^cv[4*k+3]]^g4; + + return ((g5<<8)+g6); +} + +static unsigned int +G1(fort_keysched cv, int k, unsigned int wordIn) +{ + unsigned char g1, g2, g3, g4, g5, g6; + + g5 = (unsigned char) (wordIn >> 8) & 0xff; + g6 = (unsigned char) wordIn & 0xff; + + g4 = F[g5^cv[4*k+3]]^g6; + g3 = F[g4^cv[4*k+2]]^g5; + g2 = F[g3^cv[4*k+1]]^g4; + g1 = F[g2^cv[4*k]]^g3; + + return ((g1<<8)+g2); +} + +static void +ruleA(fort_keysched cv,int round,unsigned int *w) +{ + unsigned int w4; + int i; + + for(i=0; i<8; i++) { + int k = round*16+i; + int counter = k+1; + + w4 = w[4]; + w[4] = w[3]; + w[3] = w[2]; + w[2] = G(cv,k,w[1]); + w[1] = G(cv,k,w[1]) ^ w4 ^ counter; + } + return; +} + +static void +ruleB(fort_keysched cv,int round,unsigned int *w) +{ + unsigned int w4; + int i; + + for(i=0; i<8; i++) { + int k = round*16+i+8; + int counter = k+1; + + w4 = w[4]; + w[4] = w[3]; + w[3] = w[1] ^ w[2] ^ counter; + w[2] = G(cv,k,w[1]); + w[1] = w4; + } + return; +} + +static void +ruleA1(fort_keysched cv,int round,unsigned int *w) +{ + unsigned int w4; + int i; + + for(i=7; i>=0; i--) { + int k = round*16+i; + int counter = k+1; + + w4 = w[4]; + w[4] = w[1] ^ w[2] ^ counter; + w[1] = G1(cv,k,w[2]); + w[2] = w[3]; + w[3] = w4; + } + return; +} + +static void +ruleB1(fort_keysched cv,int round,unsigned int *w) +{ + unsigned int w4; + int i; + + for(i=7; i>=0; i--) { + int k = round*16+i+8; + int counter = k+1; + + w4 = w[4]; + w[4] = w[1]; + w[1] = G1(cv,k,w[2]); + w[2] = G1(cv,k,w[2]) ^ w[3] ^ counter; + w[3] = w4; + } + return; +} + + +static void +fort_doskipD(fort_keysched cv,unsigned char *cipherIn, + unsigned char *plainOut) { + unsigned int w[5]; /* ignore w[0] so the code matches the doc */ + + /* initial byte swap */ + w[1]=(cipherIn[7]<<8)+cipherIn[6]; + w[2]=(cipherIn[5]<<8)+cipherIn[4]; + w[3]=(cipherIn[3]<<8)+cipherIn[2]; + w[4]=(cipherIn[1]<<8)+cipherIn[0]; + + ruleB1(cv,1,w); + ruleA1(cv,1,w); + ruleB1(cv,0,w); + ruleA1(cv,0,w); + + /* final byte swap */ + plainOut[0] = w[4] & 0xff; + plainOut[1] = (w[4] >> 8) & 0xff; + plainOut[2] = w[3] & 0xff; + plainOut[3] = (w[3] >> 8) & 0xff; + plainOut[4] = w[2] & 0xff; + plainOut[5] = (w[2] >> 8) & 0xff; + plainOut[6] = w[1] & 0xff; + plainOut[7] = (w[1] >> 8) & 0xff; + return; +} + +static void +fort_doskipE(fort_keysched cv,unsigned char *cipherIn, + unsigned char *plainOut) { + unsigned int w[5]; /* ignore w[0] so the code matches the doc */ + + /* initial byte swap */ + w[1]=(cipherIn[7]<<8)+cipherIn[6]; + w[2]=(cipherIn[5]<<8)+cipherIn[4]; + w[3]=(cipherIn[3]<<8)+cipherIn[2]; + w[4]=(cipherIn[1]<<8)+cipherIn[0]; + + ruleA(cv,0,w); + ruleB(cv,0,w); + ruleA(cv,1,w); + ruleB(cv,1,w); + + /* final byte swap */ + plainOut[0] = w[4] & 0xff; + plainOut[1] = (w[4] >> 8) & 0xff; + plainOut[2] = w[3] & 0xff; + plainOut[3] = (w[3] >> 8) & 0xff; + plainOut[4] = w[2] & 0xff; + plainOut[5] = (w[2] >> 8) & 0xff; + plainOut[6] = w[1] & 0xff; + plainOut[7] = (w[1] >> 8) & 0xff; + return; +} + +/* Checksums are calculated by encrypted a fixed string with the key, then + * taking 16 bytes of the result from the block */ +static int +fort_CalcKeyChecksum(FORTSkipjackKeyPtr key, unsigned char *sum) { + unsigned char ckdata[8] = { + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 }; + unsigned char ckres[8]; + fort_keysched keysched; + + + fort_skipKeySchedule(key,keysched); + + fort_doskipE(keysched,ckdata,ckres); + fort_clearShedule(keysched); + PORT_Memcpy(sum,&ckres[1],2); + return CI_OK; +} + +/* These function actually implements skipjack CBC Decrypt */ +int +fort_skipjackDecrypt(FORTSkipjackKeyPtr key, unsigned char *iv, + unsigned long size, unsigned char *cipherIn, + unsigned char *plainOut) { + unsigned char ivdata1[SKIPJACK_BLOCK_SIZE]; + unsigned char ivdata2[SKIPJACK_BLOCK_SIZE]; + unsigned char *lastiv, *nextiv, *tmpiv; + fort_keysched keysched; + + /* do the key schedule work once for efficency */ + fort_skipKeySchedule(key,keysched); + + /* As we decrypt, we need to save the last block so that we can + * Xor it out of decrypted text to get the real plain text. We actually + * have to save it because cipherIn and plainOut may point to the same + * buffer. */ + lastiv =ivdata1; + nextiv = ivdata2; + PORT_Memcpy(lastiv,iv,SKIPJACK_BLOCK_SIZE); + while (size >= SKIPJACK_BLOCK_SIZE) { + /* save the IV for the next block */ + PORT_Memcpy(nextiv,cipherIn,SKIPJACK_BLOCK_SIZE); + fort_doskipD(keysched,cipherIn,plainOut); + /* xor out the last IV */ + fort_XorIV(plainOut,plainOut,lastiv); + + /* swap the IV buffers */ + tmpiv = lastiv; + lastiv = nextiv; + nextiv =tmpiv; + + /* increment the loop pointers... be sure to get the input, output, + * and size (decrement) each fortdoskipD operates on an entire block*/ + cipherIn += SKIPJACK_BLOCK_SIZE; + plainOut += SKIPJACK_BLOCK_SIZE; + size -= SKIPJACK_BLOCK_SIZE; + } + fort_clearShedule(keysched); /* don't leave the key lying around the stack*/ + if (size != 0) return CI_INV_SIZE; + return CI_OK; +} + +/* These function actually implements skipjack CBC Encrypt */ +int +fort_skipjackEncrypt(FORTSkipjackKeyPtr key, unsigned char *iv, + unsigned long size, unsigned char *plainIn, + unsigned char *cipherOut) { + unsigned char *tmpiv; + fort_keysched keysched; + unsigned char plain[SKIPJACK_BLOCK_SIZE]; + + fort_skipKeySchedule(key,keysched); + tmpiv = iv; + while (size >= SKIPJACK_BLOCK_SIZE) { + /* We Xor into a temp buffer because we don't want to modify plainIn, + * doing so may make the caller very unhappy:). */ + fort_XorIV(plain,plainIn,tmpiv); + fort_doskipE(keysched,plain,cipherOut); + tmpiv = cipherOut; + cipherOut += SKIPJACK_BLOCK_SIZE; + plainIn += SKIPJACK_BLOCK_SIZE; + size -= SKIPJACK_BLOCK_SIZE; + } + fort_clearShedule(keysched); /* don't leave the key lying around the stack*/ + if (size != 0) return CI_INV_SIZE; + return CI_OK; +} + + + +/* + * unwrap is used for key generation and mixing + */ +int +fort_skipjackUnwrap(FORTSkipjackKeyPtr key,unsigned long len, + unsigned char *cipherIn, unsigned char *plainOut) { + unsigned char low[10]; + fort_keysched keysched; + int i,ret; + + /* unwrap can only unwrap 80 bit symetric keys and 160 private keys + * sometimes these values have checksums. When they do, we should verify + * those checksums. */ + switch (len) { + case 20: /* private key */ + case 24: /* private key with checksum */ + ret = fort_skipjackUnwrap(key,len/2,cipherIn,plainOut); + if (ret != CI_OK) return ret; + ret = fort_skipjackUnwrap(key,len/2,&cipherIn[len/2],low); + + /* unmunge the low word */ + for (i=0; i < 10; i++) { + low[i] = low[i] ^ plainOut[i]; + } + + /* the unwrap will fail above because the checkword is on + * low, not low ^ high. + */ + if (ret == CI_CHECKWORD_FAIL) { + unsigned char checksum[2]; + + ret = fort_CalcKeyChecksum(low,checksum); + if (ret != CI_OK) return ret; + if (PORT_Memcmp(checksum,&cipherIn[len-2],2) != 0) { + return CI_CHECKWORD_FAIL; + } + } + if (ret != CI_OK) return ret; + + /* re-order the low word */ + PORT_Memcpy(&plainOut[10],&low[8],2); + PORT_Memcpy(&plainOut[12],&low[0],8); + return CI_OK; + case 10: /* 80 bit skipjack key */ + case 12: /* 80 bit skipjack key with checksum */ + fort_skipKeySchedule(key,keysched); + fort_doskipD(keysched,cipherIn,plainOut); + plainOut[8] = cipherIn[8] ^ plainOut[0]; + plainOut[9] = cipherIn[9] ^ plainOut[1]; + fort_doskipD(keysched,plainOut,plainOut); + fort_clearShedule(keysched); + /* if we have a checkum, verify it */ + if (len == 12) { + unsigned char checksum[2]; + + ret = fort_CalcKeyChecksum(plainOut,checksum); + if (ret != CI_OK) return ret; + if (PORT_Memcmp(checksum,&cipherIn[10],2) != 0) { + return CI_CHECKWORD_FAIL; + } + } + return CI_OK; + default: + break; + } + return CI_INV_SIZE; +} + +/* + * unwrap is used for key generation and mixing + */ +int +fort_skipjackWrap(FORTSkipjackKeyPtr key,unsigned long len, + unsigned char *plainIn, unsigned char *cipherOut) { + unsigned char low[10]; + unsigned char checksum[2]; + fort_keysched keysched; + int i,ret; + + + /* NOTE: length refers to the target in the case of wrap */ + /* Wrap can only Wrap 80 bit symetric keys and 160 private keys + * sometimes these values have checksums. When they do, we should verify + * those checksums. */ + switch (len) { + case 20: /* private key */ + case 24: /* private key with checksum */ + /* re-order the low word */ + PORT_Memcpy(&low[8],&plainIn[10],2); + PORT_Memcpy(&low[0],&plainIn[12],8); + if (len == 24) { + ret = fort_CalcKeyChecksum(low,checksum); + if (ret != CI_OK) return ret; + } + /* munge the low word */ + for (i=0; i < 10; i++) { + low[i] = low[i] ^ plainIn[i]; + } + ret = fort_skipjackWrap(key,len/2,plainIn,cipherOut); + ret = fort_skipjackWrap(key,len/2,low,&cipherOut[len/2]); + if (len == 24) { + PORT_Memcpy(&cipherOut[len - 2], checksum, sizeof(checksum)); + } + + return CI_OK; + case 10: /* 80 bit skipjack key */ + case 12: /* 80 bit skipjack key with checksum */ + + fort_skipKeySchedule(key,keysched); + fort_doskipE(keysched,plainIn,cipherOut); + cipherOut[8] = plainIn[8] ^ cipherOut[0]; + cipherOut[9] = plainIn[9] ^ cipherOut[1]; + fort_doskipE(keysched,cipherOut,cipherOut); + fort_clearShedule(keysched); + /* if we need a checkum, get it */ + if (len == 12) { + ret = fort_CalcKeyChecksum(plainIn,&cipherOut[10]); + if (ret != CI_OK) return ret; + } + return CI_OK; + default: + break; + } + return CI_INV_SIZE; +} + diff --git a/security/nss/lib/fortcrypt/swfort/swflib.c b/security/nss/lib/fortcrypt/swfort/swflib.c new file mode 100644 index 000000000..cc4647006 --- /dev/null +++ b/security/nss/lib/fortcrypt/swfort/swflib.c @@ -0,0 +1,1028 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +/* + * implement the MACI calls as Software Fortezza Calls. + * only do the ones Nescape Needs. This provides a single software slot, + * with 100 key registers, and 50 backup Ra private registers. Since we only + * create one session per slot, this implementation only uses one session. + * One future enhancement may be to try to improve on this for better threading + * support. + */ + +#include "prtypes.h" +#include "prio.h" + +#include "swforti.h" +#include "keytlow.h" +/* #include "dh.h" */ +#include "blapi.h" +#include "maci.h" +/* #include "dsa.h" */ +/* #include "hasht.h" */ +#include "secitem.h" +#include "secrng.h" +#include "keylow.h" +#include "secder.h" + +#ifdef XP_UNIX +#include <unistd.h> +#endif + +#ifndef O_BINARY +#define O_BINARY 0 +#endif + + +/* currently we only support one software token. In the future we can use the + * session to determin which of many possible tokens we are talking about. + * all the calls which need tokens take a pointer to the software token as a + * target. + */ +static FORTSWToken *swtoken = NULL; + +#define SOCKET_ID 1 + + +/* can't change the pin on SW fortezza for now */ +int +MACI_ChangePIN(HSESSION session, int PINType, CI_PIN CI_FAR pOldPIN, + CI_PIN CI_FAR pNewPin) +{ + return CI_INV_STATE; +} + + +/* + * Check pin checks the pin, then logs the user in or out depending on if + * the pin succedes. The General implementation would support both SSO and + * User mode our's only needs User mode. Pins are checked by whether or not + * they can produce our valid Ks for this 'card'. + */ +int +MACI_CheckPIN(HSESSION session, int PINType, CI_PIN CI_FAR pin) +{ + FORTSkipjackKeyPtr Ks; + FORTSWFile *config_file = NULL; + FORTSkipjackKey seed; + unsigned char pinArea[13]; + unsigned char *padPin = NULL; + + /* This SW module can only log in as USER */ + if (PINType != CI_USER_PIN) return CI_INV_TYPE; + + if (swtoken == NULL) return CI_NO_CARD; + /* we can't check a pin if we haven't been initialized yet */ + if (swtoken->config_file == NULL) return CI_NO_CARD; + config_file = swtoken->config_file; + + /* Make sure the pin value meets minimum lengths */ + if (PORT_Strlen((char *)pin) < 12) { + PORT_Memset(pinArea, ' ', sizeof(pinArea)); + PORT_Memcpy(pinArea,pin,PORT_Strlen((char *)pin)); + pinArea[12] = 0; + padPin = pinArea; + } + + /* get the Ks by unwrapping it from the memphrase with the pbe generated + * from the pin */ + Ks = fort_CalculateKMemPhrase(config_file, + &config_file->fortezzaPhrase, (char *)pin, NULL); + + if (Ks == 0) { + Ks = fort_CalculateKMemPhrase(config_file, + &config_file->fortezzaPhrase, (char *)padPin, NULL); + if (Ks == 0) { + PORT_Memset(pinArea, 0, sizeof(pinArea)); + fort_Logout(swtoken); + return CI_FAIL; + } + } + + /* use Ks and hash to verify that pin is correct */ + if (! fort_CheckMemPhrase(config_file, &config_file->fortezzaPhrase, + (char *)pin, Ks) ) { + if ((padPin == NULL) || + ! fort_CheckMemPhrase(config_file, &config_file->fortezzaPhrase, + (char *)padPin, Ks) ) { + PORT_Memset(pinArea, 0, sizeof(pinArea)); + fort_Logout(swtoken); + return CI_FAIL; + } + } + + PORT_Memset(pinArea, 0, sizeof(pinArea)); + + + /* OK, add the random Seed value into the random number generator */ + fort_skipjackUnwrap(Ks,config_file->wrappedRandomSeed.len, + config_file->wrappedRandomSeed.data,seed); + RNG_RandomUpdate(seed,sizeof(seed)); + + /* it is, go ahead and log in */ + swtoken->login = PR_TRUE; + /* Ks is always stored in keyReg[0] when we log in */ + PORT_Memcpy(swtoken->keyReg[0].data, Ks, sizeof (FORTSkipjackKey)); + swtoken->keyReg[0].present = PR_TRUE; + PORT_Memset(Ks, 0, sizeof(FORTSkipjackKey)); + PORT_Free(Ks); + + + return CI_OK; +} + +/* + * close an open socket. Power_Down flag is set when we want to reset the + * cards complete state. + */ +int +MACI_Close(HSESSION session, unsigned int flags, int socket) +{ + if (socket != SOCKET_ID) return CI_BAD_CARD; + if (swtoken == NULL) return CI_BAD_CARD; + + if (flags == CI_POWER_DOWN_FLAG) { + fort_Logout(swtoken); + } + return CI_OK; +} + +/* + * Decrypt keeps track of it's own IV. + */ +int +MACI_Decrypt(HSESSION session, unsigned int size, CI_DATA cipherIn, + CI_DATA plainOut) +{ + int ret; + unsigned char IV[SKIPJACK_BLOCK_SIZE]; + + if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret; + if ((ret = fort_KeyOK(swtoken,swtoken->key,PR_TRUE)) != CI_OK) return ret; + + /*fort_AddNoise();*/ + + /* save the IV, before we potentially trash the new one when we decrypt. + * (it's permissible to decrypt into the cipher text buffer by passing the + * same buffers for both cipherIn and plainOut. + */ + PORT_Memcpy(IV,swtoken->IV, sizeof(IV)); + fort_UpdateIV(cipherIn,size,swtoken->IV); + return fort_skipjackDecrypt(swtoken->keyReg[swtoken->key].data, + IV,size,cipherIn,plainOut); +} + +/* + * Clear a key from one of the key registers (indicated by index). + * return an error if no key exists. + */ +int +MACI_DeleteKey(HSESSION session, int index) +{ + int ret; + if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret; + + /* can't delete Ks */ + if (index == 0) return CI_INV_KEY_INDEX; + + if ((ret = fort_KeyOK(swtoken,index,PR_TRUE)) != CI_OK) return ret; + fort_ClearKey(&swtoken->keyReg[index]); + return CI_OK; +} + + +/* + * encrypt some blocks of data and update the IV. + */ +int +MACI_Encrypt(HSESSION session, unsigned int size, CI_DATA plainIn, + CI_DATA cipherOut) +{ + int ret; + if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret; + if ((ret = fort_KeyOK(swtoken,swtoken->key,PR_TRUE)) != CI_OK) return ret; + + /*fort_AddNoise();*/ + + ret = fort_skipjackEncrypt(swtoken->keyReg[swtoken->key].data, + swtoken->IV,size,plainIn,cipherOut); + fort_UpdateIV(cipherOut,size,swtoken->IV); + + return ret; + +} + +/* + * create a new IV and encode it. + */ + +static char *leafbits="THIS IS NOT LEAF"; + +int +MACI_GenerateIV(HSESSION Session, CI_IV CI_FAR pIV) +{ + int ret; + + if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret; + if ((ret = fort_KeyOK(swtoken,swtoken->key,PR_TRUE)) != CI_OK) return ret; + + ret = fort_GenerateRandom(swtoken->IV,SKIPJACK_BLOCK_SIZE); + if (ret != CI_OK) return ret; + + PORT_Memcpy(pIV,leafbits,SKIPJACK_LEAF_SIZE); + PORT_Memcpy(&pIV[SKIPJACK_LEAF_SIZE],swtoken->IV,SKIPJACK_BLOCK_SIZE); + + return CI_OK; +} + + +/* + * create a new Key + */ +int +MACI_GenerateMEK(HSESSION session, int index, int reserved) +{ + int ret; + if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret; + if ((ret = fort_KeyOK(swtoken,index,PR_FALSE)) != CI_OK) return ret; + + ret = fort_GenerateRandom(swtoken->keyReg[index].data, + sizeof (swtoken->keyReg[index].data)); + if (ret == CI_OK) swtoken->keyReg[index].present = PR_TRUE; + + return ret; +} + +/* + * build a new Ra/ra pair for a KEA exchange. + */ +int +MACI_GenerateRa(HSESSION session, CI_RA CI_FAR pRa) +{ + int ret; + int counter; + int RaLen,raLen; + DSAPrivateKey *privKey = NULL; + PQGParams params; + SECStatus rv; + int crv = CI_EXEC_FAIL; + fortSlotEntry *certEntry = NULL; + unsigned char *unsignedRa = NULL; + unsigned char *unsignedra = NULL; + fortKeyInformation *key_info = NULL; + + + if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret; + /* make sure the personality is set */ + if (swtoken->certIndex == 0) return CI_INV_STATE; + + /* pick next Ra circular buffer */ + counter = swtoken->nextRa; + swtoken->nextRa++; + if (swtoken->nextRa >= MAX_RA_SLOTS) swtoken->nextRa = 0; + + /* now get the params for diffie -helman key gen */ + certEntry = fort_GetCertEntry(swtoken->config_file,swtoken->certIndex); + if (certEntry == NULL) return CI_INV_CERT_INDEX; + if (certEntry->exchangeKeyInformation) { + key_info = certEntry->exchangeKeyInformation; + } else { + key_info = certEntry->signatureKeyInformation; + } + if (key_info == NULL) return CI_NO_X; + + /* Generate Diffie Helman key Pair -- but we use DSA key gen to do it */ + rv = SECITEM_CopyItem(NULL,¶ms.prime,&key_info->p); + if (rv != SECSuccess) return CI_EXEC_FAIL; + rv = SECITEM_CopyItem(NULL,¶ms.subPrime,&key_info->q); + if (rv != SECSuccess) return CI_EXEC_FAIL; + rv = SECITEM_CopyItem(NULL,¶ms.base,&key_info->g); + if (rv != SECSuccess) return CI_EXEC_FAIL; + + /* KEA uses DSA like key generation with short DSA keys that have to + * maintain a relationship to q */ + rv = DSA_NewKey(¶ms, &privKey); + SECITEM_FreeItem(¶ms.prime,PR_FALSE); + SECITEM_FreeItem(¶ms.subPrime,PR_FALSE); + SECITEM_FreeItem(¶ms.base,PR_FALSE); + if (rv != SECSuccess) return CI_EXEC_FAIL; + + /* save private key, public key, and param in Ra Circular buffer */ + unsignedRa = privKey->publicValue.data; + RaLen = privKey->publicValue.len; + while ((unsignedRa[0] == 0) && (RaLen > CI_RA_SIZE)) { + unsignedRa++; + RaLen--; + } + if (RaLen > CI_RA_SIZE) goto loser; + + unsignedra = privKey->privateValue.data; + raLen = privKey->privateValue.len; + while ((unsignedra[0] == 0) && (raLen > sizeof(fortRaPrivate))) { + unsignedra++; + raLen--; + } + + if (raLen > sizeof(fortRaPrivate)) goto loser; + + PORT_Memset(swtoken->RaValues[counter].private, 0, sizeof(fortRaPrivate)); + PORT_Memcpy( + &swtoken->RaValues[counter].private[sizeof(fortRaPrivate) - raLen], + unsignedra, raLen); + PORT_Memset(pRa, 0, CI_RA_SIZE); + PORT_Memcpy(&pRa[CI_RA_SIZE-RaLen], unsignedRa, RaLen); + PORT_Memcpy(swtoken->RaValues[counter].public, pRa, CI_RA_SIZE); + crv = CI_OK; + +loser: + PORT_FreeArena(privKey->params.arena, PR_TRUE); + + return crv; +} + + +/* + * return some random data. + */ +int +MACI_GenerateRandom(HSESSION session, CI_RANDOM CI_FAR random) +{ + int ret; + if ((ret = fort_CardExists(swtoken,PR_FALSE)) != CI_OK) return ret; + return fort_GenerateRandom(random,sizeof (CI_RANDOM)); +} + + +static CI_RA Remail = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 +}; + +/* + * build a new Token exchange key using KEA. + */ +int +MACI_GenerateTEK(HSESSION hSession, int flags, int target, + CI_RA CI_FAR Ra, CI_RA CI_FAR Rb, unsigned int YSize, CI_Y CI_FAR pY ) +{ + SECKEYLowPrivateKey *key = NULL; + fortSlotEntry * certEntry; + unsigned char * w = NULL; + SECItem *q; + SECStatus rv; + int ret,i; + PRBool email = PR_TRUE; + SECItem R; /* public */ + SECItem Y; /* public */ + SECItem r; /* private */ + SECItem x; /* private */ + SECItem wItem; /* derived secret */ + fortRaPrivatePtr ra; + FORTSkipjackKey cover_key; + + unsigned char pad[10] = { 0x72, 0xf1, 0xa8, 0x7e, 0x92, + 0x82, 0x41, 0x98, 0xab, 0x0b }; + + /* verify that everything is ok with the token, keys and certs */ + if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret; + /* make sure the personality is set */ + if (swtoken->certIndex == 0) return CI_INV_STATE; + if ((ret = fort_KeyOK(swtoken,target,PR_FALSE)) != CI_OK) return ret; + + /* get the cert from the entry, then look up the key from that cert */ + certEntry = fort_GetCertEntry(swtoken->config_file,swtoken->certIndex); + if (certEntry == NULL) return CI_INV_CERT_INDEX; + key = fort_GetPrivKey(swtoken,dhKey,certEntry); + if (key == NULL) return CI_NO_X; + + if (certEntry->exchangeKeyInformation) { + q = &certEntry->exchangeKeyInformation->q; + } else { + q = &certEntry->signatureKeyInformation->q; + } + + email = (PORT_Memcmp(Rb,Remail,sizeof(Rb)) == 0) ? PR_TRUE: PR_FALSE; + + + /* load the common elements */ + Y.data = pY; + Y.len = YSize; + x.data = key->u.dh.privateValue.data; + x.len = key->u.dh.privateValue.len; + + /* now initialize the rest of the values */ + if (flags == CI_INITIATOR_FLAG) { + if (email) { + R.data = Y.data; + R.len = Y.len; + } else { + R.data = Rb; + R.len = sizeof(CI_RA); + } + ra = fort_LookupPrivR(swtoken,Ra); + if (ra == NULL) { + ret = CI_EXEC_FAIL; + goto loser; + } + r.data = ra; + r.len = sizeof(fortRaPrivate); + } else { + R.data = Ra; + R.len = sizeof(CI_RA); + if (email) { + r.data = x.data; + r.len = x.len; + } else { + ra = fort_LookupPrivR(swtoken,Rb); + if (ra == NULL) { + ret = CI_EXEC_FAIL; + goto loser; + } + r.data = ra; + r.len = sizeof(fortRaPrivate); + } + } + + + if (!KEA_Verify(&Y,&key->u.dh.prime,q)) { + ret = CI_EXEC_FAIL; + goto loser; + } + if (!KEA_Verify(&R,&key->u.dh.prime,q)) { + ret = CI_EXEC_FAIL; + goto loser; + } + + /* calculate the base key */ + rv = KEA_Derive(&key->u.dh.prime, &Y, &R, &r, &x, &wItem); + if (rv != SECSuccess) { + ret = CI_EXEC_FAIL; + goto loser; + } + + w = wItem.data; + /* use the skipjack wrapping function to 'mix' the key up */ + for (i=0; i < sizeof(FORTSkipjackKey); i++) + cover_key[i] = pad[i] ^ w[i]; + + ret = fort_skipjackWrap(cover_key,sizeof(FORTSkipjackKey), + &w[sizeof(FORTSkipjackKey)],swtoken->keyReg[target].data); + if (ret != CI_OK) goto loser; + + swtoken->keyReg[target].present = PR_TRUE; + + ret = CI_OK; +loser: + if (w) PORT_Free(w); + if (key) SECKEY_LowDestroyPrivateKey(key); + + return ret; +} + + +/* + * return the bytes of a certificate. + */ +int +MACI_GetCertificate(HSESSION hSession, int certIndex, + CI_CERTIFICATE CI_FAR cert) +{ + int len; + int ret; + fortSlotEntry *certEntry = NULL; + + if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret; + + certEntry = fort_GetCertEntry(swtoken->config_file,certIndex); + if (certEntry == NULL) return CI_INV_CERT_INDEX; + + len = certEntry->certificateData.dataEncryptedWithKs.len; + PORT_Memset(cert,0,sizeof(CI_CERTIFICATE)); + PORT_Memcpy(cert, certEntry->certificateData.dataEncryptedWithKs.data,len); + + /* Ks is always stored in keyReg[0] when we log in */ + return fort_skipjackDecrypt(swtoken->keyReg[0].data, + &certEntry->certificateData.dataIV.data[SKIPJACK_LEAF_SIZE], + len,cert,cert); +} + + +/* + * return out sofware configuration bytes. Those field not used by the PKCS #11 + * module may not be filled in exactly. + */ +#define NETSCAPE "Netscape Communications Corp " +#define PRODUCT "Netscape Software FORTEZZA Lib " +#define SOFTWARE "Software FORTEZZA Implementation" + +int +MACI_GetConfiguration(HSESSION hSession, CI_CONFIG_PTR config) +{ + config->LibraryVersion = 0x0100; + config->ManufacturerVersion = 0x0100; + PORT_Memcpy(config->ManufacturerName,NETSCAPE,sizeof(NETSCAPE)); + PORT_Memcpy(config->ProductName,PRODUCT,sizeof(PRODUCT)); + PORT_Memcpy(config->ProcessorType,SOFTWARE,sizeof(SOFTWARE)); + config->UserRAMSize = 0; + config->LargestBlockSize = 0x10000; + config->KeyRegisterCount = KEY_REGISTERS; + config->CertificateCount = + swtoken ? fort_GetCertCount(swtoken->config_file): 0; + config->CryptoCardFlag = 0; + config->ICDVersion = 0; + config->ManufacturerSWVer = 0x0100; + config->DriverVersion = 0x0100; + return CI_OK; +} + +/* + * return a list of all the personalities (up to the value 'EntryCount') + */ +int +MACI_GetPersonalityList(HSESSION hSession, int EntryCount, + CI_PERSON CI_FAR personList[]) +{ + int count; + int i,ret; + FORTSWFile *config_file = NULL; + unsigned char tmp[32]; + + if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret; + config_file = swtoken->config_file; + + /* search for the index */ + count= fort_GetCertCount(config_file); + + /* don't return more than the user asked for */ + if (count > EntryCount) count = EntryCount; + for (i=0; i < count ;i ++) { + int len, dataLen; + personList[i].CertificateIndex = + config_file->slotEntries[i]->certIndex; + len = config_file->slotEntries[i]->certificateLabel. + dataEncryptedWithKs.len; + if (len > sizeof(tmp)) len = sizeof(tmp); + PORT_Memset(personList[i].CertLabel, ' ', + sizeof(personList[i].CertLabel)); + PORT_Memcpy(tmp, + config_file->slotEntries[i]-> + certificateLabel.dataEncryptedWithKs.data, + len); + /* Ks is always stored in keyReg[0] when we log in */ + ret = fort_skipjackDecrypt(swtoken->keyReg[0].data, + &config_file->slotEntries[i]-> + certificateLabel.dataIV.data[SKIPJACK_LEAF_SIZE],len, + tmp,tmp); + if (ret != CI_OK) return ret; + dataLen = DER_GetInteger(&config_file->slotEntries[i]-> + certificateLabel.length); + if (dataLen > sizeof(tmp)) dataLen = sizeof(tmp); + PORT_Memcpy(personList[i].CertLabel, tmp, dataLen); + personList[i].CertLabel[32] = 0; + personList[i].CertLabel[33] = 0; + personList[i].CertLabel[34] = 0; + personList[i].CertLabel[35] = 0; + } + return CI_OK; +} + + +/* + * get a new session ID. This function is only to make the interface happy, + * the PKCS #11 module only uses one session per token. + */ +int +MACI_GetSessionID(HSESSION *session) +{ + *session = 1; + return CI_OK; +} + +/* + * return the current card state. + */ +int +MACI_GetState(HSESSION hSession, CI_STATE_PTR state) +{ + int ret; + if ((ret = fort_CardExists(swtoken,PR_FALSE)) != CI_OK) return ret; + *state = fort_GetState(swtoken); + return CI_OK; +} + +/* + * return the status. NOTE that KeyRegisterFlags and CertificateFlags are never + * really used by the PKCS #11 module, so they are not implemented. + */ +int +MACI_GetStatus(HSESSION hSession, CI_STATUS_PTR status) +{ + int ret; + FORTSWFile *config_file = NULL; + + if ((ret = fort_CardExists(swtoken,PR_FALSE)) != CI_OK) return ret; + config_file = swtoken->config_file; + status->CurrentSocket = 1; + status->LockState = swtoken->lock; + PORT_Memcpy(status->SerialNumber, + config_file->serialID.data, config_file->serialID.len); + status->CurrentState = fort_GetState(swtoken); + status->DecryptionMode = CI_CBC64_MODE; + status->EncryptionMode = CI_CBC64_MODE; + status->CurrentPersonality = swtoken->certIndex; + status->KeyRegisterCount = KEY_REGISTERS; + /* our code doesn't use KeyRegisters, which is good, because there's not + * enough of them .... */ + PORT_Memset(status->KeyRegisterFlags,0,sizeof(status->KeyRegisterFlags)); + status->CertificateCount = fort_GetCertCount(config_file); + PORT_Memset(status->CertificateFlags,0,sizeof(status->CertificateFlags)); + PORT_Memset(status->Flags,0,sizeof(status->Flags)); + + return CI_OK; +} + +/* + * add the time call because the PKCS #11 module calls it, but always pretend + * the clock is bad, so it never uses the returned time. + */ +int +MACI_GetTime(HSESSION hSession, CI_TIME CI_FAR time) +{ + return CI_BAD_CLOCK; +} + + +/* This function is copied from NSPR so that the PKCS #11 module can be + * independent of NSPR */ +PRInt32 local_getFileInfo(const char *fn, PRFileInfo *info); + +/* + * initialize the SW module, and return the number of slots we support (1). + */ +int +MACI_Initialize(int CI_FAR *count) +{ + char *filename = NULL; + SECItem file; + FORTSignedSWFile *decode_file = NULL; + PRFileInfo info; + /*PRFileDesc *fd = NULL;*/ + int fd = -1; + PRStatus err; + int ret = CI_OK; + int fcount; + + file.data = NULL; + file.len = 0; + + *count = 1; + + /* allocate swtoken structure */ + swtoken = PORT_ZNew(FORTSWToken); + if (swtoken == NULL) return CI_OUT_OF_MEMORY; + + filename = (char *)fort_LookupFORTEZZAInitFile(); + if (filename == NULL) { + ret = CI_BAD_READ; + goto failed; + } + + fd = open(filename,O_RDONLY|O_BINARY,0); + if (fd < 0) { + ret = CI_BAD_READ; + goto failed; + } + + err = local_getFileInfo(filename,&info); + if ((err != 0) || (info.size == 0)) { + ret = CI_BAD_READ; + goto failed; + } + + file.data = PORT_ZAlloc(info.size); + if (file.data == NULL) { + ret = CI_OUT_OF_MEMORY; + goto failed; + } + + fcount = read(fd,file.data,info.size); + close(fd); fd = -1; + if (fcount != (int)info.size) { + ret = CI_BAD_READ; + goto failed; + } + + file.len = fcount; + + decode_file = FORT_GetSWFile(&file); + if (decode_file == NULL) { + ret = CI_BAD_READ; + goto failed; + } + swtoken->config_file = &decode_file->file; + + RNG_SystemInfoForRNG(); + RNG_FileForRNG(filename); + + +failed: + if (filename) PORT_Free(filename); + if (fd != -1) close(fd); + if (file.data) PORT_Free(file.data); + if (ret != CI_OK) { + if (decode_file) FORT_DestroySignedSWFile(decode_file); + if (swtoken) PORT_Free(swtoken); + swtoken = NULL; + } + + return CI_OK; +} + +/* + * load an IV from an external source. We technically should check it with the + * key we received. + */ +int +MACI_LoadIV(HSESSION session, CI_IV CI_FAR iv) +{ + int ret; + + if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret; + PORT_Memcpy(swtoken->IV,&iv[SKIPJACK_LEAF_SIZE],SKIPJACK_BLOCK_SIZE); + return CI_OK; +} + +/* implement token lock (should call PR_Monitor here) */ +int +MACI_Lock(HSESSION session, int flags) +{ + int ret; + if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret; + swtoken->lock = 1; + + return CI_OK; +} + +/* open a token. For software there isn't much to do that hasn't already been + * done by initialize. */ +int +MACI_Open(HSESSION session, unsigned int flags, int socket) +{ + if (socket != SOCKET_ID) return CI_NO_CARD; + if (swtoken == NULL) return CI_NO_CARD; + return CI_OK; +} + +/* + * Reset logs out the token... + */ +int +MACI_Reset(HSESSION session) +{ + if (swtoken) fort_Logout(swtoken); + return CI_OK; +} + +/* + * restore and encrypt/decrypt state. NOTE: there is no error checking in this + * or the save function. + */ +int +MACI_Restore(HSESSION session, int type, CI_SAVE_DATA CI_FAR data) +{ + int ret; + if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret; + PORT_Memcpy(swtoken->IV,data, sizeof (swtoken->IV)); + return CI_OK; +} + +/* + * save and encrypt/decrypt state. NOTE: there is no error checking in this + * or the restore function. + */ +int +MACI_Save(HSESSION session, int type,CI_SAVE_DATA CI_FAR data) +{ + int ret; + if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret; + PORT_Memcpy(data,swtoken->IV, sizeof (swtoken->IV)); + return CI_OK; +} + +/* + * picks a token to operate against. In our case there can be only one. + */ +int +MACI_Select(HSESSION session, int socket) +{ + if (socket == SOCKET_ID) return CKR_OK; + return CI_NO_CARD; +} + +/* + * set a register as the key to use for encrypt/decrypt operations. + */ +int +MACI_SetKey(HSESSION session, int index) +{ + int ret; + if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret; + if ((ret = fort_KeyOK(swtoken,index,PR_TRUE)) != CI_OK) return ret; + + swtoken->key = index; + return CI_OK; +} + +/* + * only CBC64 is supported. Keep setmode for compatibility */ +int +MACI_SetMode(HSESSION session, int type, int mode) +{ + if (mode != CI_CBC64_MODE) return CI_INV_MODE; + return CI_OK; +} + +/* set the personality to use for sign/verify */ +int +MACI_SetPersonality(HSESSION session, int cert) +{ + int ret; + fortSlotEntry *certEntry = NULL; + + if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret; + + certEntry = fort_GetCertEntry(swtoken->config_file,cert); + if ((certEntry == NULL) || + ((certEntry->exchangeKeyInformation == NULL) && + (certEntry->signatureKeyInformation == NULL)) ) + return CI_INV_CERT_INDEX; + swtoken->certIndex = cert; + return CI_OK; +} + + +/* DSA sign some data */ +int +MACI_Sign(HSESSION session, CI_HASHVALUE CI_FAR hash, CI_SIGNATURE CI_FAR sig) +{ + SECKEYLowPrivateKey *key = NULL; + fortSlotEntry * certEntry = NULL; + int ret = CI_OK; + SECStatus rv; + SECItem signItem; + SECItem hashItem; + unsigned char random[DSA_SUBPRIME_LEN]; + + /* standard checks */ + if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret; + /* make sure the personality is set */ + if (swtoken->certIndex == 0) return CI_INV_STATE; + + /* get the current personality */ + certEntry = fort_GetCertEntry(swtoken->config_file,swtoken->certIndex); + if (certEntry == NULL) return CI_INV_CERT_INDEX; + + /* extract the private key from the personality */ + ret = CI_OK; + key = fort_GetPrivKey(swtoken,dsaKey,certEntry); + if (key == NULL) { + ret = CI_NO_X; + goto loser; + } + + /* create a random value for the signature */ + ret = fort_GenerateRandom(random, sizeof(random)); + if (ret != CI_OK) goto loser; + + /* Sign with that private key */ + signItem.data = sig; + signItem.len = DSA_SIGNATURE_LEN; + + hashItem.data = hash; + hashItem.len = SHA1_LENGTH; + + rv = DSA_SignDigestWithSeed(&key->u.dsa, &signItem, &hashItem, random); + if (rv != SECSuccess) { + ret = CI_EXEC_FAIL; + } + + /* clean up */ +loser: + if (key != NULL) SECKEY_LowDestroyPrivateKey(key); + + return ret; +} + +/* + * clean up after ourselves. + */ +int +MACI_Terminate(HSESSION session) +{ + if (swtoken == NULL) return CI_OUT_OF_MEMORY; + + /* clear all the keys */ + fort_Logout(swtoken); + + FORT_DestroySWFile(swtoken->config_file); + PORT_Free(swtoken); + swtoken = NULL; + return CI_OK; +} + + + +/* implement token unlock (should call PR_Monitor here) */ +int +MACI_Unlock(HSESSION session) +{ + int ret; + if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret; + swtoken->lock = 0; + return CI_OK; +} + +/* + * unwrap a key into our software token. NOTE: this function does not + * verify that the wrapping key is Ks or a TEK. This is because our higher + * level software doesn't try to wrap MEKs with MEKs. If this API was exposed + * generically, then we would have to worry about things like this. + */ +int +MACI_UnwrapKey(HSESSION session, int wrapKey, int target, + CI_KEY CI_FAR keyData) +{ + int ret = CI_OK; + + if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret; + if ((ret = fort_KeyOK(swtoken,target,PR_FALSE)) != CI_OK) return ret; + if ((ret = fort_KeyOK(swtoken,wrapKey,PR_TRUE)) != CI_OK) return ret; + ret = fort_skipjackUnwrap(swtoken->keyReg[wrapKey].data, + sizeof(CI_KEY), keyData, swtoken->keyReg[target].data); + if (ret != CI_OK) goto loser; + + swtoken->keyReg[target].present = PR_TRUE; + +loser: + return ret; +} + +/* + * Wrap a key out of our software token. NOTE: this function does not + * verify that the wrapping key is Ks or a TEK, or that the source key is + * a MEK. This is because our higher level software doesn't try to wrap MEKs + * with MEKs, or wrap out TEKS and Ks. If this API was exposed + * generically, then we would have to worry about things like this. + */ +int +MACI_WrapKey(HSESSION session, int wrapKey, int source, CI_KEY CI_FAR keyData) +{ + int ret; + + if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret; + if ((ret = fort_KeyOK(swtoken,source,PR_TRUE)) != CI_OK) return ret; + if ((ret = fort_KeyOK(swtoken,wrapKey,PR_TRUE)) != CI_OK) return ret; + ret = fort_skipjackWrap(swtoken->keyReg[wrapKey].data, + sizeof(CI_KEY), swtoken->keyReg[source].data,keyData); + + return ret; +} + diff --git a/security/nss/lib/fortcrypt/swfort/swfort.h b/security/nss/lib/fortcrypt/swfort/swfort.h new file mode 100644 index 000000000..d0cefb098 --- /dev/null +++ b/security/nss/lib/fortcrypt/swfort/swfort.h @@ -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 libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +/* + * Software implementation of FORTEZZA skipjack primatives + */ +#ifndef _SWFORT_H_ +#define _SWFORT_H_ + +#include "seccomon.h" +#include "swfortt.h" +/*#include "genci.h"*/ + + +SEC_BEGIN_PROTOS + +FORTSignedSWFile * +FORT_GetSWFile(SECItem *initBits); + +SECStatus +FORT_CheckInitPhrase(FORTSignedSWFile *sw_init_file, char *initMemPhrase); + +SECStatus +FORT_CheckUserPhrase(FORTSignedSWFile *sw_init_file, char *userMemPhrase); + +void +FORT_DestroySWFile(FORTSWFile *file); + +void +FORT_DestroySignedSWFile(FORTSignedSWFile *swfile); + +SECItem * +FORT_GetDERCert(FORTSignedSWFile *swfile, int index); + +SECItem * +FORT_PutSWFile(FORTSignedSWFile *sw_init_file); + + +SEC_END_PROTOS + +#endif diff --git a/security/nss/lib/fortcrypt/swfort/swforti.h b/security/nss/lib/fortcrypt/swfort/swforti.h new file mode 100644 index 000000000..c2156e2fc --- /dev/null +++ b/security/nss/lib/fortcrypt/swfort/swforti.h @@ -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 libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +/* + * Software implementation of FORTEZZA Skipjack primatives and helper functions. + */ +#ifndef _SWFORTI_H_ +#define _SWFORTI_H_ + +#ifndef RETURN_TYPE +#define RETURN_TYPE int +#endif + +#include "seccomon.h" +#include "swfort.h" +#include "swfortti.h" +#include "maci.h" + + +SEC_BEGIN_PROTOS +/* + * Check to see if the index is ok, and that key is appropriately present or + * absent. + */ +int fort_KeyOK(FORTSWToken *token, int index, PRBool isPresent); + +/* + * clear out a key register + */ +void fort_ClearKey(FORTKeySlot *key); + +/* + * clear out an Ra register + */ +void fort_ClearRaSlot(FORTRaRegisters *ra); + +/* + * provide a helper function to do all the loggin out functions. + * NOTE: Logging in only happens in MACI_CheckPIN + */ +void fort_Logout(FORTSWToken *token); + +/* + * update the new IV value based on the current cipherText (should be the last + * block of the cipher text). + */ +int fort_UpdateIV(unsigned char *cipherText, unsigned int size,unsigned char *IV); + + +/* + * verify that we have a card initialized, and if necessary, logged in. + */ +int fort_CardExists(FORTSWToken *token,PRBool needLogin); + +/* + * walk down the cert slot entries, counting them. + * return that count. + */ +int fort_GetCertCount(FORTSWFile *file); + +/* + * copy an unsigned SECItem to a signed SecItem. (if the high bit is on, + * pad with a leading 0. + */ +SECStatus fort_CopyUnsigned(PRArenaPool *arena, SECItem *to, const SECItem *from); + +/* + * NOTE: these keys do not have the public values, and cannot be used to + * extract the public key from the private key. Since we never do this in + * this code, and this function is private, we're reasonably safe (as long as + * any of your callees do not try to extract the public value as well). + * Also -- the token must be logged in before this function is called. + */ +SECKEYLowPrivateKey * fort_GetPrivKey(FORTSWToken *token,KeyType keyType,fortSlotEntry *certEntry); + +/* + * find a particulare certificate entry from the config + * file. + */ +fortSlotEntry * fort_GetCertEntry(FORTSWFile *file,int index); + +/* + * use the token to termine it's CI_State. + */ +CI_STATE fort_GetState(FORTSWToken *token); + +/* + * find the private ra value for a given public Ra value. + */ +fortRaPrivatePtr fort_LookupPrivR(FORTSWToken *token,CI_RA Ra); + +/* + * go add more noise to the random number generator + */ +void fort_AddNoise(void); + +/* + * Get a random number + */ +int fort_GenerateRandom(unsigned char *buf, int bytes); + + +/* + * We're deep in the bottom of MACI and PKCS #11... We need to + * find our fortezza key file. This function lets us search manual paths to + * find our key file. + */ +char *fort_FindFileInPath(char *path, char *fn); + + +char *fort_LookupFORTEZZAInitFile(void); + + +FORTSkipjackKeyPtr fort_CalculateKMemPhrase(FORTSWFile *file, + fortProtectedPhrase * prot_phrase, char *phrase, FORTSkipjackKeyPtr wrapKey); + + +PRBool fort_CheckMemPhrase(FORTSWFile *file, + fortProtectedPhrase * prot_phrase, char *phrase, FORTSkipjackKeyPtr wrapKey); + + +/* These function actually implements skipjack CBC64 Decrypt */ +int fort_skipjackDecrypt(FORTSkipjackKeyPtr key, unsigned char *iv, + unsigned long size, unsigned char *cipherIn, + unsigned char *plainOut); + +/* These function actually implements skipjack CBC64 Encrypt */ +int fort_skipjackEncrypt(FORTSkipjackKeyPtr key, unsigned char *iv, + unsigned long size, unsigned char *plainIn, + unsigned char *cipherOut); + +/* + * unwrap is used for key generation and mixing + */ +int fort_skipjackUnwrap(FORTSkipjackKeyPtr key,unsigned long len, + unsigned char *cipherIn, unsigned char *plainOut); + +/* + * unwrap is used for key generation and mixing + */ +int +fort_skipjackWrap(FORTSkipjackKeyPtr key,unsigned long len, + unsigned char *plainIn, unsigned char *cipherOut); + +SEC_END_PROTOS + +#endif diff --git a/security/nss/lib/fortcrypt/swfort/swfortt.h b/security/nss/lib/fortcrypt/swfort/swfortt.h new file mode 100644 index 000000000..a5ee7b2b5 --- /dev/null +++ b/security/nss/lib/fortcrypt/swfort/swfortt.h @@ -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 libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. 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 the data structures for Software fortezza are internal only. + * The external API for Software fortezza is MACI (which is only used by + * the PKCS #11 module. + */ + +#ifndef _SWFORTT_H_ +#define _SWFORTT_H_ + +/* structure typedefs */ +typedef struct FORTKeySlotStr FORTKeySlot; +typedef struct FORTRaRegistersStr FORTRaRegisters; +typedef struct FORTSWTokenStr FORTSWToken; + +/* Der parsing typedefs */ +typedef struct fortKeyInformationStr fortKeyInformation; +typedef struct fortProtectedDataStr fortProtectedData; +typedef struct fortSlotEntryStr fortSlotEntry; +typedef struct fortProtectedPhraseStr fortProtectedPhrase; +typedef struct FORTSWFileStr FORTSWFile; +typedef struct FORTSignedSWFileStr FORTSignedSWFile; + + +#endif diff --git a/security/nss/lib/fortcrypt/swfort/swfortti.h b/security/nss/lib/fortcrypt/swfort/swfortti.h new file mode 100644 index 000000000..2e6df4250 --- /dev/null +++ b/security/nss/lib/fortcrypt/swfort/swfortti.h @@ -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 libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. 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 the data structures for Software fortezza are internal only. + * The external API for Software fortezza is MACI (which is only used by + * the PKCS #11 module. + */ + +#ifndef _SWFORTTI_H_ +#define _SWFORTTI_H_ + +#include "maci.h" +#include "seccomon.h" +#include "mcom_db.h" /* really should be included by certt.h */ +#include "certt.h" +#include "keyt.h" +#include "swfortt.h" + +/* the following parameters are tunable. The bigger the key registers are, + * the less likely the PKCS #11 module will thrash. */ +#define KEY_REGISTERS 100 +#define MAX_RA_SLOTS 20 + +/* SKIPJACK algorithm constants */ +#define SKIPJACK_KEY_SIZE 10 +#define SKIPJACK_BLOCK_SIZE 8 +#define SKIPJACK_LEAF_SIZE 16 + +/* private typedefs */ +typedef unsigned char FORTSkipjackKey[SKIPJACK_KEY_SIZE]; +typedef unsigned char *FORTSkipjackKeyPtr; +typedef unsigned char fortRaPrivate[20]; +typedef unsigned char *fortRaPrivatePtr; + +/* save a public/private key pair */ +struct FORTRaRegistersStr { + CI_RA public; + fortRaPrivate private; +}; + +/* FORTEZZA Key Register */ +struct FORTKeySlotStr { + FORTSkipjackKey data; + PRBool present; +}; + +/* structure to hole private key information */ +struct fortKeyInformationStr { + SECItem keyFlags; + SECItem privateKeyWrappedWithKs; + SECItem derPublicKey; + SECItem p; + SECItem g; + SECItem q; +}; + +/* struture to hole Ks wrapped data */ +struct fortProtectedDataStr { + SECItem length; + SECItem dataIV; + SECItem dataEncryptedWithKs; +}; + +/* This structure represents a fortezza personality */ +struct fortSlotEntryStr { + SECItem trusted; + SECItem certificateIndex; + int certIndex; + fortProtectedData certificateLabel; + fortProtectedData certificateData; + fortKeyInformation *exchangeKeyInformation; + fortKeyInformation *signatureKeyInformation; +}; + +/* this structure represents a K value wrapped by a protected pin */ +struct fortProtectedPhraseStr { + SECItem kValueIV; + SECItem wrappedKValue; + SECItem memPhraseIV; + SECItem hashedEncryptedMemPhrase; +}; + + +/* This structure represents all the relevant data stored in a der encoded + * fortezza slot file. */ +struct FORTSWFileStr { + PRArenaPool *arena; + SECItem version; + SECItem derIssuer; + SECItem serialID; + fortProtectedPhrase initMemPhrase; +#define fortezzaPhrase initMemPhrase + fortProtectedPhrase ssoMemPhrase; + fortProtectedPhrase userMemPhrase; + fortProtectedPhrase ssoPinPhrase; + fortProtectedPhrase userPinPhrase; + SECItem wrappedRandomSeed; + fortSlotEntry **slotEntries; +}; + +/* This data structed represents a signed data structure */ +struct FORTSignedSWFileStr { + FORTSWFile file; + CERTSignedData signatureWrap; + FORTSkipjackKeyPtr Kinit; + FORTSkipjackKeyPtr Ks; +}; + + +/* collect all the data that makes up a token */ +struct FORTSWTokenStr { + PRBool login; /* has this token been logged in? */ + int lock; /* the current lock state */ + int certIndex; /* index of the current personality */ + int key; /* currently selected key */ + int nextRa; /* where the next Ra/ra pair will go */ + FORTSWFile *config_file; /* parsed Fortezza Config file */ + unsigned char IV[SKIPJACK_BLOCK_SIZE]; + FORTKeySlot keyReg[KEY_REGISTERS]; /* sw fortezza key slots */ + FORTRaRegisters RaValues[MAX_RA_SLOTS]; /* Ra/ra values */ +}; + +#endif diff --git a/security/nss/lib/fortcrypt/swfort/swfparse.c b/security/nss/lib/fortcrypt/swfort/swfparse.c new file mode 100644 index 000000000..e7ad6ffb6 --- /dev/null +++ b/security/nss/lib/fortcrypt/swfort/swfparse.c @@ -0,0 +1,538 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +/* + * The following program decodes the FORTEZZA Init File, and stores the result + * into the fortezza directory. + */ +#include "secasn1.h" +#include "swforti.h" +#include "blapi.h" +#include "secoid.h" +#include "secitem.h" +#include "secder.h" + + +/* + * templates for parsing the FORTEZZA Init File. These were taken from DER + * definitions on SWF Initialization File Format Version 1.0 pp1-3. + */ + +/* Key info structure... There are up to two of these per slot entry */ +static const SEC_ASN1Template fortKeyInfoTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(fortKeyInformation) }, + { SEC_ASN1_INTEGER, + offsetof(fortKeyInformation,keyFlags) }, + { SEC_ASN1_OCTET_STRING, + offsetof(fortKeyInformation,privateKeyWrappedWithKs) }, + { SEC_ASN1_ANY , + offsetof(fortKeyInformation, derPublicKey) }, + { SEC_ASN1_OCTET_STRING, offsetof(fortKeyInformation,p) }, + { SEC_ASN1_OCTET_STRING, offsetof(fortKeyInformation,g) }, + { SEC_ASN1_OCTET_STRING, offsetof(fortKeyInformation,q) }, + { 0 } +}; + +/* This is data that has been wrapped by Ks */ +static const SEC_ASN1Template fortProtDataTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(fortProtectedData) }, + { SEC_ASN1_INTEGER, + offsetof(fortProtectedData,length) }, + { SEC_ASN1_OCTET_STRING, + offsetof(fortProtectedData,dataIV) }, + { SEC_ASN1_OCTET_STRING, + offsetof(fortProtectedData,dataEncryptedWithKs) }, + { 0 } +}; + +/* DER to describe each Certificate Slot ... there are an arbitrary number */ +static const SEC_ASN1Template fortSlotEntryTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(fortSlotEntry) }, + { SEC_ASN1_BOOLEAN, + offsetof(fortSlotEntry,trusted) }, + { SEC_ASN1_INTEGER, + offsetof(fortSlotEntry,certificateIndex) }, + { SEC_ASN1_INLINE, + offsetof(fortSlotEntry,certificateLabel), fortProtDataTemplate }, + { SEC_ASN1_INLINE, + offsetof(fortSlotEntry,certificateData), fortProtDataTemplate }, + { SEC_ASN1_POINTER | SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | + SEC_ASN1_CONSTRUCTED | 0, + offsetof(fortSlotEntry, exchangeKeyInformation), + fortKeyInfoTemplate }, + { SEC_ASN1_POINTER | SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | + SEC_ASN1_CONSTRUCTED | 1, + offsetof(fortSlotEntry, signatureKeyInformation), + fortKeyInfoTemplate }, + { 0 } +}; + +/* This data is used to check MemPhrases, and to generate Ks + * each file has two mem phrases, one for SSO, one for User */ +static const SEC_ASN1Template fortProtectedMemPhrase[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(fortProtectedPhrase) }, + { SEC_ASN1_OCTET_STRING, + offsetof(fortProtectedPhrase,kValueIV) }, + { SEC_ASN1_OCTET_STRING, + offsetof(fortProtectedPhrase,wrappedKValue) }, + { SEC_ASN1_OCTET_STRING, + offsetof(fortProtectedPhrase,memPhraseIV) }, + { SEC_ASN1_OCTET_STRING, + offsetof(fortProtectedPhrase,hashedEncryptedMemPhrase) }, + { 0 } +}; + +/* This data is used to check the Mem Init Phrases, and to generate Kinit + * each file has one mem init phrase, which is used only in transport of + * this file */ +static const SEC_ASN1Template fortMemInitPhrase[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(fortProtectedPhrase) }, + { SEC_ASN1_OCTET_STRING, + offsetof(fortProtectedPhrase,wrappedKValue) }, + { SEC_ASN1_OCTET_STRING, + offsetof(fortProtectedPhrase,memPhraseIV) }, + { SEC_ASN1_OCTET_STRING, + offsetof(fortProtectedPhrase,hashedEncryptedMemPhrase) }, + { 0 } +}; + +static const SEC_ASN1Template fortSlotEntriesTemplate[] = { + { SEC_ASN1_SEQUENCE_OF, 0, fortSlotEntryTemplate } +}; + +/* This is the complete file with all it's data, but has not been signed + * yet. */ +static const SEC_ASN1Template fortSwFortezzaInitFileToSign[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(FORTSWFile) }, + { SEC_ASN1_INTEGER, + offsetof(FORTSWFile,version) }, + { SEC_ASN1_ANY, + offsetof(FORTSWFile,derIssuer) }, + { SEC_ASN1_OCTET_STRING, + offsetof(FORTSWFile,serialID) }, + { SEC_ASN1_INLINE, + offsetof(FORTSWFile,initMemPhrase), fortMemInitPhrase }, + { SEC_ASN1_INLINE, + offsetof(FORTSWFile,ssoMemPhrase), fortProtectedMemPhrase }, + { SEC_ASN1_INLINE, + offsetof(FORTSWFile,userMemPhrase), fortProtectedMemPhrase }, + { SEC_ASN1_INLINE, + offsetof(FORTSWFile,ssoPinPhrase), fortProtectedMemPhrase }, + { SEC_ASN1_INLINE, + offsetof(FORTSWFile,userPinPhrase), fortProtectedMemPhrase }, + { SEC_ASN1_OCTET_STRING, + offsetof(FORTSWFile,wrappedRandomSeed) }, + { SEC_ASN1_SEQUENCE_OF, offsetof(FORTSWFile,slotEntries), + fortSlotEntryTemplate }, + /* optional extentions to ignore here... */ + { 0 } +}; + +/* The complete, signed init file */ +static const SEC_ASN1Template fortSwFortezzaInitFile[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(FORTSignedSWFile) }, + { SEC_ASN1_SAVE, + offsetof(FORTSignedSWFile,signatureWrap.data) }, + { SEC_ASN1_INLINE, + offsetof(FORTSignedSWFile,file), + fortSwFortezzaInitFileToSign }, + { SEC_ASN1_INLINE, + offsetof(FORTSignedSWFile,signatureWrap.signatureAlgorithm), + SECOID_AlgorithmIDTemplate }, + { SEC_ASN1_BIT_STRING, + offsetof(FORTSignedSWFile,signatureWrap.signature) }, + { 0 } +}; + +FORTSkipjackKeyPtr +fort_CalculateKMemPhrase(FORTSWFile *file, + fortProtectedPhrase * prot_phrase, char *phrase, FORTSkipjackKeyPtr wrapKey) +{ + unsigned char *data = NULL; + unsigned char hashout[SHA1_LENGTH]; + int data_len = prot_phrase->wrappedKValue.len; + int ret; + unsigned int len; + unsigned int version; + unsigned char enc_version[2]; + FORTSkipjackKeyPtr Kout = NULL; + FORTSkipjackKey Kfek; + SHA1Context *sha; + + data = (unsigned char *) PORT_ZAlloc(data_len); + if (data == NULL) goto fail; + + PORT_Memcpy(data,prot_phrase->wrappedKValue.data,data_len); + + /* if it's a real protected mem phrase, it's been wrapped by kinit, which + * was passed to us. */ + if (wrapKey) { + fort_skipjackDecrypt(wrapKey, + &prot_phrase->kValueIV.data[SKIPJACK_LEAF_SIZE],data_len, + data,data); + data_len = sizeof(CI_KEY); + } + + /* now calculate the PBE key for fortezza */ + sha = SHA1_NewContext(); + if (sha == NULL) goto fail; + SHA1_Begin(sha); + version = DER_GetUInteger(&file->version); + enc_version[0] = (version >> 8) & 0xff; + enc_version[1] = version & 0xff; + SHA1_Update(sha,enc_version,sizeof(enc_version)); + SHA1_Update(sha,file->derIssuer.data, file->derIssuer.len); + SHA1_Update(sha,file->serialID.data, file->serialID.len); + SHA1_Update(sha,(unsigned char *)phrase,strlen(phrase)); + SHA1_End(sha,hashout,&len,SHA1_LENGTH); + SHA1_DestroyContext(sha, PR_TRUE); + PORT_Memcpy(Kfek,hashout,sizeof(FORTSkipjackKey)); + + /* now use that key to unwrap */ + Kout = (FORTSkipjackKeyPtr) PORT_Alloc(sizeof(FORTSkipjackKey)); + ret = fort_skipjackUnwrap(Kfek,data_len,data,Kout); + if (ret != CI_OK) { + PORT_Free(Kout); + Kout = NULL; + } + +fail: + PORT_Memset(&Kfek, 0, sizeof(FORTSkipjackKey)); + if (data) PORT_ZFree(data,data_len); + return Kout; +} + + +PRBool +fort_CheckMemPhrase(FORTSWFile *file, + fortProtectedPhrase * prot_phrase, char *phrase, FORTSkipjackKeyPtr wrapKey) +{ + unsigned char *data = NULL; + unsigned char hashout[SHA1_LENGTH]; + int data_len = prot_phrase->hashedEncryptedMemPhrase.len; + unsigned int len; + SHA1Context *sha; + PRBool pinOK = PR_FALSE; + unsigned char cw[4]; + int i; + + + /* first, decrypt the hashed/Encrypted Memphrase */ + data = (unsigned char *) PORT_ZAlloc(data_len); + if (data == NULL) goto failed; + + PORT_Memcpy(data,prot_phrase->hashedEncryptedMemPhrase.data,data_len); + fort_skipjackDecrypt(wrapKey, + &prot_phrase->memPhraseIV.data[SKIPJACK_LEAF_SIZE],data_len, + data,data); + + /* now build the hash for comparisons */ + sha = SHA1_NewContext(); + if (sha == NULL) goto failed; + SHA1_Begin(sha); + SHA1_Update(sha,(unsigned char *)phrase,strlen(phrase)); + SHA1_End(sha,hashout,&len,SHA1_LENGTH); + SHA1_DestroyContext(sha, PR_TRUE); + + /* hashes don't match... must not be the right pass mem */ + if (PORT_Memcmp(data,hashout,len) != 0) goto failed; + + /* now calcuate the checkword and compare it */ + cw[0] = cw[1] = cw[2] = cw[3] = 0; + for (i=0; i <5 ; i++) { + cw[0] = cw[0] ^ hashout[i*4]; + cw[1] = cw[1] ^ hashout[i*4+1]; + cw[2] = cw[2] ^ hashout[i*4+2]; + cw[3] = cw[3] ^ hashout[i*4+3]; + } + + /* checkword doesn't match, must not be the right pass mem */ + if (PORT_Memcmp(data+len,cw,4) != 0) goto failed; + + /* pased all our test, its OK */ + pinOK = PR_TRUE; + +failed: + PORT_Free(data); + + return pinOK; +} + +/* + * walk through the list of memphrases. This function allows us to use a + * for loop to walk down them. + */ +fortProtectedPhrase * +fort_getNextPhrase( FORTSWFile *file, fortProtectedPhrase *last) +{ + if (last == &file->userMemPhrase) { + return &file->userPinPhrase; + } + /* we can add more test here if we want to support SSO mode someday. */ + + return NULL; +} + +/* + * decode the DER file data into our nice data structures, including turning + * cert indexes into integers. + */ +FORTSignedSWFile * +FORT_GetSWFile(SECItem *initBits) +{ + FORTSignedSWFile *sw_init_file; + PRArenaPool *arena = NULL; + SECStatus rv; + int i, count; + + /* get the local arena... be sure to free this at the end */ + + /* get the local arena... be sure to free this at the end */ + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (arena == NULL) goto fail; + + sw_init_file = (FORTSignedSWFile *) + PORT_ArenaZAlloc(arena,sizeof(FORTSignedSWFile)); + if (sw_init_file == NULL) goto fail; + + /* ANS1 decode the complete init file */ + rv = SEC_ASN1DecodeItem(arena,sw_init_file,fortSwFortezzaInitFile,initBits); + if (rv != SECSuccess) { + goto fail; + } + + /* count the certs */ + count = 0; + while (sw_init_file->file.slotEntries[count]) count++; + + for (i=0; i < count; i++) { + /* update the cert Index Pointers */ + sw_init_file->file.slotEntries[i]->certIndex = + DER_GetInteger(&sw_init_file-> + file.slotEntries[i]->certificateIndex ); + } + + /* now start checking the mem phrases and pins, as well as calculating the + * file's 'K' values. First we start with K(init). */ + sw_init_file->file.arena = arena; + + return sw_init_file; + /* OK now that we've read in the init file, and now have Kinit, Ks, and the + * appropriate Pin Phrase, we need to build our database file. */ + +fail: + if (arena) PORT_FreeArena(arena,PR_TRUE); + return NULL; +} + +/* + * Check the init memphrases and the user mem phrases. Remove all the init + * memphrase wrappings. Save the Kinit and Ks values for use. + */ +SECStatus +FORT_CheckInitPhrase(FORTSignedSWFile *sw_init_file, char *initMemPhrase) +{ + SECStatus rv = SECFailure; + + sw_init_file->Kinit = fort_CalculateKMemPhrase(&sw_init_file->file, + &sw_init_file->file.initMemPhrase, initMemPhrase, NULL); + if (sw_init_file->Kinit == NULL) goto fail; + + /* now check the init Mem phrase */ + if (!fort_CheckMemPhrase(&sw_init_file->file, + &sw_init_file->file.initMemPhrase, + initMemPhrase, sw_init_file->Kinit)) { + goto fail; + } + rv = SECSuccess; + +fail: + return rv; +} + + /* now check user user mem phrase and calculate Ks */ +SECStatus +FORT_CheckUserPhrase(FORTSignedSWFile *sw_init_file, char *userMemPhrase) +{ + SECStatus rv = SECFailure; + char tmp_data[13]; + char *padMemPhrase = NULL; + fortProtectedPhrase *phrase_store; + + if (strlen(userMemPhrase) < 12) { + PORT_Memset(tmp_data, ' ', sizeof(tmp_data)); + PORT_Memcpy(tmp_data,userMemPhrase,strlen(userMemPhrase)); + tmp_data[12] = 0; + padMemPhrase = tmp_data; + } + + for (phrase_store = &sw_init_file->file.userMemPhrase; phrase_store; + phrase_store = fort_getNextPhrase(&sw_init_file->file,phrase_store)) { + sw_init_file->Ks = fort_CalculateKMemPhrase(&sw_init_file->file, + phrase_store, userMemPhrase, sw_init_file->Kinit); + + if ((sw_init_file->Ks == NULL) && (padMemPhrase != NULL)) { + sw_init_file->Ks = fort_CalculateKMemPhrase(&sw_init_file->file, + phrase_store, padMemPhrase, sw_init_file->Kinit); + userMemPhrase = padMemPhrase; + } + if (sw_init_file->Ks == NULL) { + continue; + } + + /* now check the User Mem phrase */ + if (fort_CheckMemPhrase(&sw_init_file->file, phrase_store, + userMemPhrase, sw_init_file->Ks)) { + break; + } + PORT_Free(sw_init_file->Ks); + sw_init_file->Ks = NULL; + } + + + if (phrase_store == NULL) goto fail; + + /* strip the Kinit wrapping */ + fort_skipjackDecrypt(sw_init_file->Kinit, + &phrase_store->kValueIV.data[SKIPJACK_LEAF_SIZE], + phrase_store->wrappedKValue.len, phrase_store->wrappedKValue.data, + phrase_store->wrappedKValue.data); + phrase_store->wrappedKValue.len = 12; + + PORT_Memset(phrase_store->kValueIV.data,0,phrase_store->kValueIV.len); + + sw_init_file->file.initMemPhrase = *phrase_store; + sw_init_file->file.ssoMemPhrase = *phrase_store; + sw_init_file->file.ssoPinPhrase = *phrase_store; + sw_init_file->file.userMemPhrase = *phrase_store; + sw_init_file->file.userPinPhrase = *phrase_store; + + + rv = SECSuccess; + +fail: + /* don't keep the pin around */ + PORT_Memset(tmp_data, 0, sizeof(tmp_data)); + return rv; +} + +void +FORT_DestroySWFile(FORTSWFile *file) +{ + PORT_FreeArena(file->arena,PR_FALSE); +} + +void +FORT_DestroySignedSWFile(FORTSignedSWFile *swfile) +{ + FORT_DestroySWFile(&swfile->file); +} + + +SECItem * +FORT_GetDERCert(FORTSignedSWFile *swfile,int index) +{ + SECItem *newItem = NULL; + unsigned char *cert = NULL; + int len,ret; + fortSlotEntry *certEntry = NULL; + + + newItem = PORT_ZNew(SECItem); + if (newItem == NULL) return NULL; + + certEntry = fort_GetCertEntry(&swfile->file,index); + if (certEntry == NULL) { + PORT_Free(newItem); + return NULL; + } + + newItem->len = len = certEntry->certificateData.dataEncryptedWithKs.len; + newItem->data = cert = PORT_ZAlloc(len); + if (cert == NULL) { + PORT_Free(newItem); + return NULL; + } + newItem->len = DER_GetUInteger(&certEntry->certificateData.length); + + + PORT_Memcpy(cert, certEntry->certificateData.dataEncryptedWithKs.data,len); + + /* Ks is always stored in keyReg[0] when we log in */ + ret = fort_skipjackDecrypt(swfile->Ks, + &certEntry->certificateData.dataIV.data[SKIPJACK_LEAF_SIZE], + len,cert,cert); + if (ret != CI_OK) { + SECITEM_FreeItem(newItem,PR_TRUE); + return NULL; + } + return newItem; +} + +/* + * decode the DER file data into our nice data structures, including turning + * cert indexes into integers. + */ +SECItem * +FORT_PutSWFile(FORTSignedSWFile *sw_init_file) +{ + SECItem *outBits, *tmpBits; + PRArenaPool *arena = NULL; + + + /* get the local arena... be sure to free this at the end */ + /* arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); */ + /* if (arena == NULL) goto fail; */ + + /*outBits = (SECItem *) PORT_ArenaZAlloc(arena,sizeof(SECItem)); */ + outBits = PORT_ZNew(SECItem); + if (outBits == NULL) goto fail; + + /* ANS1 encode the complete init file */ + tmpBits = SEC_ASN1EncodeItem(NULL,outBits,sw_init_file,fortSwFortezzaInitFile); + if (tmpBits == NULL) { + goto fail; + } + + return outBits; + +fail: + if (outBits) SECITEM_FreeItem(outBits,PR_TRUE); + return NULL; +} diff --git a/security/nss/lib/fortcrypt/swfort/swfutl.c b/security/nss/lib/fortcrypt/swfort/swfutl.c new file mode 100644 index 000000000..740444c3a --- /dev/null +++ b/security/nss/lib/fortcrypt/swfort/swfutl.c @@ -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 libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. 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 includes utility functions used by cilib. and swfparse.c + */ + +#include "prtypes.h" +#include "prsystem.h" +#include "prio.h" + +#include "swforti.h" +#include "keyt.h" +/* #include "dh.h" */ +#include "maci.h" +#include "secport.h" +#include "secrng.h" + +#ifdef XP_WIN +#include <windows.h> +#include <winsock.h> +#include <direct.h> +#endif + +/* no platform seem to agree on where this function is defined */ +static char *local_index(char *source, char target) { + while ((*source != target) && (*source != 0)) { + *source++; + } + return (*source != 0) ? source : NULL; +} + +/* + * Check to see if the index is ok, and that key is appropriately present or + * absent. + */ +int +fort_KeyOK(FORTSWToken *token, int index, PRBool isPresent) +{ + if (index < 0) return CI_INV_KEY_INDEX; + if (index >= KEY_REGISTERS) return CI_INV_KEY_INDEX; + + return (token->keyReg[index].present == isPresent) ? CI_OK : + (isPresent ? CI_NO_KEY : CI_REG_IN_USE); +} + +/* + * clear out a key register + */ +void +fort_ClearKey(FORTKeySlot *key) +{ + key->present = PR_FALSE; + PORT_Memset(key->data, 0, sizeof (key->data)); + return; +} + +/* + * clear out an Ra register + */ +void +fort_ClearRaSlot(FORTRaRegisters *ra) +{ + PORT_Memset(ra->public, 0, sizeof(ra->public)); + PORT_Memset(ra->private, 0, sizeof(ra->private)); + return; +} + +/* + * provide a helper function to do all the loggin out functions. + * NOTE: Logining in only happens in MACI_CheckPIN + */ +void +fort_Logout(FORTSWToken *token) +{ + int i; + + /* ditch all the stored keys */ + for (i=0; i < KEY_REGISTERS; i++) { + fort_ClearKey(&token->keyReg[i]); + } + for (i=0; i < MAX_RA_SLOTS; i++) { + fort_ClearRaSlot(&token->RaValues[i]); + } + + /* mark as logged out */ + token->login = PR_FALSE; + token->certIndex = 0; + token->key = 0; + return; +} + +/* + * update the new IV value based on the current cipherText (should be the last + * block of the cipher text). + */ +int +fort_UpdateIV(unsigned char *cipherText, unsigned int size,unsigned char *IV) +{ + if (size == 0) return CI_INV_SIZE; + if ((size & (SKIPJACK_BLOCK_SIZE-1)) != 0) return CI_INV_SIZE; + size -= SKIPJACK_BLOCK_SIZE; + PORT_Memcpy(IV,&cipherText[size],SKIPJACK_BLOCK_SIZE); + return CI_OK; +} + + +/* + * verify that we have a card initialized, and if necessary, logged in. + */ +int +fort_CardExists(FORTSWToken *token,PRBool needLogin) +{ + if (token == NULL ) return CI_LIB_NOT_INIT; + if (token->config_file == NULL) return CI_NO_CARD; + if (needLogin && !token->login) return CI_INV_STATE; + return CI_OK; +} + +/* + * walk down the cert slot entries, counting them. + * return that count. + */ +int +fort_GetCertCount(FORTSWFile *file) +{ + int i; + + if (file->slotEntries == NULL) return 0; + + for (i=0; file->slotEntries[i]; i++) + /* no body */ ; + + return i; +} + +/* + * copy an unsigned SECItem to a signed SecItem. (if the high bit is on, + * pad with a leading 0. + */ +SECStatus +fort_CopyUnsigned(PRArenaPool *arena, SECItem *to, const SECItem *from) +{ + int offset = 0; + + if (from->data && from->len) { + if (from->data[0] & 0x80) offset = 1; + if ( arena ) { + to->data = (unsigned char*) PORT_ArenaZAlloc(arena, + from->len+offset); + } else { + to->data = (unsigned char*) PORT_ZAlloc(from->len+offset); + } + + if (!to->data) { + return SECFailure; + } + PORT_Memcpy(to->data+offset, from->data, from->len); + to->len = from->len+offset; + } else { + to->data = 0; + to->len = 0; + } + return SECSuccess; +} + +/* + * NOTE: these keys do not have the public values, and cannot be used to + * extract the public key from the private key. Since we never do this in + * this code, and this function is static, we're reasonably safe (as long as + * any of your callees do not try to extract the public value as well). + * Also -- the token must be logged in before this function is called. + */ +SECKEYLowPrivateKey * +fort_GetPrivKey(FORTSWToken *token,KeyType keyType,fortSlotEntry *certEntry) +{ + SECKEYLowPrivateKey *returnKey = NULL; + SECStatus rv = SECFailure; + PRArenaPool *poolp; + fortKeyInformation *keyInfo; + unsigned char *keyData; + int len, ret; + + + /* select the right keyinfo */ + switch (keyType) { + case dsaKey: + keyInfo = certEntry->signatureKeyInformation; + if (keyInfo == NULL) keyInfo = certEntry->exchangeKeyInformation; + break; + case dhKey: + keyInfo = certEntry->exchangeKeyInformation; + if (keyInfo == NULL) keyInfo = certEntry->signatureKeyInformation; + break; + } + + /* if we don't have any key information, blow out of here */ + if (keyInfo == NULL) return NULL; + + poolp = PORT_NewArena(2048); + if(!poolp) { + return NULL; + } + + returnKey = (SECKEYLowPrivateKey*)PORT_ArenaZAlloc(poolp, sizeof(SECKEYLowPrivateKey)); + if(!returnKey) { + rv = SECFailure; + goto loser; + } + + returnKey->keyType = keyType; + returnKey->arena = poolp; + + /* + * decrypt the private key + */ + len = keyInfo->privateKeyWrappedWithKs.len; + keyData = PORT_ArenaZAlloc(poolp,len); + if (keyData == NULL) { + rv = SECFailure; + goto loser; + } + /* keys must be 160 bits (20 bytes) if that's not the case the Unwrap will + * fail.. */ + ret = fort_skipjackUnwrap(token->keyReg[0].data, len, + keyInfo->privateKeyWrappedWithKs.data, keyData); + if (ret != CI_OK) { + rv = SECFailure; + goto loser; + } + + switch(keyType) { + case dsaKey: + returnKey->u.dsa.privateValue.data = keyData; + returnKey->u.dsa.privateValue.len = 20; + returnKey->u.dsa.params.arena = poolp; + rv = fort_CopyUnsigned(poolp, &(returnKey->u.dsa.params.prime), + &(keyInfo->p)); + if(rv != SECSuccess) break; + rv = fort_CopyUnsigned(poolp, &(returnKey->u.dsa.params.subPrime), + &(keyInfo->q)); + if(rv != SECSuccess) break; + rv = fort_CopyUnsigned(poolp, &(returnKey->u.dsa.params.base), + &(keyInfo->g)); + if(rv != SECSuccess) break; + break; + case dhKey: + returnKey->u.dh.arena = poolp; + returnKey->u.dh.privateValue.data = keyData; + returnKey->u.dh.privateValue.len = 20; + rv = fort_CopyUnsigned(poolp, &(returnKey->u.dh.prime), + &(keyInfo->p)); + if(rv != SECSuccess) break; + rv = fort_CopyUnsigned(poolp, &(returnKey->u.dh.base), + &(keyInfo->g)); + if(rv != SECSuccess) break; + rv = SECSuccess; + break; + default: + rv = SECFailure; + } + +loser: + + if(rv != SECSuccess) { + PORT_FreeArena(poolp, PR_TRUE); + returnKey = NULL; + } + + return returnKey; +} + + + +/* + * find a particulare certificate entry from the config + * file. + */ +fortSlotEntry * +fort_GetCertEntry(FORTSWFile *file,int index) +{ + /* search for the index */ + int i,count= fort_GetCertCount(file); + + /* make sure the given index exists & has key material */ + for (i=0; i < count ;i ++) { + if (file->slotEntries[i]->certIndex == index) { + return file->slotEntries[i]; + } + } + return NULL; +} + +/* + * use the token to determine it's CI_State. + */ +CI_STATE +fort_GetState(FORTSWToken *token) +{ + /* no file? then the token has not been initialized */ + if (!token->config_file) { + return CI_UNINITIALIZED; + } + /* we're initialized, are we logged in (CI_USER_INITIALIZED is not logged + * in) */ + if (!token->login) { + return CI_USER_INITIALIZED; + } + /* We're logged in, do we have a personality set */ + if (token->certIndex) { + return CI_READY; + } + /* We're logged in, with no personality set */ + return CI_STANDBY; +} + +/* + * find the private ra value for a given public Ra value. + */ +fortRaPrivatePtr +fort_LookupPrivR(FORTSWToken *token,CI_RA Ra) +{ + int i; + + /* probably a more efficient way of doing this would be to search first + * several entries before nextRa (or search backwards from next Ra) + */ + for (i=0; i < MAX_RA_SLOTS; i++) { + if (PORT_Memcmp(token->RaValues[i].public,Ra,CI_RA_SIZE) == 0) { + return token->RaValues[i].private; + } + } + return NULL; +} + +/* + * go add more noise to the random number generator + */ +void +fort_AddNoise(void) +{ + unsigned char seed[20]; + + /* note: GetNoise doesn't always get 20 bytes, but adding more + * random data from the stack doesn't subtract entropy from the + * Random number generator, so just send it all. + */ + RNG_GetNoise(seed,sizeof(seed)); + RNG_RandomUpdate(seed,sizeof(seed)); +} + +/* + * Get a random number + */ +int +fort_GenerateRandom(unsigned char *buf, int bytes) +{ + SECStatus rv; + + fort_AddNoise(); + rv = RNG_GenerateGlobalRandomBytes(buf,bytes); + if (rv != SECSuccess) return CI_EXEC_FAIL; + return CI_OK; +} + +/* + * NOTE: that MAC is missing below. + */ +#ifdef XP_UNIX +#define NS_PATH_SEP ':' +#define NS_DIR_SEP '/' +#define NS_DEFAULT_PATH ".:/bin/netscape:/etc/netscape/:/etc" +PRInt32 +local_getFileInfo(const char *fn, PRFileInfo *info) +{ + PRInt32 rv; + struct stat sb; + + rv = stat(fn, &sb); + if (rv < 0) + return -1; + else if (NULL != info) + { + if (S_IFREG & sb.st_mode) + info->type = PR_FILE_FILE; + else if (S_IFDIR & sb.st_mode) + info->type = PR_FILE_DIRECTORY; + else + info->type = PR_FILE_OTHER; + +#if defined(OSF1) + if (0x7fffffffLL < sb.st_size) + { + return -1; + } +#endif /* defined(OSF1) */ + info->size = sb.st_size; + + } + return rv; +} +#endif +#ifdef XP_WIN +#define NS_PATH_SEP ';' +#define NS_DIR_SEP '\\' +#define NS_DEFAULT_PATH ".;c:\\program files\\netscape\\communicator\\program\\pkcs11\\netscape;c:\\netscape\\communicator\\program\\pkcs11\\netscape;c:\\windows\\system" + + +/* + * Since we're a pkcs #11 module, we may get + * loaded into lots of different binaries, each with different or no versions + * of NSPR running... so we copy the one function we need. + */ + +#define _PR_IS_SLASH(ch) ((ch) == '/' || (ch) == '\\') + +/* + * IsRootDirectory -- + * + * Return PR_TRUE if the pathname 'fn' is a valid root directory, + * else return PR_FALSE. The char buffer pointed to by 'fn' must + * be writable. During the execution of this function, the contents + * of the buffer pointed to by 'fn' may be modified, but on return + * the original contents will be restored. 'buflen' is the size of + * the buffer pointed to by 'fn'. + * + * Root directories come in three formats: + * 1. / or \, meaning the root directory of the current drive. + * 2. C:/ or C:\, where C is a drive letter. + * 3. \\<server name>\<share point name>\ or + * \\<server name>\<share point name>, meaning the root directory + * of a UNC (Universal Naming Convention) name. + */ + +static PRBool +IsRootDirectory(char *fn, size_t buflen) +{ + char *p; + PRBool slashAdded = PR_FALSE; + PRBool rv = PR_FALSE; + + if (_PR_IS_SLASH(fn[0]) && fn[1] == '\0') { + return PR_TRUE; + } + + if (isalpha(fn[0]) && fn[1] == ':' && _PR_IS_SLASH(fn[2]) + && fn[3] == '\0') { + rv = GetDriveType(fn) > 1 ? PR_TRUE : PR_FALSE; + return rv; + } + + /* The UNC root directory */ + + if (_PR_IS_SLASH(fn[0]) && _PR_IS_SLASH(fn[1])) { + /* The 'server' part should have at least one character. */ + p = &fn[2]; + if (*p == '\0' || _PR_IS_SLASH(*p)) { + return PR_FALSE; + } + + /* look for the next slash */ + do { + p++; + } while (*p != '\0' && !_PR_IS_SLASH(*p)); + if (*p == '\0') { + return PR_FALSE; + } + + /* The 'share' part should have at least one character. */ + p++; + if (*p == '\0' || _PR_IS_SLASH(*p)) { + return PR_FALSE; + } + + /* look for the final slash */ + do { + p++; + } while (*p != '\0' && !_PR_IS_SLASH(*p)); + if (_PR_IS_SLASH(*p) && p[1] != '\0') { + return PR_FALSE; + } + if (*p == '\0') { + /* + * GetDriveType() doesn't work correctly if the + * path is of the form \\server\share, so we add + * a final slash temporarily. + */ + if ((p + 1) < (fn + buflen)) { + *p++ = '\\'; + *p = '\0'; + slashAdded = PR_TRUE; + } else { + return PR_FALSE; /* name too long */ + } + } + rv = GetDriveType(fn) > 1 ? PR_TRUE : PR_FALSE; + /* restore the 'fn' buffer */ + if (slashAdded) { + *--p = '\0'; + } + } + return rv; +} + +PRInt32 +local_getFileInfo(const char *fn, PRFileInfo *info) +{ + HANDLE hFindFile; + WIN32_FIND_DATA findFileData; + char pathbuf[MAX_PATH + 1]; + + if (NULL == fn || '\0' == *fn) { + return -1; + } + + /* + * FindFirstFile() expands wildcard characters. So + * we make sure the pathname contains no wildcard. + */ + if (NULL != strpbrk(fn, "?*")) { + return -1; + } + + hFindFile = FindFirstFile(fn, &findFileData); + if (INVALID_HANDLE_VALUE == hFindFile) { + DWORD len; + char *filePart; + + /* + * FindFirstFile() does not work correctly on root directories. + * It also doesn't work correctly on a pathname that ends in a + * slash. So we first check to see if the pathname specifies a + * root directory. If not, and if the pathname ends in a slash, + * we remove the final slash and try again. + */ + + /* + * If the pathname does not contain ., \, and /, it cannot be + * a root directory or a pathname that ends in a slash. + */ + if (NULL == strpbrk(fn, ".\\/")) { + return -1; + } + len = GetFullPathName(fn, sizeof(pathbuf), pathbuf, + &filePart); + if (len > sizeof(pathbuf)) { + return -1; + } + if (IsRootDirectory(pathbuf, sizeof(pathbuf))) { + info->type = PR_FILE_DIRECTORY; + info->size = 0; + /* + * These timestamps don't make sense for root directories. + */ + info->modifyTime = 0; + info->creationTime = 0; + return 0; + } + if (!((pathbuf[len - 1] == '/') || (pathbuf[len-1] == '\\'))) { + return -1; + } else { + pathbuf[len - 1] = '\0'; + hFindFile = FindFirstFile(pathbuf, &findFileData); + if (INVALID_HANDLE_VALUE == hFindFile) { + return -1; + } + } + } + + FindClose(hFindFile); + + if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + info->type = PR_FILE_DIRECTORY; + } else { + info->type = PR_FILE_FILE; + } + + info->size = findFileData.nFileSizeLow; + + return 0; +} + +#endif +#ifdef XP_MAC +#error Need to write fort_FindFileInPath for Mac +#define NS_PATH_SEP ',' +#define NS_DIR_SEP ':' +#define NS_DEFAULT_PATH ",System Folder,System Folder:Netscape f:pkcs11:netscape" +#endif + +#define NETSCAPE_INIT_FILE "nsswft.swf" + +/* + * OK, We're deep in the bottom of MACI and PKCS #11... We need to + * find our fortezza key file. We have no clue of where the our binary lives + * or where our key file lives. This function lets us search manual paths + * to find our key file. + */ +char *fort_FindFileInPath(char *path, char *fn) +{ + char *next; + char *holdData; + char *ret = NULL; + int len = 0; + int fn_len = PORT_Strlen(fn)+1; /* include the NULL */ + PRFileInfo info; + char dirSep = NS_DIR_SEP; + + holdData = PORT_Alloc(strlen(path)+1+fn_len); + + while ((next = local_index(path,NS_PATH_SEP)) != NULL) { + len = next - path; + + PORT_Memcpy(holdData,path,len); + if ((len != 0) && (holdData[len-1] != dirSep)) { + PORT_Memcpy(&holdData[len],&dirSep,1); + len++; + } + PORT_Memcpy(&holdData[len],fn,fn_len); + + if ((local_getFileInfo(holdData,&info) == 0) && + (info.type == PR_FILE_FILE) && (info.size != 0)) { + ret = PORT_Strdup(holdData); + PORT_Free(holdData); + return ret; + } + path = next+1; + } + + len = strlen(path); + PORT_Memcpy(holdData,path,len); + if ((len != 0) && (holdData[len-1] != dirSep)) { + PORT_Memcpy(&holdData[len],&dirSep,1); + len++; + } + PORT_Memcpy(&holdData[len],fn,fn_len); + + if ((local_getFileInfo(holdData,&info) == 0) && + (info.type == PR_FILE_FILE) && (info.size != 0)) { + ret = PORT_Strdup(holdData); + } + PORT_Free(holdData); + return ret; +} + +static char *path_table[] = { + "PATH","LD_LIBRARY_PATH","LIBPATH" +}; + +static int path_table_size = sizeof(path_table)/sizeof(path_table[0]); + +char *fort_LookupFORTEZZAInitFile(void) +{ + char *fname = NULL; + char *home = NULL; +#ifdef XP_UNIX + char unix_home[512]; +#endif + int i; + + /* first try to get it from the environment */ + fname = getenv("SW_FORTEZZA_FILE"); + if (fname != NULL) { + return PORT_Strdup(fname); + } + +#ifdef XP_UNIX + home = getenv("HOME"); + if (home) { + strncpy(unix_home,home, sizeof(unix_home)-sizeof("/.netscape")); + strcat(unix_home,"/.netscape"); + fname = fort_FindFileInPath(unix_home,NETSCAPE_INIT_FILE); + if (fname) return fname; + } +#endif +#ifdef XP_WIN + home = getenv("windir"); + if (home) { + fname = fort_FindFileInPath(home,NETSCAPE_INIT_FILE); + if (fname) return fname; + } +#endif + + fname = fort_FindFileInPath(NS_DEFAULT_PATH,NETSCAPE_INIT_FILE); + if (fname) return fname; + + /* now search the system paths */ + for (i=0; i < path_table_size; i++) { + char *path = getenv(path_table[i]); + + if (path != NULL) { + fname = fort_FindFileInPath(path,NETSCAPE_INIT_FILE); + if (fname) return fname; + } + } + + + return NULL; +} |