summaryrefslogtreecommitdiff
path: root/security/nss/lib/fortcrypt/swfort
diff options
context:
space:
mode:
authorrelyea%netscape.com <devnull@localhost>2000-03-31 20:13:40 +0000
committerrelyea%netscape.com <devnull@localhost>2000-03-31 20:13:40 +0000
commit9502869e82d4f3ce26b292263e1c626dca3a34f3 (patch)
tree4d0f8ab157505b57c13a5e2bdf979560ab751527 /security/nss/lib/fortcrypt/swfort
parent222a52dab759085f56dcb6588b69a6a937d82aa2 (diff)
downloadnss-hg-9502869e82d4f3ce26b292263e1c626dca3a34f3.tar.gz
Initial NSS Open Source checkin
Diffstat (limited to 'security/nss/lib/fortcrypt/swfort')
-rw-r--r--security/nss/lib/fortcrypt/swfort/.cvsignore1
-rw-r--r--security/nss/lib/fortcrypt/swfort/Makefile82
-rw-r--r--security/nss/lib/fortcrypt/swfort/config.mk44
-rw-r--r--security/nss/lib/fortcrypt/swfort/manifest.mn56
-rw-r--r--security/nss/lib/fortcrypt/swfort/nsmap.h86
-rw-r--r--security/nss/lib/fortcrypt/swfort/pkcs11/.cvsignore15
-rw-r--r--security/nss/lib/fortcrypt/swfort/pkcs11/Makefile164
-rw-r--r--security/nss/lib/fortcrypt/swfort/pkcs11/config.mk52
-rw-r--r--security/nss/lib/fortcrypt/swfort/pkcs11/inst.js189
-rw-r--r--security/nss/lib/fortcrypt/swfort/pkcs11/manifest.mn73
-rwxr-xr-xsecurity/nss/lib/fortcrypt/swfort/pkcs11/pk11inst49
-rw-r--r--security/nss/lib/fortcrypt/swfort/pkcs11/stub.c344
-rw-r--r--security/nss/lib/fortcrypt/swfort/swfalg.c506
-rw-r--r--security/nss/lib/fortcrypt/swfort/swflib.c1028
-rw-r--r--security/nss/lib/fortcrypt/swfort/swfort.h70
-rw-r--r--security/nss/lib/fortcrypt/swfort/swforti.h176
-rw-r--r--security/nss/lib/fortcrypt/swfort/swfortt.h56
-rw-r--r--security/nss/lib/fortcrypt/swfort/swfortti.h153
-rw-r--r--security/nss/lib/fortcrypt/swfort/swfparse.c538
-rw-r--r--security/nss/lib/fortcrypt/swfort/swfutl.c728
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,&params.prime,&key_info->p);
+ if (rv != SECSuccess) return CI_EXEC_FAIL;
+ rv = SECITEM_CopyItem(NULL,&params.subPrime,&key_info->q);
+ if (rv != SECSuccess) return CI_EXEC_FAIL;
+ rv = SECITEM_CopyItem(NULL,&params.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(&params, &privKey);
+ SECITEM_FreeItem(&params.prime,PR_FALSE);
+ SECITEM_FreeItem(&params.subPrime,PR_FALSE);
+ SECITEM_FreeItem(&params.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;
+}