[Libreoffice-commits] core.git: Branch 'distro/collabora/cp-5.1' - 3 commits - download.lst external/libxslt external/nss

Andras Timar andras.timar at collabora.com
Sun Mar 26 16:38:54 UTC 2017


 download.lst                                                                     |    4 
 external/libxslt/0001-Fix-for-type-confusion-in-preprocessing-attributes.patch.1 |   29 
 external/libxslt/ExternalPackage_xslt.mk                                         |    2 
 external/libxslt/ExternalProject_xslt.mk                                         |    4 
 external/libxslt/UnpackedTarball_xslt.mk                                         |    8 
 external/libxslt/libxslt-android.patch                                           |   15 
 external/libxslt/libxslt-config-guess.patch.0                                    | 1921 ----------
 external/libxslt/libxslt-configure.patch.1                                       |   23 
 external/libxslt/libxslt-freebsd.patch.1                                         |   28 
 external/libxslt/libxslt-msvc.patch.2                                            |   13 
 external/libxslt/libxslt-vc15.patch                                              |   13 
 external/nss/ExternalPackage_nss.mk                                              |    5 
 external/nss/ExternalProject_nss.mk                                              |    1 
 external/nss/Module_nss.mk                                                       |    2 
 external/nss/README                                                              |   64 
 external/nss/UnpackedTarball_nss.mk                                              |    5 
 external/nss/asan.patch.1                                                        |   12 
 external/nss/clang-cl.patch.0                                                    |   74 
 external/nss/nss-winXP-sdk.patch.1                                               |    5 
 external/nss/nss.nowerror.patch                                                  |    8 
 external/nss/nss.patch                                                           |   26 
 external/nss/nss.utf8bom.patch.1                                                 |   30 
 external/nss/nss.windowbuild.patch.0                                             |   55 
 external/nss/nss.windows.patch                                                   |    6 
 external/nss/nss_macosx.patch                                                    |   10 
 external/nss/ubsan-alignment.patch.0                                             |   40 
 external/nss/ubsan.patch.0                                                       |   34 
 27 files changed, 288 insertions(+), 2149 deletions(-)

New commits:
commit d6877736acfbd44417d79e8587739dfc92bf8123
Author: Andras Timar <andras.timar at collabora.com>
Date:   Sun Mar 26 18:31:29 2017 +0200

    Revert "nss: remove nss-pem.patch"
    
    This reverts commit 2a9e6ecc61b232be08d8b1687874289ca0fe8d43.

diff --git a/external/nss/ExternalPackage_nss.mk b/external/nss/ExternalPackage_nss.mk
index 6d568b7edfee..a7c1994e787a 100644
--- a/external/nss/ExternalPackage_nss.mk
+++ b/external/nss/ExternalPackage_nss.mk
@@ -64,4 +64,22 @@ $(eval $(call gb_ExternalPackage_add_files,nss,$(LIBO_LIB_FOLDER),\
 ))
 endif
 
+ifeq ($(SYSTEM_CURL),)
+ifeq ($(OS),IOS)
+# nothing
+else ifeq ($(OS),MACOSX)
+$(eval $(call gb_ExternalPackage_add_files,nss,$(LIBO_LIB_FOLDER),\
+		dist/out/lib/libnsspem.dylib \
+))
+else ifeq ($(OS),WNT)
+$(eval $(call gb_ExternalPackage_add_files,nss,$(LIBO_LIB_FOLDER),\
+		dist/out/lib/nsspem.dll \
+))
+else # OS!=WNT/MACOSX
+$(eval $(call gb_ExternalPackage_add_files,nss,$(LIBO_LIB_FOLDER),\
+		dist/out/lib/libnsspem.so \
+))
+endif
+endif
+
 # vim: set noet sw=4 ts=4:
diff --git a/external/nss/ExternalProject_nss.mk b/external/nss/ExternalProject_nss.mk
index 07cc472b9fb2..03fd1f1ce135 100644
--- a/external/nss/ExternalProject_nss.mk
+++ b/external/nss/ExternalProject_nss.mk
@@ -89,6 +89,7 @@ $(call gb_ExternalProject_get_state_target,nss,build): $(call gb_ExternalProject
 				$(gb_Package_SOURCEDIR_nss)/dist/out/lib/libnss3.dylib \
 				$(gb_Package_SOURCEDIR_nss)/dist/out/lib/libnssckbi.dylib \
 				$(gb_Package_SOURCEDIR_nss)/dist/out/lib/libnssdbm3.dylib \
+				$(gb_Package_SOURCEDIR_nss)/dist/out/lib/libnsspem.dylib \
 				$(gb_Package_SOURCEDIR_nss)/dist/out/lib/libnssutil3.dylib \
 				$(gb_Package_SOURCEDIR_nss)/dist/out/lib/libplc4.dylib \
 				$(gb_Package_SOURCEDIR_nss)/dist/out/lib/libplds4.dylib \
diff --git a/external/nss/UnpackedTarball_nss.mk b/external/nss/UnpackedTarball_nss.mk
index a0ac57173fd1..73a63da68416 100644
--- a/external/nss/UnpackedTarball_nss.mk
+++ b/external/nss/UnpackedTarball_nss.mk
@@ -40,6 +40,13 @@ $(eval $(call gb_UnpackedTarball_add_patches,nss,\
     	external/nss/nss.utf8bom.patch.1) \
 ))
 
+# nss-pem is only needed for internal curl to read the NSS CA database
+ifeq ($(SYSTEM_CURL),)
+$(eval $(call gb_UnpackedTarball_add_patches,nss,\
+	external/nss/nss-pem.patch \
+))
+endif
+
 ifeq ($(COM_IS_CLANG),TRUE)
 ifneq ($(filter -fsanitize=%,$(CC)),)
 $(eval $(call gb_UnpackedTarball_add_patches,nss,\
diff --git a/external/nss/nss-pem.patch b/external/nss/nss-pem.patch
new file mode 100644
index 000000000000..d41809d3ecaf
--- /dev/null
+++ b/external/nss/nss-pem.patch
@@ -0,0 +1,6376 @@
+diff --git a/a/nss/lib/ckfw/manifest.mn b/b/nss/lib/ckfw/manifest.mn
+index 20bebeb..4f10563 100644
+--- a/a/nss/lib/ckfw/manifest.mn
++++ b/b/nss/lib/ckfw/manifest.mn
+@@ -5,7 +5,7 @@
+ 
+ CORE_DEPTH = ../..
+ 
+-DIRS = builtins 
++DIRS = builtins pem
+ 
+ PRIVATE_EXPORTS = \
+ 	ck.h		  \
+diff --git a/a/nss/lib/ckfw/pem/Makefile b/b/nss/lib/ckfw/pem/Makefile
+new file mode 100644
+index 0000000..aec3bbd
+--- /dev/null
++++ b/b/nss/lib/ckfw/pem/Makefile
+@@ -0,0 +1,107 @@
++# 
++# ***** BEGIN LICENSE BLOCK *****
++# Version: MPL 1.1/GPL 2.0/LGPL 2.1
++#
++# The contents of this file are subject to the Mozilla Public License Version
++# 1.1 (the "License"); you may not use this file except in compliance with
++# the License. You may obtain a copy of the License at
++# http://www.mozilla.org/MPL/
++#
++# Software distributed under the License is distributed on an "AS IS" basis,
++# WITHOUT WARRANTY OF ANY KIND, either 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 the Initial Developer are Copyright (C) 1994-2000
++# the Initial Developer. All Rights Reserved.
++#
++# Contributor(s):
++#
++# Alternatively, the contents of this file may be used under the terms of
++# either the GNU General Public License Version 2 or later (the "GPL"), or
++# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
++# in which case the provisions of the GPL or the LGPL are applicable instead
++# of those above. If you wish to allow use of your version of this file only
++# under the terms of either the GPL or the LGPL, and not to allow others to
++# use your version of this file under the terms of the MPL, indicate your
++# decision by deleting the provisions above and replace them with the notice
++# and other provisions required by the GPL or the LGPL. If you do not delete
++# the provisions above, a recipient may use your version of this file under
++# the terms of any one of the MPL, the GPL or the LGPL.
++#
++# ***** END LICENSE BLOCK *****
++MAKEFILE_CVS_ID = "@(#) $RCSfile: Makefile,v $ $Revision: 1.5 $ $Date: 2007/05/09 00:09:37 $"
++
++include manifest.mn
++include $(CORE_DEPTH)/coreconf/config.mk
++include config.mk
++
++EXTRA_LIBS = \
++	$(DIST)/lib/$(LIB_PREFIX)nssckfw.$(LIB_SUFFIX) \
++	$(DIST)/lib/$(LIB_PREFIX)nssb.$(LIB_SUFFIX) \
++	$(DIST)/lib/$(LIB_PREFIX)freebl.$(LIB_SUFFIX) \
++	$(DIST)/lib/$(LIB_PREFIX)nssutil.$(LIB_SUFFIX) \
++	$(NULL)
++
++# can't do this in manifest.mn because OS_TARGET isn't defined there.
++ifeq (,$(filter-out WIN%,$(OS_TARGET)))
++
++ifdef NS_USE_GCC
++EXTRA_LIBS += \
++	-L$(NSPR_LIB_DIR) \
++	-lplc4 \
++	-lplds4 \
++	-lnspr4 \
++	$(NULL)
++else 
++EXTRA_SHARED_LIBS += \
++        $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plc4.lib \
++        $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plds4.lib \
++        $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)nspr4.lib \
++        crypt32.lib \
++	advapi32.lib \
++	rpcrt4.lib \
++        $(NULL)
++endif # NS_USE_GCC
++else
++
++EXTRA_LIBS += \
++	-L$(NSPR_LIB_DIR) \
++	-lplc4 \
++	-lplds4 \
++	-lnspr4 \
++	$(NULL)
++endif
++
++
++include $(CORE_DEPTH)/coreconf/rules.mk
++
++# Generate certdata.c.
++generate:
++	$(PERL) certdata.perl < certdata.txt
++
++# This'll need some help from a build person.
++
++
++ifeq ($(OS_TARGET)$(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_TARGET)$(OS_RELEASE), AIX4.2)
++LD      += -G
++endif 
++
++
+diff --git a/a/nss/lib/ckfw/pem/anchor.c b/b/nss/lib/ckfw/pem/anchor.c
+new file mode 100644
+index 0000000..621f919
+--- /dev/null
++++ b/b/nss/lib/ckfw/pem/anchor.c
+@@ -0,0 +1,50 @@
++/* ***** BEGIN LICENSE BLOCK *****
++ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
++ *
++ * The contents of this file are subject to the Mozilla Public License Version
++ * 1.1 (the "License"); you may not use this file except in compliance with
++ * the License. You may obtain a copy of the License at
++ * http://www.mozilla.org/MPL/
++ *
++ * Software distributed under the License is distributed on an "AS IS" basis,
++ * WITHOUT WARRANTY OF ANY KIND, either 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 the Initial Developer are Copyright (C) 1994-2000
++ * the Initial Developer. All Rights Reserved.
++ *
++ * Contributor(s):
++ *   Rob Crittenden (rcritten at redhat.com)
++ *
++ * Alternatively, the contents of this file may be used under the terms of
++ * either the GNU General Public License Version 2 or later (the "GPL"), or
++ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
++ * in which case the provisions of the GPL or the LGPL are applicable instead
++ * of those above. If you wish to allow use of your version of this file only
++ * under the terms of either the GPL or the LGPL, and not to allow others to
++ * use your version of this file under the terms of the MPL, indicate your
++ * decision by deleting the provisions above and replace them with the notice
++ * and other provisions required by the GPL or the LGPL. If you do not delete
++ * the provisions above, a recipient may use your version of this file under
++ * the terms of any one of the MPL, the GPL or the LGPL.
++ *
++ * ***** END LICENSE BLOCK ***** */
++
++/*
++ * anchor.c
++ *
++ * This file "anchors" the actual cryptoki entry points in this module's
++ * shared library, which is required for dynamic loading.  See the 
++ * comments in nssck.api for more information.
++ */
++
++#include "ckpem.h"
++
++#define MODULE_NAME pem
++#define INSTANCE_NAME (NSSCKMDInstance *)&pem_mdInstance
++#include "nssck.api"
+diff --git a/a/nss/lib/ckfw/pem/ckpem.h b/b/nss/lib/ckfw/pem/ckpem.h
+new file mode 100644
+index 0000000..9712ccd
+--- /dev/null
++++ b/b/nss/lib/ckfw/pem/ckpem.h
+@@ -0,0 +1,263 @@
++#ifndef CKPEM_H
++#define CKPEM_H
++
++#include "nssckmdt.h"
++#include "nssckfw.h"
++#include "ckfwtm.h"
++#include "ckfw.h"
++#include "secder.h"
++#include "secoid.h"
++#include "secasn1.h"
++#include "blapit.h"
++#include "softoken.h"
++
++/*
++ * I'm including this for access to the arena functions.
++ * Looks like we should publish that API.
++ */
++#ifndef BASE_H
++#include "base.h"
++#endif /* BASE_H */
++
++/*
++ * This is where the Netscape extensions live, at least for now.
++ */
++#ifndef CKT_H
++#include "ckt.h"
++#endif /* CKT_H */
++
++#define NUM_SLOTS 8
++
++/*
++ * statically defined raw objects. Allows us to data description objects
++ * to this PKCS #11 module.
++ */
++struct pemRawObjectStr {
++  CK_ULONG n;
++  const CK_ATTRIBUTE_TYPE *types;
++  const NSSItem *items;
++};
++typedef struct pemRawObjectStr pemRawObject;
++
++/*
++ * common values needed for both bare keys and cert referenced keys.
++ */
++struct pemKeyParamsStr {
++  NSSItem         modulus;
++  NSSItem         exponent;
++  NSSItem         privateExponent;
++  NSSItem         prime1;
++  NSSItem         prime2;
++  NSSItem         exponent1;
++  NSSItem         exponent2;
++  NSSItem         coefficient;
++  unsigned char   publicExponentData[sizeof(CK_ULONG)];
++  SECItem         *privateKey;
++  SECItem         *privateKeyOrig; /* deep copy of privateKey until decrypted */
++  void            *pubKey;
++};
++typedef struct pemKeyParamsStr pemKeyParams;
++/*
++ * Key objects. Handles bare keys which do not yet have certs associated
++ * with them. These are usually short lived, but may exist for several days
++ * while the CA is issuing the certificate.
++ */
++struct pemKeyObjectStr {
++  char            *provName;
++  char            *containerName;
++  pemKeyParams    key;
++  char            *ivstring;
++  int             cipher;
++};
++typedef struct pemKeyObjectStr pemKeyObject;
++
++/*
++ * Certificate and certificate referenced keys.
++ */
++struct pemCertObjectStr {
++  const char      *certStore;
++  NSSItem         label;
++  NSSItem         subject;
++  NSSItem         issuer;
++  NSSItem         serial;
++  NSSItem         derCert;
++  unsigned char   sha1_hash[SHA1_LENGTH];
++  unsigned char   md5_hash[MD5_LENGTH];
++  pemKeyParams key;
++  unsigned char   *labelData;
++  /* static data: to do, make this dynamic like labelData */
++  unsigned char   derSerial[128];
++};
++typedef struct pemCertObjectStr pemCertObject;
++
++/*
++ * Trust
++ */
++struct pemTrustObjectStr {
++  char            *nickname;
++};
++typedef struct pemTrustObjectStr pemTrustObject;
++
++typedef enum {
++  pemAll = -1, /* matches all types */
++  pemRaw,
++  pemCert,
++  pemBareKey,
++  pemTrust
++} pemObjectType;
++
++typedef struct pemInternalObjectStr pemInternalObject;
++typedef struct pemObjectListItemStr pemObjectListItem;
++
++/*
++ * singly-linked list of internal objects
++ */
++struct pemObjectListItemStr {
++  pemInternalObject     *io;
++  pemObjectListItem     *next;
++};
++
++/*
++ * all the various types of objects are abstracted away in cobject and
++ * cfind as pemInternalObjects.
++ */
++struct pemInternalObjectStr {
++  pemObjectType type;
++  union {
++    pemRawObject    raw;
++    pemCertObject   cert;
++    pemKeyObject    key;
++    pemTrustObject  trust;
++  } u;
++  CK_OBJECT_CLASS objClass;
++  NSSItem         hashKey;
++  NSSItem         id;
++  unsigned char   hashKeyData[128];
++  SECItem         *derCert;
++  char            *nickname;
++  NSSCKMDObject   mdObject;
++  CK_SLOT_ID      slotID;
++  CK_ULONG        gobjIndex;
++  int             refCount;
++
++  /* used by pem_mdFindObjects_Next */
++  CK_BBOOL        extRef;
++
++  /* If list != NULL, the object contains no useful data except of the list
++   * of slave objects */
++  pemObjectListItem *list;
++};
++
++struct pemTokenStr {
++  PRBool          logged_in;
++};
++typedef struct pemTokenStr pemToken;
++
++/* our raw object data array */
++NSS_EXTERN_DATA pemInternalObject nss_pem_data[];
++NSS_EXTERN_DATA const PRUint32               nss_pem_nObjects;
++
++/* our raw object data array */
++NSS_EXTERN_DATA pemInternalObject nss_pem_data[];
++NSS_EXTERN_DATA const PRUint32               nss_pem_nObjects;
++
++NSS_EXTERN_DATA pemInternalObject pem_data[];
++NSS_EXTERN_DATA const PRUint32               pem_nObjects;
++
++NSS_EXTERN_DATA const CK_VERSION   pem_CryptokiVersion;
++NSS_EXTERN_DATA const NSSUTF8 *    pem_ManufacturerID;
++NSS_EXTERN_DATA const NSSUTF8 *    pem_LibraryDescription;
++NSS_EXTERN_DATA const CK_VERSION   pem_LibraryVersion;
++NSS_EXTERN_DATA const NSSUTF8 *    pem_SlotDescription;
++NSS_EXTERN_DATA const CK_VERSION   pem_HardwareVersion;
++NSS_EXTERN_DATA const CK_VERSION   pem_FirmwareVersion;
++NSS_EXTERN_DATA const NSSUTF8 *    pem_TokenLabel;
++NSS_EXTERN_DATA const NSSUTF8 *    pem_TokenModel;
++NSS_EXTERN_DATA const NSSUTF8 *    pem_TokenSerialNumber;
++
++NSS_EXTERN_DATA const NSSCKMDInstance pem_mdInstance;
++NSS_EXTERN_DATA const NSSCKMDSlot     pem_mdSlot;
++NSS_EXTERN_DATA const NSSCKMDToken    pem_mdToken;
++NSS_EXTERN_DATA const NSSCKMDMechanism pem_mdMechanismRSA;
++
++NSS_EXTERN NSSCKMDSession *
++pem_CreateSession
++(
++  NSSCKFWSession *fwSession,
++  CK_RV *pError
++);
++
++NSS_EXTERN NSSCKMDFindObjects *
++pem_FindObjectsInit
++(
++  NSSCKFWSession *fwSession,
++  CK_ATTRIBUTE_PTR pTemplate,
++  CK_ULONG ulAttributeCount,
++  CK_RV *pError
++);
++
++NSS_EXTERN NSSCKMDObject *
++pem_CreateMDObject
++(
++  NSSArena *arena,
++  pemInternalObject *io,
++  CK_RV *pError
++);
++
++#define NSS_PEM_ARRAY_SIZE(x) ((sizeof (x))/(sizeof ((x)[0])))
++
++typedef enum {
++    pemLOWKEYNullKey = 0,
++    pemLOWKEYRSAKey = 1,
++    pemLOWKEYDSAKey = 2,
++    pemLOWKEYDHKey = 4,
++    pemLOWKEYECKey = 5
++} pemLOWKEYType;
++
++/*
++** Low Level private key object
++** This is only used by the raw Crypto engines (crypto), keydb (keydb),
++** and PKCS #11. Everyone else uses the high level key structure.
++*/
++struct pemLOWKEYPrivateKeyStr {
++    PLArenaPool *arena;
++    pemLOWKEYType keyType;
++    union {
++        RSAPrivateKey rsa;
++        DSAPrivateKey dsa;
++        DHPrivateKey  dh;
++        ECPrivateKey  ec;
++    } u;
++};
++typedef struct pemLOWKEYPrivateKeyStr pemLOWKEYPrivateKey;
++
++SECStatus ReadDERFromFile(SECItem ***derlist, char *filename, PRBool ascii, int *cipher, char **ivstring, PRBool certsonly);
++const NSSItem * pem_FetchAttribute ( pemInternalObject *io, CK_ATTRIBUTE_TYPE type);
++void pem_PopulateModulusExponent(pemInternalObject *io);
++NSSCKMDObject * pem_CreateObject(NSSCKFWInstance *fwInstance, NSSCKFWSession *fwSession, NSSCKMDToken *mdToken, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, CK_RV *pError);
++NSSCKMDSlot *pem_NewSlot( NSSCKFWInstance *fwInstance, CK_RV *pError);
++
++
++PRBool pem_ParseString(const char* inputstring, const char delimiter,
++                       PRInt32* numStrings, char*** returnedstrings);
++PRBool pem_FreeParsedStrings(PRInt32 numStrings, char** instrings);
++
++pemInternalObject *
++AddObjectIfNeeded(CK_OBJECT_CLASS objClass, pemObjectType type,
++                  SECItem *certDER, SECItem *keyDER, char *filename, int objid,
++                  CK_SLOT_ID slotID, PRBool *pAdded);
++
++void pem_DestroyInternalObject (pemInternalObject *io);
++
++
++/* prsa.c */
++unsigned int pem_PrivateModulusLen(pemLOWKEYPrivateKey *privk);
++
++/* ptoken.c */
++NSSCKMDToken * pem_NewToken(NSSCKFWInstance *fwInstance, CK_RV *pError);
++
++/* util.c */
++void open_log();
++void plog(const char *fmt, ...);
++
++#endif /* CKPEM_H */
+diff --git a/a/nss/lib/ckfw/pem/ckpemver.c b/b/nss/lib/ckfw/pem/ckpemver.c
+new file mode 100644
+index 0000000..76ab5df
+--- /dev/null
++++ b/b/nss/lib/ckfw/pem/ckpemver.c
+@@ -0,0 +1,59 @@
++/* ***** BEGIN LICENSE BLOCK *****
++ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
++ *
++ * The contents of this file are subject to the Mozilla Public License Version
++ * 1.1 (the "License"); you may not use this file except in compliance with
++ * the License. You may obtain a copy of the License at
++ * http://www.mozilla.org/MPL/
++ *
++ * Software distributed under the License is distributed on an "AS IS" basis,
++ * WITHOUT WARRANTY OF ANY KIND, either 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 the Initial Developer are Copyright (C) 1994-2000
++ * the Initial Developer. All Rights Reserved.
++ * Portions created by Red Hat, Inc, are Copyright (C) 2005
++ *
++ * Contributor(s):
++ *   Rob Crittenden (rcritten at redhat.com)
++ *
++ * Alternatively, the contents of this file may be used under the terms of
++ * either the GNU General Public License Version 2 or later (the "GPL"), or
++ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
++ * in which case the provisions of the GPL or the LGPL are applicable instead
++ * of those above. If you wish to allow use of your version of this file only
++ * under the terms of either the GPL or the LGPL, and not to allow others to
++ * use your version of this file under the terms of the MPL, indicate your
++ * decision by deleting the provisions above and replace them with the notice
++ * and other provisions required by the GPL or the LGPL. If you do not delete
++ * the provisions above, a recipient may use your version of this file under
++ * the terms of any one of the MPL, the GPL or the LGPL.
++ *
++ * ***** END LICENSE BLOCK ***** */
++/* Library identity and versioning */
++
++#include "nsspem.h"
++
++#if defined(DEBUG)
++#define _DEBUG_STRING " (debug)"
++#else
++#define _DEBUG_STRING ""
++#endif
++
++/*
++ * Version information for the 'ident' and 'what commands
++ *
++ * NOTE: the first component of the concatenated rcsid string
++ * must not end in a '$' to prevent rcs keyword substitution.
++ */
++const char __nss_ckpem_rcsid[] = "$Header: NSS Access to Flat Files in PEM format"
++        NSS_CKPEM_LIBRARY_VERSION _DEBUG_STRING
++        "  " __DATE__ " " __TIME__ " $";
++const char __nss_ckcapi_sccsid[] = "@(#)NSS Access to Flag Files in PEM format "
++        NSS_CKPEM_LIBRARY_VERSION _DEBUG_STRING
++        "  " __DATE__ " " __TIME__;
+diff --git a/a/nss/lib/ckfw/pem/config.mk b/b/nss/lib/ckfw/pem/config.mk
+new file mode 100644
+index 0000000..ff6cd9a
+--- /dev/null
++++ b/b/nss/lib/ckfw/pem/config.mk
+@@ -0,0 +1,71 @@
++# 
++# ***** BEGIN LICENSE BLOCK *****
++# Version: MPL 1.1/GPL 2.0/LGPL 2.1
++#
++# The contents of this file are subject to the Mozilla Public License Version
++# 1.1 (the "License"); you may not use this file except in compliance with
++# the License. You may obtain a copy of the License at
++# http://www.mozilla.org/MPL/
++#
++# Software distributed under the License is distributed on an "AS IS" basis,
++# WITHOUT WARRANTY OF ANY KIND, either 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 the Initial Developer are Copyright (C) 1994-2000
++# the Initial Developer. All Rights Reserved.
++#
++# Contributor(s):
++#
++# Alternatively, the contents of this file may be used under the terms of
++# either the GNU General Public License Version 2 or later (the "GPL"), or
++# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
++# in which case the provisions of the GPL or the LGPL are applicable instead
++# of those above. If you wish to allow use of your version of this file only
++# under the terms of either the GPL or the LGPL, and not to allow others to
++# use your version of this file under the terms of the MPL, indicate your
++# decision by deleting the provisions above and replace them with the notice
++# and other provisions required by the GPL or the LGPL. If you do not delete
++# the provisions above, a recipient may use your version of this file under
++# the terms of any one of the MPL, the GPL or the LGPL.
++#
++# ***** END LICENSE BLOCK *****
++CONFIG_CVS_ID = "@(#) $RCSfile: config.mk,v $ $Revision: 1.11 $ $Date: 2005/01/20 02:25:46 $"
++
++#
++#  Override TARGETS variable so that only shared libraries
++#  are specified as dependencies within rules.mk.
++#
++
++TARGETS        = $(SHARED_LIBRARY)
++LIBRARY        =
++IMPORT_LIBRARY =
++PROGRAM        =
++
++ifeq (,$(filter-out WIN%,$(OS_TARGET)))
++    SHARED_LIBRARY = $(OBJDIR)/$(DLL_PREFIX)$(LIBRARY_NAME)$(LIBRARY_VERSION).$(DLL_SUFFIX)
++    RES = $(OBJDIR)/$(LIBRARY_NAME).res
++    RESNAME = $(LIBRARY_NAME).rc
++endif
++
++ifdef BUILD_IDG
++    DEFINES += -DNSSDEBUG
++endif
++
++#
++# To create a loadable module on Darwin, we must use -bundle.
++#
++ifeq ($(OS_TARGET),Darwin)
++DSO_LDOPTS = -bundle
++endif
++
++ifeq ($(OS_TARGET),SunOS)
++# The -R '$ORIGIN' linker option instructs this library to search for its
++# dependencies in the same directory where it resides.
++MKSHLIB += -R '$$ORIGIN'
++endif
++
+diff --git a/a/nss/lib/ckfw/pem/constants.c b/b/nss/lib/ckfw/pem/constants.c
+new file mode 100644
+index 0000000..0ceb443
+--- /dev/null
++++ b/b/nss/lib/ckfw/pem/constants.c
+@@ -0,0 +1,77 @@
++/* ***** BEGIN LICENSE BLOCK *****
++ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
++ *
++ * The contents of this file are subject to the Mozilla Public License Version
++ * 1.1 (the "License"); you may not use this file except in compliance with
++ * the License. You may obtain a copy of the License at
++ * http://www.mozilla.org/MPL/
++ *
++ * Software distributed under the License is distributed on an "AS IS" basis,
++ * WITHOUT WARRANTY OF ANY KIND, either 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 the Initial Developer are Copyright (C) 1994-2000
++ * the Initial Developer. All Rights Reserved.
++ *
++ * Contributor(s):
++ *   Rob Crittenden (rcritten at redhat.com)
++ *
++ * Alternatively, the contents of this file may be used under the terms of
++ * either the GNU General Public License Version 2 or later (the "GPL"), or
++ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
++ * in which case the provisions of the GPL or the LGPL are applicable instead
++ * of those above. If you wish to allow use of your version of this file only
++ * under the terms of either the GPL or the LGPL, and not to allow others to
++ * use your version of this file under the terms of the MPL, indicate your
++ * decision by deleting the provisions above and replace them with the notice
++ * and other provisions required by the GPL or the LGPL. If you do not delete
++ * the provisions above, a recipient may use your version of this file under
++ * the terms of any one of the MPL, the GPL or the LGPL.
++ *
++ * ***** END LICENSE BLOCK ***** */
++/*
++ * constants.c
++ *
++ * Identification and other constants, all collected here in one place.
++ */
++
++#ifndef NSSBASET_H
++#include "nssbaset.h"
++#endif /* NSSBASET_H */
++
++#ifndef NSSCKT_H
++#include "nssckt.h"
++#endif /* NSSCKT_H */
++
++#ifndef NSSCKBI_H
++#include "../builtins/nssckbi.h"
++#endif /* NSSCKBI_H */
++
++NSS_IMPLEMENT_DATA const CK_VERSION
++pem_CryptokiVersion =  { 2, 1 };
++
++NSS_IMPLEMENT_DATA const NSSUTF8 *
++pem_ManufacturerID = (NSSUTF8 *) "Red Hat, Inc.";
++
++NSS_IMPLEMENT_DATA const NSSUTF8 *
++pem_LibraryDescription = (NSSUTF8 *) "PEM Reader Cryptoki Module";
++
++NSS_IMPLEMENT_DATA const CK_VERSION
++pem_LibraryVersion = { 1, 0 };
++
++NSS_IMPLEMENT_DATA const CK_VERSION
++pem_HardwareVersion = { 1, 0 };
++
++NSS_IMPLEMENT_DATA const CK_VERSION
++pem_FirmwareVersion = {  1, 0 };
++
++NSS_IMPLEMENT_DATA const NSSUTF8 *
++pem_TokenModel = (NSSUTF8 *) "1";
++
++NSS_IMPLEMENT_DATA const NSSUTF8 *
++pem_TokenSerialNumber = (NSSUTF8 *) "1";
+diff --git a/a/nss/lib/ckfw/pem/manifest.mn b/b/nss/lib/ckfw/pem/manifest.mn
+new file mode 100644
+index 0000000..8de27d1
+--- /dev/null
++++ b/b/nss/lib/ckfw/pem/manifest.mn
+@@ -0,0 +1,68 @@
++# 
++# ***** BEGIN LICENSE BLOCK *****
++# Version: MPL 1.1/GPL 2.0/LGPL 2.1
++#
++# The contents of this file are subject to the Mozilla Public License Version
++# 1.1 (the "License"); you may not use this file except in compliance with
++# the License. You may obtain a copy of the License at
++# http://www.mozilla.org/MPL/
++#
++# Software distributed under the License is distributed on an "AS IS" basis,
++# WITHOUT WARRANTY OF ANY KIND, either 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 the Initial Developer are Copyright (C) 1994-2000
++# the Initial Developer. All Rights Reserved.
++#
++# Contributor(s):
++#
++# Alternatively, the contents of this file may be used under the terms of
++# either the GNU General Public License Version 2 or later (the "GPL"), or
++# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
++# in which case the provisions of the GPL or the LGPL are applicable instead
++# of those above. If you wish to allow use of your version of this file only
++# under the terms of either the GPL or the LGPL, and not to allow others to
++# use your version of this file under the terms of the MPL, indicate your
++# decision by deleting the provisions above and replace them with the notice
++# and other provisions required by the GPL or the LGPL. If you do not delete
++# the provisions above, a recipient may use your version of this file under
++# the terms of any one of the MPL, the GPL or the LGPL.
++#
++# ***** END LICENSE BLOCK *****
++MANIFEST_CVS_ID = "@(#) $RCSfile: manifest.mn,v $ $Revision: 1.1 $ $Date: 2005/11/04 02:05:04 $"
++
++CORE_DEPTH = ../../..
++
++MODULE = nss
++MAPFILE = $(OBJDIR)/nsspem.def
++
++EXPORTS =		\
++	nsspem.h	\
++	$(NULL)
++
++CSRCS =			\
++	anchor.c	\
++	constants.c	\
++	pargs.c		\
++	pfind.c		\
++	pinst.c 	\
++	pobject.c	\
++	prsa.c		\
++	psession.c	\
++	pslot.c		\
++	ptoken.c	\
++	ckpemver.c	\
++	rsawrapr.c	\
++	util.c		\
++	$(NULL)
++
++REQUIRES = nspr
++
++LIBRARY_NAME = nsspem
++
++#EXTRA_SHARED_LIBS = -L$(DIST)/lib -lnssckfw -lnssb -lplc4 -lplds4
+diff --git a/a/nss/lib/ckfw/pem/nsspem.def b/b/nss/lib/ckfw/pem/nsspem.def
+new file mode 100644
+index 0000000..4978252
+--- /dev/null
++++ b/b/nss/lib/ckfw/pem/nsspem.def
+@@ -0,0 +1,58 @@
++;+#
++;+# ***** BEGIN LICENSE BLOCK *****
++;+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
++;+#
++;+# The contents of this file are subject to the Mozilla Public License Version
++;+# 1.1 (the "License"); you may not use this file except in compliance with
++;+# the License. You may obtain a copy of the License at
++;+# http://www.mozilla.org/MPL/
++;+#
++;+# Software distributed under the License is distributed on an "AS IS" basis,
++;+# WITHOUT WARRANTY OF ANY KIND, either 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 the Initial Developer are Copyright (C) 2003
++;+# the Initial Developer. All Rights Reserved.
++;+#
++;+# Contributor(s):
++;+#
++;+# Alternatively, the contents of this file may be used under the terms of
++;+# either the GNU General Public License Version 2 or later (the "GPL"), or
++;+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
++;+# in which case the provisions of the GPL or the LGPL are applicable instead
++;+# of those above. If you wish to allow use of your version of this file only
++;+# under the terms of either the GPL or the LGPL, and not to allow others to
++;+# use your version of this file under the terms of the MPL, indicate your
++;+# decision by deleting the provisions above and replace them with the notice
++;+# and other provisions required by the GPL or the LGPL. If you do not delete
++;+# the provisions above, a recipient may use your version of this file under
++;+# the terms of any one of the MPL, the GPL or the LGPL.
++;+#
++;+# ***** END LICENSE BLOCK *****
++;+#
++;+# OK, this file is meant to support SUN, LINUX, AIX and WINDOWS
++;+#   1. For all unix platforms, the string ";-"  means "remove this line"
++;+#   2. For all unix platforms, the string " DATA " will be removed from any 
++;+#     line on which it occurs.
++;+#   3. Lines containing ";+" will have ";+" removed on SUN and LINUX.
++;+#      On AIX, lines containing ";+" will be removed.
++;+#   4. For all unix platforms, the string ";;" will thave the ";;" removed.
++;+#   5. For all unix platforms, after the above processing has taken place,
++;+#    all characters after the first ";" on the line will be removed.
++;+#    And for AIX, the first ";" will also be removed.
++;+#  This file is passed directly to windows. Since ';' is a comment, all UNIX
++;+#   directives are hidden behind ";", ";+", and ";-"
++;+
++;+NSS_3.1 {       # NSS 3.1 release
++;+    global:
++LIBRARY nsspem ;-
++EXPORTS ;-
++C_GetFunctionList;
++;+    local:
++;+*;
++;+};
+diff --git a/a/nss/lib/ckfw/pem/nsspem.h b/b/nss/lib/ckfw/pem/nsspem.h
+new file mode 100644
+index 0000000..1547bf4
+--- /dev/null
++++ b/b/nss/lib/ckfw/pem/nsspem.h
+@@ -0,0 +1,75 @@
++/* ***** BEGIN LICENSE BLOCK *****
++ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
++ *
++ * The contents of this file are subject to the Mozilla Public License Version
++ * 1.1 (the "License"); you may not use this file except in compliance with
++ * the License. You may obtain a copy of the License at
++ * http://www.mozilla.org/MPL/
++ *
++ * Software distributed under the License is distributed on an "AS IS" basis,
++ * WITHOUT WARRANTY OF ANY KIND, either 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 the Initial Developer are Copyright (C) 1994-2000
++ * the Initial Developer. All Rights Reserved.
++ * Portions created by Red Hat, Inc, are Copyright (C) 2005
++ *
++ * Contributor(s):
++ *   Rob Crittenden (rcritten at redhat.com)
++ *
++ * Alternatively, the contents of this file may be used under the terms of
++ * either the GNU General Public License Version 2 or later (the "GPL"), or
++ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
++ * in which case the provisions of the GPL or the LGPL are applicable instead
++ * of those above. If you wish to allow use of your version of this file only
++ * under the terms of either the GPL or the LGPL, and not to allow others to
++ * use your version of this file under the terms of the MPL, indicate your
++ * decision by deleting the provisions above and replace them with the notice
++ * and other provisions required by the GPL or the LGPL. If you do not delete
++ * the provisions above, a recipient may use your version of this file under
++ * the terms of any one of the MPL, the GPL or the LGPL.
++ *
++ * ***** END LICENSE BLOCK ***** */
++
++#ifndef NSSPEM_H
++#define NSSPEM_H
++
++/*
++ * NSS CKPEM Version numbers.
++ *
++ * These are the version numbers for the capi module packaged with
++ * this release on NSS. To determine the version numbers of the builtin
++ * module you are using, use the appropriate PKCS #11 calls.
++ *
++ * These version numbers detail changes to the PKCS #11 interface. They map
++ * to the PKCS #11 spec versions.
++ */
++#define NSS_CKPEM_CRYPTOKI_VERSION_MAJOR 2
++#define NSS_CKPEM_CRYPTOKI_VERSION_MINOR 20
++
++/* These version numbers detail the changes 
++ * to the list of trusted certificates.
++ *
++ * NSS_CKPEM_LIBRARY_VERSION_MINOR is a CK_BYTE.  It's not clear
++ * whether we may use its full range (0-255) or only 0-99 because
++ * of the comment in the CK_VERSION type definition.
++ */
++#define NSS_CKPEM_LIBRARY_VERSION_MAJOR 1
++#define NSS_CKPEM_LIBRARY_VERSION_MINOR 1
++#define NSS_CKPEM_LIBRARY_VERSION "1.1"
++
++/* These version numbers detail the semantic changes to the ckfw engine. */
++#define NSS_CKPEM_HARDWARE_VERSION_MAJOR 1
++#define NSS_CKPEM_HARDWARE_VERSION_MINOR 0
++
++/* These version numbers detail the semantic changes to ckbi itself 
++ * (new PKCS #11 objects), etc. */
++#define NSS_CKPEM_FIRMWARE_VERSION_MAJOR 1
++#define NSS_CKPEM_FIRMWARE_VERSION_MINOR 0
++
++#endif /* NSSCKBI_H */
+diff --git a/a/nss/lib/ckfw/pem/nsspem.rc b/b/nss/lib/ckfw/pem/nsspem.rc
+new file mode 100644
+index 0000000..eb208d6
+--- /dev/null
++++ b/b/nss/lib/ckfw/pem/nsspem.rc
+@@ -0,0 +1,64 @@
++/* This Source Code Form is subject to the terms of the Mozilla Public
++ * License, v. 2.0. If a copy of the MPL was not distributed with this
++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
++
++#include "nsspem.h"
++#include <winver.h>
++
++#define MY_LIBNAME "nsspem"
++#define MY_FILEDESCRIPTION "NSS PEM support"
++
++#ifdef _DEBUG
++#define MY_DEBUG_STR " (debug)"
++#define MY_FILEFLAGS_1 VS_FF_DEBUG
++#else
++#define MY_DEBUG_STR ""
++#define MY_FILEFLAGS_1 0x0L
++#endif
++#if NSS_BETA
++#define MY_FILEFLAGS_2 MY_FILEFLAGS_1|VS_FF_PRERELEASE
++#else
++#define MY_FILEFLAGS_2 MY_FILEFLAGS_1
++#endif
++
++#ifdef WINNT
++#define MY_FILEOS VOS_NT_WINDOWS32
++#else
++#define MY_FILEOS VOS__WINDOWS32
++#endif
++
++#define MY_INTERNAL_NAME MY_LIBNAME
++
++/////////////////////////////////////////////////////////////////////////////
++//
++// Version-information resource
++//
++
++VS_VERSION_INFO VERSIONINFO
++ FILEVERSION NSS_CKPEM_LIBRARY_VERSION_MAJOR,NSS_CKPEM_LIBRARY_VERSION_MINOR,0,0
++ PRODUCTVERSION NSS_CKPEM_LIBRARY_VERSION_MAJOR,NSS_CKPEM_LIBRARY_VERSION_MINOR,0,0
++ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
++ FILEFLAGS MY_FILEFLAGS_2
++ FILEOS MY_FILEOS
++ FILETYPE VFT_DLL
++ FILESUBTYPE 0x0L // not used
++
++BEGIN
++    BLOCK "StringFileInfo"
++    BEGIN
++        BLOCK "040904B0" // Lang=US English, CharSet=Unicode
++        BEGIN
++            VALUE "CompanyName", "Mozilla Foundation\0"
++            VALUE "FileDescription", MY_FILEDESCRIPTION MY_DEBUG_STR "\0"
++            VALUE "FileVersion", NSS_CKPEM_LIBRARY_VERSION "\0"
++            VALUE "InternalName", MY_INTERNAL_NAME "\0"
++            VALUE "OriginalFilename", MY_INTERNAL_NAME ".dll\0"
++            VALUE "ProductName", "Network Security Services\0"
++            VALUE "ProductVersion", NSS_CKPEM_LIBRARY_VERSION "\0"
++        END
++    END
++    BLOCK "VarFileInfo"
++    BEGIN
++        VALUE "Translation", 0x409, 1200
++    END
++END
+diff --git a/a/nss/lib/ckfw/pem/pargs.c b/b/nss/lib/ckfw/pem/pargs.c
+new file mode 100644
+index 0000000..21291a8
+--- /dev/null
++++ b/b/nss/lib/ckfw/pem/pargs.c
+@@ -0,0 +1,164 @@
++/* ***** BEGIN LICENSE BLOCK *****
++ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
++ *
++ * The contents of this file are subject to the Mozilla Public License Version
++ * 1.1 (the "License"); you may not use this file except in compliance with
++ * the License. You may obtain a copy of the License at
++ * http://www.mozilla.org/MPL/
++ *
++ * Software distributed under the License is distributed on an "AS IS" basis,
++ * WITHOUT WARRANTY OF ANY KIND, either 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 the Initial Developer are Copyright (C) 1994-2000
++ * the Initial Developer. All Rights Reserved.
++ *
++ * Contributor(s):
++ *   Rob Crittenden (rcritten at redhat.com)
++ *
++ * Alternatively, the contents of this file may be used under the terms of
++ * either the GNU General Public License Version 2 or later (the "GPL"), or
++ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
++ * in which case the provisions of the GPL or the LGPL are applicable instead
++ * of those above. If you wish to allow use of your version of this file only
++ * under the terms of either the GPL or the LGPL, and not to allow others to
++ * use your version of this file under the terms of the MPL, indicate your
++ * decision by deleting the provisions above and replace them with the notice
++ * and other provisions required by the GPL or the LGPL. If you do not delete
++ * the provisions above, a recipient may use your version of this file under
++ * the terms of any one of the MPL, the GPL or the LGPL.
++ *
++ * ***** END LICENSE BLOCK ***** */
++
++#include <string.h>
++#include <nspr.h>
++
++void *pem_Malloc(const PRInt32 sz)
++{
++    return PR_Malloc(sz);
++}
++
++char *pem_StrNdup(const char *instr, PRInt32 inlen)
++{
++    size_t len = inlen;
++    char *buffer;
++    if (!instr) {
++        return NULL;
++    }
++
++    if (!len) {
++        return NULL;
++    }
++    buffer = (char *) pem_Malloc(len + 1);
++    if (!buffer) {
++        return NULL;
++    }
++    memcpy(buffer, instr, len);
++    buffer[len] = 0; /* NULL termination */
++    return buffer;
++}
++
++char *pem_Strdup(const char *instr)
++{
++    size_t len;
++    if (!instr) {
++        return NULL;
++    }
++
++    len = strlen(instr);
++    return pem_StrNdup(instr, len);
++}
++
++void pem_Free(char *instr)
++{
++    if (!instr) {
++        PR_ASSERT(0);
++    }
++    PR_Free(instr);
++}
++
++void
++addString(char ***returnedstrings, char *newstring, PRInt32 stringcount)
++{
++    char **stringarray = NULL;
++    if (!returnedstrings || !newstring) {
++        return;
++    }
++    if (!stringcount) {
++        /* first string to be added, allocate buffer */
++        *returnedstrings =
++            (char **) PR_Malloc(sizeof(char *) * (stringcount + 1));
++        stringarray = *returnedstrings;
++    } else {
++        stringarray = (char **) PR_Realloc(*returnedstrings,
++                                           sizeof(char *) * (stringcount + 1));
++        if (stringarray) {
++            *returnedstrings = stringarray;
++        }
++    }
++    if (stringarray) {
++        stringarray[stringcount] = newstring;
++    }
++}
++
++PRBool
++pem_ParseString(const char *inputstring, const char delimiter,
++                PRInt32 * numStrings, char ***returnedstrings)
++{
++    char nextchar;
++    char *instring = (char *) inputstring;
++    if (!inputstring || !delimiter || !numStrings || !returnedstrings) {
++        /* we need a string and a non-zero delimiter, as well as
++         * a valid place to return the strings and count
++         */
++        return PR_FALSE;
++    }
++    *numStrings = 0;
++    *returnedstrings = NULL;
++
++    while ((nextchar = *instring)) {
++        unsigned long len = 0;
++        char *next = (char *) strchr(instring, delimiter);
++        if (next) {
++            /* current string string */
++            len = next - instring;
++        } else {
++            /* last string length */
++            len = strlen(instring);
++        }
++
++        if (len > 0) {
++            char *newstring = pem_StrNdup(instring, len);
++
++            addString(returnedstrings, newstring, (*numStrings)++);
++
++            instring += len;
++        }
++
++        if (delimiter == *instring) {
++            instring++; /* skip past next delimiter */
++        }
++    }
++    return PR_TRUE;
++}
++
++PRBool pem_FreeParsedStrings(PRInt32 numStrings, char **instrings)
++{
++    PRInt32 counter;
++    if (!numStrings || !instrings) {
++        return PR_FALSE;
++    }
++    for (counter = 0; counter < numStrings; counter++) {
++        char *astring = instrings[counter];
++        if (astring) {
++            pem_Free(astring);
++        }
++    }
++    PR_Free((void *) instrings);
++    return PR_TRUE;
++}
+diff --git a/a/nss/lib/ckfw/pem/pfind.c b/b/nss/lib/ckfw/pem/pfind.c
+new file mode 100644
+index 0000000..30b1174
+--- /dev/null
++++ b/b/nss/lib/ckfw/pem/pfind.c
+@@ -0,0 +1,435 @@
++/* ***** BEGIN LICENSE BLOCK *****
++ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
++ *
++ * The contents of this file are subject to the Mozilla Public License Version
++ * 1.1 (the "License"); you may not use this file except in compliance with
++ * the License. You may obtain a copy of the License at
++ * http://www.mozilla.org/MPL/
++ *
++ * Software distributed under the License is distributed on an "AS IS" basis,
++ * WITHOUT WARRANTY OF ANY KIND, either 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 the Initial Developer are Copyright (C) 1994-2000
++ * the Initial Developer. All Rights Reserved.
++ *
++ * Contributor(s):
++ *   Rob Crittenden (rcritten at redhat.com)
++ *
++ * Alternatively, the contents of this file may be used under the terms of
++ * either the GNU General Public License Version 2 or later (the "GPL"), or
++ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
++ * in which case the provisions of the GPL or the LGPL are applicable instead
++ * of those above. If you wish to allow use of your version of this file only
++ * under the terms of either the GPL or the LGPL, and not to allow others to
++ * use your version of this file under the terms of the MPL, indicate your
++ * decision by deleting the provisions above and replace them with the notice
++ * and other provisions required by the GPL or the LGPL. If you do not delete
++ * the provisions above, a recipient may use your version of this file under
++ * the terms of any one of the MPL, the GPL or the LGPL.
++ *
++ * ***** END LICENSE BLOCK ***** */
++
++#include "ckpem.h"
++
++/*
++ * pfind.c
++ *
++ * This file implements the NSSCKMDFindObjects object for the
++ * "PEM objects" cryptoki module.
++ */
++
++NSS_EXTERN_DATA pemInternalObject **gobj;
++NSS_EXTERN_DATA int pem_nobjs;
++
++struct pemFOStr {
++    NSSArena *arena;
++    CK_ULONG n;
++    CK_ULONG i;
++    pemInternalObject **objs;
++};
++
++#define PEM_ITEM_CHUNK  512
++
++#define PUT_Object(obj,err) \
++  { \
++    if (count >= size) { \
++    *listp = *listp ? \
++                nss_ZREALLOCARRAY(*listp, pemInternalObject *, \
++                               (size+PEM_ITEM_CHUNK) ) : \
++                nss_ZNEWARRAY(NULL, pemInternalObject *, \
++                               (size+PEM_ITEM_CHUNK) ) ; \
++      if ((pemInternalObject **)NULL == *listp) { \
++        err = CKR_HOST_MEMORY; \
++        goto loser; \
++      } \
++      size += PEM_ITEM_CHUNK; \
++    } \
++    (*listp)[ count ] = (obj); \
++    count++; \
++  }
++
++static void
++pem_mdFindObjects_Final
++(
++    NSSCKMDFindObjects * mdFindObjects,
++    NSSCKFWFindObjects * fwFindObjects,
++    NSSCKMDSession * mdSession,
++    NSSCKFWSession * fwSession,
++    NSSCKMDToken * mdToken,
++    NSSCKFWToken * fwToken,
++    NSSCKMDInstance * mdInstance,
++    NSSCKFWInstance * fwInstance
++)
++{
++    struct pemFOStr *fo = (struct pemFOStr *) mdFindObjects->etc;
++    NSSArena *arena = fo->arena;
++
++    nss_ZFreeIf(fo->objs);
++    nss_ZFreeIf(fo);
++    nss_ZFreeIf(mdFindObjects);
++    if ((NSSArena *) NULL != arena) {
++        NSSArena_Destroy(arena);
++    }
++
++    return;
++}
++
++static NSSCKMDObject *
++pem_mdFindObjects_Next
++(
++    NSSCKMDFindObjects * mdFindObjects,
++    NSSCKFWFindObjects * fwFindObjects,
++    NSSCKMDSession * mdSession,
++    NSSCKFWSession * fwSession,
++    NSSCKMDToken * mdToken,
++    NSSCKFWToken * fwToken,
++    NSSCKMDInstance * mdInstance,
++    NSSCKFWInstance * fwInstance,
++    NSSArena * arena,
++    CK_RV * pError
++)
++{
++    struct pemFOStr *fo = (struct pemFOStr *) mdFindObjects->etc;
++    pemInternalObject *io;
++
++    plog("pem_FindObjects_Next: ");
++
++    if (fo->i == fo->n) {
++        plog("Done creating objects\n");
++        *pError = CKR_OK;
++        return (NSSCKMDObject *) NULL;
++    }
++
++    io = fo->objs[fo->i];
++    fo->i++;
++
++    plog("Creating object for type %d\n", io->type);
++
++    if (!io->extRef) {
++        /* increase reference count only once as ckfw will free the found
++         * object only once */
++        io->extRef = CK_TRUE;
++        io->refCount ++;
++    }
++
++    return pem_CreateMDObject(arena, io, pError);
++}
++
++#if 0
++static int
++pem_derUnwrapInt(unsigned char *src, int size, unsigned char **dest)
++{
++    unsigned char *start = src;
++    int len = 0;
++
++    if (*src++ != 2) {
++        return 0;
++    }
++    len = *src++;
++    if (len & 0x80) {
++        int count = len & 0x7f;
++        len = 0;
++
++        if (count + 2 > size) {
++            return 0;
++        }
++        while (count-- > 0) {
++            len = (len << 8) | *src++;
++        }
++    }
++    if (len + (src - start) != size) {
++        return 0;
++    }
++    *dest = src;
++    return len;
++}
++#endif
++
++static char * pem_attr_name(CK_ATTRIBUTE_TYPE type) {
++    switch(type) {
++    case CKA_CLASS:
++        return "CKA_CLASS";
++    case CKA_TOKEN:
++        return "CKA_TOKEN";
++    case CKA_PRIVATE:
++        return "CKA_PRIVATE";
++    case CKA_LABEL:
++        return "CKA_LABEL";
++    case CKA_APPLICATION:
++        return "CKA_APPLICATION";
++    case CKA_VALUE:
++        return "CKA_VALUE";
++    case CKA_OBJECT_ID:
++        return "CKA_OBJECT_ID";
++    case CKA_CERTIFICATE_TYPE:
++        return "CKA_CERTIFICATE_TYPE";
++    case CKA_ISSUER:
++        return "CKA_ISSUER";
++    case CKA_SERIAL_NUMBER:
++        return "CKA_SERIAL_NUMBER";
++    case CKA_ID:
++        return "CKA_ID";
++    default:
++        return "unknown";
++    }
++}
++
++static CK_BBOOL
++pem_attrmatch(CK_ATTRIBUTE_PTR a, pemInternalObject * o) {
++    PRBool prb;
++    const NSSItem *b;
++
++    b = pem_FetchAttribute(o, a->type);
++    if (b == NULL) {
++        plog("pem_attrmatch %s %08x: CK_FALSE attr not found\n", pem_attr_name(a->type), a->type);
++        return CK_FALSE;
++    }
++
++    if (a->ulValueLen != b->size) {
++         plog("pem_attrmatch %s %08x: CK_FALSE size mismatch %d vs %d\n", pem_attr_name(a->type), a->type, a->ulValueLen, b->size);
++        return CK_FALSE;
++    }
++
++    prb = nsslibc_memequal(a->pValue, b->data, b->size, (PRStatus *) NULL);
++
++    if (PR_TRUE == prb) {
++        plog("pem_attrmatch %s %08x: CK_TRUE\n", pem_attr_name(a->type), a->type);
++        return CK_TRUE;
++    } else {
++        plog("pem_attrmatch %s %08x: CK_FALSE\n", pem_attr_name(a->type), a->type);
++        plog("type: %08x, label: %s a->pValue %08x, b->data %08x\n", o->objClass, o->u.cert.label.data, a->pValue, b->data);
++        return CK_FALSE;
++    }
++}
++
++static CK_BBOOL
++pem_match
++(
++    CK_ATTRIBUTE_PTR pTemplate,
++    CK_ULONG ulAttributeCount,
++    pemInternalObject * o
++)
++{
++    CK_ULONG i;
++
++    for (i = 0; i < ulAttributeCount; i++) {
++        if (CK_FALSE == pem_attrmatch(&pTemplate[i], o)) {
++            plog("pem_match: CK_FALSE\n");
++            return CK_FALSE;
++        }
++    }
++
++    /* Every attribute passed */
++    plog("pem_match: CK_TRUE\n");
++    return CK_TRUE;
++}
++
++CK_OBJECT_CLASS
++pem_GetObjectClass(CK_ATTRIBUTE_PTR pTemplate,
++                   CK_ULONG ulAttributeCount)
++{
++    CK_ULONG i;
++
++    for (i = 0; i < ulAttributeCount; i++) {
++        if (pTemplate[i].type == CKA_CLASS) {
++            return *(CK_OBJECT_CLASS *) pTemplate[i].pValue;
++        }
++    }
++    /* need to return a value that says 'fetch them all' */
++    return CK_INVALID_HANDLE;
++}
++
++static PRUint32
++collect_objects(CK_ATTRIBUTE_PTR pTemplate,
++                CK_ULONG ulAttributeCount,
++                pemInternalObject *** listp,
++                CK_RV * pError, CK_SLOT_ID slotID)
++{
++    PRUint32 i;
++    PRUint32 count = 0;
++    PRUint32 size = 0;
++    pemObjectType type = pemRaw;
++    CK_OBJECT_CLASS objClass = pem_GetObjectClass(pTemplate, ulAttributeCount);
++
++    *pError = CKR_OK;
++
++    plog("collect_objects slot #%ld, ", slotID);
++    plog("%d attributes, ", ulAttributeCount);
++    plog("%d objects to look through.\n", pem_nobjs);
++    plog("Looking for: ");
++    /*
++     * now determine type of the object
++     */
++    switch (objClass) {
++    case CKO_CERTIFICATE:
++        plog("CKO_CERTIFICATE\n");
++        type = pemCert;
++        break;
++    case CKO_PUBLIC_KEY:
++        plog("CKO_PUBLIC_KEY\n");
++        type = pemBareKey;
++        break;
++    case CKO_PRIVATE_KEY:
++        type = pemBareKey;
++        plog("CKO_PRIVATE_KEY\n");
++        break;
++    case CKO_NETSCAPE_TRUST:
++        type = pemTrust;
++        plog("CKO_NETSCAPE_TRUST\n");
++        break;
++    case CKO_NETSCAPE_CRL:
++        plog("CKO_NETSCAPE_CRL\n");
++        goto done;
++    case CKO_NETSCAPE_SMIME:
++        plog("CKO_NETSCAPE_SMIME\n");
++        goto done;
++    case CKO_NETSCAPE_BUILTIN_ROOT_LIST:
++        plog("CKO_NETSCAPE_BUILTIN_ROOT_LIST\n");
++        goto done;
++    case CK_INVALID_HANDLE:
++        type = pemAll; /* look through all objectclasses - ignore the type field */
++        plog("CK_INVALID_HANDLE\n");
++        break;
++    default:
++        plog("no other object types %08x\n", objClass);
++        goto done; /* no other object types we understand in this module */
++    }
++
++    /* find objects */
++    for (i = 0; i < pem_nobjs; i++) {
++        int match = 1; /* matches type if type not specified */
++        if (NULL == gobj[i])
++            continue;
++
++        plog("  %d type = %d\n", i, gobj[i]->type);
++        if (type != pemAll) {
++            /* type specified - must match given type */
++            match = (type == gobj[i]->type);
++        }
++        if (match) {
++            match = (slotID == gobj[i]->slotID) &&
++                (CK_TRUE == pem_match(pTemplate, ulAttributeCount, gobj[i]));
++        }
++        if (match) {
++            pemInternalObject *o = gobj[i];
++            PUT_Object(o, *pError);
++        }
++    }
++
++    if (CKR_OK != *pError) {
++        goto loser;
++    }
++
++  done:
++    plog("collect_objects: Found %d\n", count);
++    return count;
++  loser:
++    nss_ZFreeIf(*listp);
++    return 0;
++
++}
++
++NSS_IMPLEMENT NSSCKMDFindObjects *
++pem_FindObjectsInit
++(
++    NSSCKFWSession * fwSession,
++    CK_ATTRIBUTE_PTR pTemplate,
++    CK_ULONG ulAttributeCount,
++    CK_RV * pError
++)
++{
++    NSSArena *arena = NULL;
++    NSSCKMDFindObjects *rv = (NSSCKMDFindObjects *) NULL;
++    struct pemFOStr *fo = (struct pemFOStr *) NULL;
++    pemInternalObject **temp = (pemInternalObject **) NULL;
++    NSSCKFWSlot *fwSlot;
++    CK_SLOT_ID slotID;
++
++    plog("pem_FindObjectsInit\n");
++    fwSlot = nssCKFWSession_GetFWSlot(fwSession);
++    if ((NSSCKFWSlot *) NULL == fwSlot) {
++        goto loser;
++    }
++    slotID = nssCKFWSlot_GetSlotID(fwSlot);
++
++    arena = NSSArena_Create();
++    if ((NSSArena *) NULL == arena) {
++        goto loser;
++    }
++
++    rv = nss_ZNEW(arena, NSSCKMDFindObjects);
++    if ((NSSCKMDFindObjects *) NULL == rv) {
++        *pError = CKR_HOST_MEMORY;
++        goto loser;
++    }
++
++    fo = nss_ZNEW(arena, struct pemFOStr);
++    if ((struct pemFOStr *) NULL == fo) {
++        *pError = CKR_HOST_MEMORY;
++        goto loser;
++    }
++
++    fo->arena = arena;
++    /* fo->n and fo->i are already zero */
++
++    rv->etc = (void *) fo;
++    rv->Final = pem_mdFindObjects_Final;
++    rv->Next = pem_mdFindObjects_Next;
++    rv->null = (void *) NULL;
++
++    fo->n =
++        collect_objects(pTemplate, ulAttributeCount, &temp, pError,
++                        slotID);
++    if (*pError != CKR_OK) {
++        goto loser;
++    }
++
++    fo->objs = nss_ZNEWARRAY(arena, pemInternalObject *, fo->n);
++    if ((pemInternalObject **) NULL == fo->objs) {
++        *pError = CKR_HOST_MEMORY;
++        goto loser;
++    }
++
++    (void) nsslibc_memcpy(fo->objs, temp,
++                          sizeof(pemInternalObject *) * fo->n);
++
++    nss_ZFreeIf(temp);
++    temp = (pemInternalObject **) NULL;
++
++    return rv;
++
++  loser:
++    nss_ZFreeIf(temp);
++    nss_ZFreeIf(fo);
++    nss_ZFreeIf(rv);
++    if ((NSSArena *) NULL != arena) {
++        NSSArena_Destroy(arena);
++    }
++    return (NSSCKMDFindObjects *) NULL;
++}
+diff --git a/a/nss/lib/ckfw/pem/pinst.c b/b/nss/lib/ckfw/pem/pinst.c
+new file mode 100644
+index 0000000..9c98e89
+--- /dev/null
++++ b/b/nss/lib/ckfw/pem/pinst.c
+@@ -0,0 +1,768 @@
++/* ***** BEGIN LICENSE BLOCK *****
++ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
++ *
++ * The contents of this file are subject to the Mozilla Public License Version
++ * 1.1 (the "License"); you may not use this file except in compliance with
++ * the License. You may obtain a copy of the License at
++ * http://www.mozilla.org/MPL/
++ *
++ * Software distributed under the License is distributed on an "AS IS" basis,
++ * WITHOUT WARRANTY OF ANY KIND, either 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 the Initial Developer are Copyright (C) 1994-2000
++ * the Initial Developer. All Rights Reserved.
++ *
++ * Contributor(s):
++ *   Rob Crittenden (rcritten at redhat.com)
++ *
++ * Alternatively, the contents of this file may be used under the terms of
++ * either the GNU General Public License Version 2 or later (the "GPL"), or
++ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
++ * in which case the provisions of the GPL or the LGPL are applicable instead
++ * of those above. If you wish to allow use of your version of this file only
++ * under the terms of either the GPL or the LGPL, and not to allow others to
++ * use your version of this file under the terms of the MPL, indicate your
++ * decision by deleting the provisions above and replace them with the notice
++ * and other provisions required by the GPL or the LGPL. If you do not delete
++ * the provisions above, a recipient may use your version of this file under
++ * the terms of any one of the MPL, the GPL or the LGPL.
++ *
++ * ***** END LICENSE BLOCK ***** */
++#include <stdlib.h>
++#include "ckpem.h"
++#include "blapi.h"
++#include "prprf.h"
++
++/*
++ * pinstance.c
++ *
++ * This file implements the NSSCKMDInstance object for the 
++ * "PEM objects" cryptoki module.
++ */
++
++static PRBool pemInitialized = PR_FALSE;
++
++pemInternalObject **gobj;
++int pem_nobjs = 0;
++int token_needsLogin[NUM_SLOTS];
++
++PRInt32 size = 0;
++PRInt32 count = 0;
++
++#define PEM_ITEM_CHUNK  512
++
++/*
++ * simple cert decoder to avoid the cost of asn1 engine
++ */
++static unsigned char *
++dataStart(unsigned char *buf, unsigned int length,
++          unsigned int *data_length,
++          PRBool includeTag, unsigned char *rettag)
++{
++    unsigned char tag;
++    unsigned int used_length = 0;
++    if (!length)
++        return NULL;
++
++    tag = buf[used_length++];
++
++    if (rettag) {
++        *rettag = tag;
++    }
++
++    /* blow out when we come to the end */
++    if (tag == 0 || length <= used_length) {
++        return NULL;
++    }
++
++    *data_length = buf[used_length++];
++
++    if (*data_length & 0x80) {
++        int len_count = *data_length & 0x7f;
++
++        *data_length = 0;
++
++        while (len_count-- > 0) {
++            if (length <= used_length)
++                return NULL;
++
++            *data_length = (*data_length << 8) | buf[used_length++];
++        }
++    }
++
++    if (*data_length > (length - used_length)) {
++        *data_length = length - used_length;
++        return NULL;
++    }
++    if (includeTag)
++        *data_length += used_length;
++
++    return (buf + (includeTag ? 0 : used_length));
++}
++
++static int
++GetCertFields(unsigned char *cert, int cert_length,
++              SECItem * issuer, SECItem * serial, SECItem * derSN,
++              SECItem * subject, SECItem * valid, SECItem * subjkey)
++{
++    unsigned char *buf;
++    unsigned int buf_length;
++    unsigned char *dummy;
++    unsigned int dummylen;
++
++    /* get past the signature wrap */
++    buf = dataStart(cert, cert_length, &buf_length, PR_FALSE, NULL);
++    if (buf == NULL)
++        return SECFailure;
++    /* get into the raw cert data */
++    buf = dataStart(buf, buf_length, &buf_length, PR_FALSE, NULL);
++    if (buf == NULL)
++        return SECFailure;
++    /* skip past any optional version number */
++    if ((buf[0] & 0xa0) == 0xa0) {
++        dummy = dataStart(buf, buf_length, &dummylen, PR_FALSE, NULL);
++        if (dummy == NULL)
++            return SECFailure;
++        buf_length -= (dummy - buf) + dummylen;
++        buf = dummy + dummylen;
++    }
++    /* serial number */
++    if (derSN) {
++        derSN->data =
++            dataStart(buf, buf_length, &derSN->len, PR_TRUE, NULL);
++    }
++    serial->data =
++        dataStart(buf, buf_length, &serial->len, PR_FALSE, NULL);
++    if (serial->data == NULL)
++        return SECFailure;
++    buf_length -= (serial->data - buf) + serial->len;
++    buf = serial->data + serial->len;
++    /* skip the OID */
++    dummy = dataStart(buf, buf_length, &dummylen, PR_FALSE, NULL);
++    if (dummy == NULL)
++        return SECFailure;
++    buf_length -= (dummy - buf) + dummylen;
++    buf = dummy + dummylen;
++    /* issuer */
++    issuer->data = dataStart(buf, buf_length, &issuer->len, PR_TRUE, NULL);
++    if (issuer->data == NULL)
++        return SECFailure;
++    buf_length -= (issuer->data - buf) + issuer->len;
++    buf = issuer->data + issuer->len;
++
++    /* only wanted issuer/SN */
++    if (subject == NULL || valid == NULL || subjkey == NULL) {
++        return SECSuccess;
++    }
++    /* validity */
++    valid->data = dataStart(buf, buf_length, &valid->len, PR_FALSE, NULL);
++    if (valid->data == NULL)
++        return SECFailure;
++    buf_length -= (valid->data - buf) + valid->len;
++    buf = valid->data + valid->len;
++    /*subject */
++    subject->data =
++        dataStart(buf, buf_length, &subject->len, PR_TRUE, NULL);
++    if (subject->data == NULL)
++        return SECFailure;
++    buf_length -= (subject->data - buf) + subject->len;
++    buf = subject->data + subject->len;
++    /* subject  key info */
++    subjkey->data =
++        dataStart(buf, buf_length, &subjkey->len, PR_TRUE, NULL);
++    if (subjkey->data == NULL)
++        return SECFailure;
++    buf_length -= (subjkey->data - buf) + subjkey->len;
++    buf = subjkey->data + subjkey->len;
++    return SECSuccess;
++}
++
++static CK_RV
++assignObjectID(pemInternalObject *o, int objid)
++{
++    char id[16];
++    int len;
++
++    sprintf(id, "%d", objid);
++    len = strlen(id) + 1;       /* zero terminate */
++    o->id.size = len;
++    o->id.data = nss_ZAlloc(NULL, len);
++    if (o->id.data == NULL)
++        return CKR_HOST_MEMORY;
++
++    nsslibc_memcpy(o->id.data, id, len);
++    return CKR_OK;
++}
++
++static pemInternalObject *
++CreateObject(CK_OBJECT_CLASS objClass,
++             pemObjectType type, SECItem * certDER,
++             SECItem * keyDER, char *filename,
++             int objid, CK_SLOT_ID slotID)
++{
++    pemInternalObject *o;
++    SECItem subject;
++    SECItem issuer;
++    SECItem serial;
++    SECItem derSN;
++    SECItem valid;
++    SECItem subjkey;
++    char *nickname;
++
++    o = nss_ZNEW(NULL, pemInternalObject);
++    if ((pemInternalObject *) NULL == o) {
++        return NULL;
++    }
++
++    nickname = strrchr(filename, '/');
++    if (nickname)
++        nickname++;
++    else
++        nickname = filename;
++
++    switch (objClass) {
++    case CKO_CERTIFICATE:
++        plog("Creating cert nick %s id %d in slot %ld\n", nickname, objid, slotID);
++        memset(&o->u.cert, 0, sizeof(o->u.cert));
++        break;
++    case CKO_PRIVATE_KEY:
++        plog("Creating key id %d in slot %ld\n", objid, slotID);
++        memset(&o->u.key, 0, sizeof(o->u.key));
++        nickname = filename;
++        break;
++    case CKO_NETSCAPE_TRUST:
++        plog("Creating trust nick %s id %d in slot %ld\n", nickname, objid, slotID);
++        memset(&o->u.trust, 0, sizeof(o->u.trust));
++        break;
++    }
++
++    o->nickname = (char *) nss_ZAlloc(NULL, strlen(nickname) + 1);
++    if (o->nickname == NULL)
++        goto fail;
++    strcpy(o->nickname, nickname);
++
++    if (CKR_OK != assignObjectID(o, objid))
++        goto fail;
++
++    o->objClass = objClass;
++    o->type = type;
++    o->slotID = slotID;
++
++    o->derCert = nss_ZNEW(NULL, SECItem);
++    if (o->derCert == NULL)
++        goto fail;
++    o->derCert->data = (void *) nss_ZAlloc(NULL, certDER->len);
++    if (o->derCert->data == NULL)
++        goto fail;
++    o->derCert->len = certDER->len;
++    nsslibc_memcpy(o->derCert->data, certDER->data, certDER->len);
++
++    switch (objClass) {
++    case CKO_CERTIFICATE:
++    case CKO_NETSCAPE_TRUST:
++        if (SECSuccess != GetCertFields(o->derCert->data, o->derCert->len,
++                                        &issuer, &serial, &derSN, &subject,
++                                        &valid, &subjkey))
++            goto fail;
++
++        o->u.cert.subject.data = (void *) nss_ZAlloc(NULL, subject.len);
++        if (o->u.cert.subject.data == NULL)
++            goto fail;
++        o->u.cert.subject.size = subject.len;
++        nsslibc_memcpy(o->u.cert.subject.data, subject.data, subject.len);
++
++        o->u.cert.issuer.data = (void *) nss_ZAlloc(NULL, issuer.len);
++        if (o->u.cert.issuer.data == NULL) {
++            nss_ZFreeIf(o->u.cert.subject.data);
++            goto fail;
++        }
++        o->u.cert.issuer.size = issuer.len;
++        nsslibc_memcpy(o->u.cert.issuer.data, issuer.data, issuer.len);
++
++        o->u.cert.serial.data = (void *) nss_ZAlloc(NULL, serial.len);
++        if (o->u.cert.serial.data == NULL) {
++            nss_ZFreeIf(o->u.cert.issuer.data);
++            nss_ZFreeIf(o->u.cert.subject.data);
++            goto fail;
++        }
++        o->u.cert.serial.size = serial.len;
++        nsslibc_memcpy(o->u.cert.serial.data, serial.data, serial.len);
++        break;
++    case CKO_PRIVATE_KEY:
++        o->u.key.key.privateKey = nss_ZNEW(NULL, SECItem);
++        if (o->u.key.key.privateKey == NULL)
++            goto fail;
++        o->u.key.key.privateKey->data =
++            (void *) nss_ZAlloc(NULL, keyDER->len);
++        if (o->u.key.key.privateKey->data == NULL) {
++            nss_ZFreeIf(o->u.key.key.privateKey);
++            goto fail;
++        }
++
++        /* store deep copy of original key DER so we can compare it later on */
++        o->u.key.key.privateKeyOrig = SECITEM_DupItem(keyDER);
++        if (o->u.key.key.privateKeyOrig == NULL) {
++            nss_ZFreeIf(o->u.key.key.privateKey->data);
++            nss_ZFreeIf(o->u.key.key.privateKey);
++            goto fail;
++        }
++
++        o->u.key.key.privateKey->len = keyDER->len;
++        nsslibc_memcpy(o->u.key.key.privateKey->data, keyDER->data,
++                       keyDER->len);
++    }
++
++
++    return o;
++
++fail:
++    if (o) {
++        if (o->derCert) {
++            nss_ZFreeIf(o->derCert->data);
++            nss_ZFreeIf(o->derCert);
++        }
++        nss_ZFreeIf(o->id.data);
++        nss_ZFreeIf(o->nickname);
++        nss_ZFreeIf(o);
++    }
++    return NULL;
++}
++
++/* Compare the DER encoding of the internal object against those
++ * of the provided certDER or keyDER according to its objClass.
++ */
++static PRBool
++derEncodingsMatch(CK_OBJECT_CLASS objClass, pemInternalObject * obj,
++                  SECItem * certDER, SECItem * keyDER)
++{
++    SECComparison result;
++
++    switch (objClass) {
++    case CKO_CERTIFICATE:
++    case CKO_NETSCAPE_TRUST:
++        result = SECITEM_CompareItem(obj->derCert, certDER);
++        break;
++
++    case CKO_PRIVATE_KEY:
++        result = SECITEM_CompareItem(obj->u.key.key.privateKeyOrig, keyDER);
++        break;
++
++    default:
++        /* unhandled object class */
++        return PR_FALSE;
++    }
++
++    return SECEqual == result;
++}
++
++static CK_RV
++LinkSharedKeyObject(int oldKeyIdx, int newKeyIdx)
++{
++    int i;
++    for (i = 0; i < pem_nobjs; i++) {
++        CK_RV rv;
++        pemInternalObject *obj = gobj[i];
++        if (NULL == obj)
++            continue;
++
++        if (atoi(obj->id.data) != oldKeyIdx)
++            continue;
++
++        nss_ZFreeIf(obj->id.data);
++        rv = assignObjectID(obj, newKeyIdx);
++        if (CKR_OK != rv)
++            return rv;
++    }
++
++    return CKR_OK;
++}
++
++pemInternalObject *
++AddObjectIfNeeded(CK_OBJECT_CLASS objClass,
++                  pemObjectType type, SECItem * certDER,
++                  SECItem * keyDER, char *filename,
++                  int objid, CK_SLOT_ID slotID, PRBool *pAdded)
++{
++    int i;
++    pemInternalObject *io;
++
++    /* FIXME: copy-pasted from CreateObject */
++    const char *nickname = strrchr(filename, '/');
++    if (nickname && CKO_PRIVATE_KEY != objClass)
++        nickname++;
++    else
++        nickname = filename;
++
++    if (pAdded)
++        *pAdded = PR_FALSE;
++
++    /* first look for the object in gobj, it might be already there */
++    for (i = 0; i < pem_nobjs; i++) {
++        if (NULL == gobj[i])
++            continue;
++
++        /* Comparing DER encodings is dependable and frees the PEM module
++         * from having to require clients to provide unique nicknames.
++         */
++        if ((gobj[i]->objClass == objClass)
++                && (gobj[i]->type == type)
++                && (gobj[i]->slotID == slotID)
++                && derEncodingsMatch(objClass, gobj[i], certDER, keyDER)) {
++
++            /* While adding a client certificate we (wrongly?) assumed that the
++             * key object will follow right after the cert object.  However, if
++             * the key object is shared by multiple client certificates, such
++             * an assumption does not hold.  We have to update the references.
++             */
++            LinkSharedKeyObject(pem_nobjs, i);
++
++            plog("AddObjectIfNeeded: re-using internal object #%i\n", i);
++            gobj[i]->refCount ++;
++            return gobj[i];
++        }
++    }
++
++    /* object not found, we need to create it */
++    io = CreateObject(objClass, type, certDER, keyDER,
++                                         filename, objid, slotID);
++    if (io == NULL)
++        return NULL;
++
++    /* initialize pointers to functions */
++    pem_CreateMDObject(NULL, io, NULL);
++
++    io->gobjIndex = count;
++
++    /* add object to global array */
++    if (count >= size) {
++        gobj = gobj ?
++            nss_ZREALLOCARRAY(gobj, pemInternalObject *,
++                    (size+PEM_ITEM_CHUNK) ) :
++            nss_ZNEWARRAY(NULL, pemInternalObject *,
++                    (size+PEM_ITEM_CHUNK) ) ;
++
++        if ((pemInternalObject **)NULL == gobj)
++            return NULL;
++        size += PEM_ITEM_CHUNK;
++    }
++    gobj[count] = io;
++    count++;
++    pem_nobjs++;
++
++    if (pAdded)
++        *pAdded = PR_TRUE;
++
++    io->refCount ++;
++    return io;
++}
++
++CK_RV
++AddCertificate(char *certfile, char *keyfile, PRBool cacert,
++               CK_SLOT_ID slotID)
++{
++    pemInternalObject *o;
++    CK_RV error = 0;
++    int objid, i;
++    int nobjs = 0;
++    SECItem **objs = NULL;
++    char *ivstring = NULL;
++    int cipher;
++
++    nobjs = ReadDERFromFile(&objs, certfile, PR_TRUE, &cipher, &ivstring, PR_TRUE /* certs only */);
++    if (nobjs <= 0) {
++        nss_ZFreeIf(objs);
++        return CKR_GENERAL_ERROR;
++    }
++
++    /* For now load as many certs as are in the file for CAs only */
++    if (cacert) {
++        for (i = 0; i < nobjs; i++) {
++            char nickname[1024];
++            objid = pem_nobjs + 1;
++
++            PR_snprintf(nickname, 1024, "%s - %d", certfile, i);
++
++            o = AddObjectIfNeeded(CKO_CERTIFICATE, pemCert, objs[i], NULL,
++                                   nickname, 0, slotID, NULL);
++            if (o == NULL) {
++                error = CKR_GENERAL_ERROR;
++                goto loser;
++            }
++
++            /* Add the CA trust object */
++            o = AddObjectIfNeeded(CKO_NETSCAPE_TRUST, pemTrust, objs[i], NULL,
++                                   nickname, 0, slotID, NULL);
++            if (o == NULL) {
++                error = CKR_GENERAL_ERROR;
++                goto loser;
++            }
++        }                       /* for */
++    } else {
++        objid = pem_nobjs + 1;
++        o = AddObjectIfNeeded(CKO_CERTIFICATE, pemCert, objs[0], NULL, certfile,
++                              objid, slotID, NULL);
++        if (o == NULL) {
++            error = CKR_GENERAL_ERROR;
++            goto loser;
++        }
++
++        o = NULL;
++
++        if (keyfile) {          /* add the private key */
++            SECItem **keyobjs = NULL;
++            int kobjs = 0;
++            kobjs =
++                ReadDERFromFile(&keyobjs, keyfile, PR_TRUE, &cipher,
++                                &ivstring, PR_FALSE);
++            if (kobjs < 1) {
++                error = CKR_GENERAL_ERROR;
++                goto loser;
++            }
++            o = AddObjectIfNeeded(CKO_PRIVATE_KEY, pemBareKey, objs[0],
++                                  keyobjs[0], certfile, objid, slotID, NULL);
++            if (o == NULL) {
++                error = CKR_GENERAL_ERROR;
++                goto loser;
++            }
++        }
++    }
++
++    nss_ZFreeIf(objs);
++    return CKR_OK;
++
++  loser:
++    nss_ZFreeIf(objs);
++    nss_ZFreeIf(o);
++    return error;
++}
++
++CK_RV
++pem_Initialize
++(
++    NSSCKMDInstance * mdInstance,
++    NSSCKFWInstance * fwInstance,
++    NSSUTF8 * configurationData
++)
++{
++    CK_RV rv;
++    /* parse the initialization string */
++    char **certstrings = NULL;
++    char *modparms = NULL;
++    PRInt32 numcerts = 0;
++    PRBool status, error = PR_FALSE;
++    int i;
++    CK_C_INITIALIZE_ARGS_PTR modArgs = NULL;
++
++    if (!fwInstance) return CKR_ARGUMENTS_BAD;
++
++    modArgs = NSSCKFWInstance_GetInitArgs(fwInstance);
++    if (modArgs &&
++       ((modArgs->flags & CKF_OS_LOCKING_OK) || (modArgs->CreateMutex != 0))) {
++        return CKR_CANT_LOCK;
++    }
++
++    if (pemInitialized) {
++        return CKR_OK;
++    }
++
++    RNG_RNGInit();
++
++    open_log();
++
++    plog("pem_Initialize\n");
++
++    if (!modArgs || !modArgs->LibraryParameters) {
++        goto done;
++    }
++    modparms = (char *) modArgs->LibraryParameters;
++    plog("Initialized with %s\n", modparms);
++
++    /*
++     * The initialization string format is a space-delimited file of
++     * pairs of paths which are delimited by a semi-colon. The first
++     * entry of the pair is the path to the certificate file. The
++     * second is the path to the key file.
++     *
++     * CA certificates do not need the semi-colon.
++     *
++     * Example:
++     *  /etc/certs/server.pem;/etc/certs/server.key /etc/certs/ca.pem
++     *
++     */
++    status =
++        pem_ParseString(modparms, ' ', &numcerts,
++                        &certstrings);
++    if (status == PR_FALSE) {
++        return CKR_ARGUMENTS_BAD;
++    }
++
++    for (i = 0; i < numcerts && error != PR_TRUE; i++) {
++        char *cert = certstrings[i];
++        PRInt32 attrcount = 0;
++        char **certattrs = NULL;
++        status = pem_ParseString(cert, ';', &attrcount, &certattrs);
++        if (status == PR_FALSE) {
++            error = PR_TRUE;
++            break;
++        }
++
++        if (error == PR_FALSE) {
++            if (attrcount == 1) /* CA certificate */
++                rv = AddCertificate(certattrs[0], NULL, PR_TRUE, 0);
++            else
++                rv = AddCertificate(certattrs[0], certattrs[1], PR_FALSE,
++                                    0);
++
++            if (rv != CKR_OK) {
++                error = PR_TRUE;
++                status = PR_FALSE;
++            }
++        }
++        pem_FreeParsedStrings(attrcount, certattrs);
++    }
++    pem_FreeParsedStrings(numcerts, certstrings);
++
++    if (status == PR_FALSE) {
++        return CKR_ARGUMENTS_BAD;
++    }
++
++    for (i = 0; i < NUM_SLOTS; i++)
++        token_needsLogin[i] = PR_FALSE;
++
++  done:
++
++    PR_AtomicSet(&pemInitialized, PR_TRUE);
++
++    return CKR_OK;
++}
++
++void
++pem_Finalize
++(
++    NSSCKMDInstance * mdInstance,
++    NSSCKFWInstance * fwInstance
++)
++{
++    plog("pem_Finalize\n");
++    if (!pemInitialized)
++        return;
++
++    nss_ZFreeIf(gobj);
++    gobj = NULL;
++
++    pem_nobjs = 0;
++    size = 0;
++    count = 0;
++
++    PR_AtomicSet(&pemInitialized, PR_FALSE);
++
++    return;
++}
++
++/*
++ * NSSCKMDInstance methods
++ */
++
++static CK_ULONG
++pem_mdInstance_GetNSlots
++(
++    NSSCKMDInstance * mdInstance,
++    NSSCKFWInstance * fwInstance,
++    CK_RV * pError
++)
++{
++    return (CK_ULONG) NUM_SLOTS;
++}
++
++static CK_VERSION
++pem_mdInstance_GetCryptokiVersion
++(
++    NSSCKMDInstance * mdInstance,
++    NSSCKFWInstance * fwInstance
++)
++{
++    return pem_CryptokiVersion;
++}
++
++static NSSUTF8 *
++pem_mdInstance_GetManufacturerID
++(
++    NSSCKMDInstance * mdInstance,
++    NSSCKFWInstance * fwInstance,
++    CK_RV * pError
++)
++{
++    return (NSSUTF8 *) pem_ManufacturerID;
++}
++
++static NSSUTF8 *
++pem_mdInstance_GetLibraryDescription
++(
++    NSSCKMDInstance * mdInstance,
++    NSSCKFWInstance * fwInstance,
++    CK_RV * pError
++)
++{
++    return (NSSUTF8 *) pem_LibraryDescription;
++}
++
++static CK_VERSION
++pem_mdInstance_GetLibraryVersion
++(
++    NSSCKMDInstance * mdInstance,
++    NSSCKFWInstance * fwInstance
++)
++{
++    return pem_LibraryVersion;
++}
++
++static CK_RV
++pem_mdInstance_GetSlots
++(
++    NSSCKMDInstance * mdInstance,
++    NSSCKFWInstance * fwInstance,
++    NSSCKMDSlot * slots[]
++)
++{
++    int i;
++    CK_RV pError;
++
++    for (i = 0; i < NUM_SLOTS; i++) {
++        slots[i] = (NSSCKMDSlot *) pem_NewSlot(fwInstance, &pError);
++        if (pError != CKR_OK)
++            return pError;
++    }
++    return CKR_OK;
++}
++
++CK_BBOOL
++pem_mdInstance_ModuleHandlesSessionObjects
++(
++    NSSCKMDInstance * mdInstance,
++    NSSCKFWInstance * fwInstance
++)
++{
++    return CK_TRUE;
++}
++
++NSS_IMPLEMENT_DATA const NSSCKMDInstance
++pem_mdInstance = {
++    (void *) NULL, /* etc */
++    pem_Initialize, /* Initialize */
++    pem_Finalize, /* Finalize */
++    pem_mdInstance_GetNSlots,
++    pem_mdInstance_GetCryptokiVersion,
++    pem_mdInstance_GetManufacturerID,
++    pem_mdInstance_GetLibraryDescription,
++    pem_mdInstance_GetLibraryVersion,
++    pem_mdInstance_ModuleHandlesSessionObjects,
++    pem_mdInstance_GetSlots,
++    NULL, /* WaitForSlotEvent */
++    (void *) NULL /* null terminator */
++};
+diff --git a/a/nss/lib/ckfw/pem/pobject.c b/b/nss/lib/ckfw/pem/pobject.c
+new file mode 100644
+index 0000000..a13e531
+--- /dev/null
++++ b/b/nss/lib/ckfw/pem/pobject.c
+@@ -0,0 +1,1240 @@
++/* ***** BEGIN LICENSE BLOCK *****
++ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
++ *
++ * The contents of this file are subject to the Mozilla Public License Version
++ * 1.1 (the "License"); you may not use this file except in compliance with
++ * the License. You may obtain a copy of the License at
++ * http://www.mozilla.org/MPL/
++ *
++ * Software distributed under the License is distributed on an "AS IS" basis,
++ * WITHOUT WARRANTY OF ANY KIND, either 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 the Initial Developer are Copyright (C) 1994-2000
++ * the Initial Developer. All Rights Reserved.
++ *
++ * Contributor(s):
++ *   Rob Crittenden (rcritten at redhat.com)
++ *
++ * Alternatively, the contents of this file may be used under the terms of
++ * either the GNU General Public License Version 2 or later (the "GPL"), or
++ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
++ * in which case the provisions of the GPL or the LGPL are applicable instead
++ * of those above. If you wish to allow use of your version of this file only
++ * under the terms of either the GPL or the LGPL, and not to allow others to
++ * use your version of this file under the terms of the MPL, indicate your
++ * decision by deleting the provisions above and replace them with the notice
++ * and other provisions required by the GPL or the LGPL. If you do not delete
++ * the provisions above, a recipient may use your version of this file under
++ * the terms of any one of the MPL, the GPL or the LGPL.
++ *
++ * ***** END LICENSE BLOCK ***** */
++
++#include "ckpem.h"
++#include "secasn1.h"
++#include "certt.h"
++#include "prprf.h"
++#include "pk11pub.h"
++
++/*
++ * pobject.c
++ *
++ * This file implements the NSSCKMDObject object for the
++ * "PEM objects" cryptoki module.
++ */
++
++NSS_EXTERN_DATA pemInternalObject **gobj;
++NSS_EXTERN_DATA int pem_nobjs;
++NSS_EXTERN_DATA int token_needsLogin[NUM_SLOTS];
++
++#define APPEND_LIST_ITEM(item) do { \
++    item->next = nss_ZNEW(NULL, pemObjectListItem); \
++    if (NULL == item->next) \
++      goto loser; \
++    item = item->next; \
++} while (0)
++
++const CK_ATTRIBUTE_TYPE certAttrs[] = {
++    CKA_CLASS,
++    CKA_TOKEN,
++    CKA_PRIVATE,
++    CKA_MODIFIABLE,
++    CKA_LABEL,
++    CKA_CERTIFICATE_TYPE,
++    CKA_SUBJECT,
++    CKA_ISSUER,
++    CKA_SERIAL_NUMBER,
++    CKA_VALUE
++};
++const PRUint32 certAttrsCount = NSS_PEM_ARRAY_SIZE(certAttrs);
++
++/* private keys, for now only support RSA */
++const CK_ATTRIBUTE_TYPE privKeyAttrs[] = {
++    CKA_CLASS,
++    CKA_TOKEN,
++    CKA_PRIVATE,
++    CKA_MODIFIABLE,
++    CKA_LABEL,
++    CKA_KEY_TYPE,
++    CKA_DERIVE,
++    CKA_LOCAL,
++    CKA_SUBJECT,
++    CKA_SENSITIVE,
++    CKA_DECRYPT,
++    CKA_SIGN,
++    CKA_SIGN_RECOVER,
++    CKA_UNWRAP,
++    CKA_EXTRACTABLE,
++    CKA_ALWAYS_SENSITIVE,
++    CKA_NEVER_EXTRACTABLE,
++    CKA_MODULUS,
++    CKA_PUBLIC_EXPONENT,
++};
++const PRUint32 privKeyAttrsCount = NSS_PEM_ARRAY_SIZE(privKeyAttrs);
++
++/* public keys, for now only support RSA */
++const CK_ATTRIBUTE_TYPE pubKeyAttrs[] = {
++    CKA_CLASS,
++    CKA_TOKEN,
++    CKA_PRIVATE,
++    CKA_MODIFIABLE,
++    CKA_LABEL,
++    CKA_KEY_TYPE,
++    CKA_DERIVE,
++    CKA_LOCAL,
++    CKA_SUBJECT,
++    CKA_ENCRYPT,
++    CKA_VERIFY,
++    CKA_VERIFY_RECOVER,
++    CKA_WRAP,
++    CKA_MODULUS,
++    CKA_PUBLIC_EXPONENT,
++};
++const PRUint32 pubKeyAttrsCount = NSS_PEM_ARRAY_SIZE(pubKeyAttrs);
++
++/* Trust */
++const CK_ATTRIBUTE_TYPE trustAttrs[] = {
++    CKA_CLASS,
++    CKA_TOKEN,
++    CKA_LABEL,
++    CKA_CERT_SHA1_HASH,
++    CKA_CERT_MD5_HASH,
++    CKA_ISSUER,
++    CKA_SUBJECT,
++    CKA_TRUST_SERVER_AUTH,
++    CKA_TRUST_CLIENT_AUTH,
++    CKA_TRUST_EMAIL_PROTECTION,
++    CKA_TRUST_CODE_SIGNING
++};
++const PRUint32 trustAttrsCount = NSS_PEM_ARRAY_SIZE(trustAttrs);
++
++static const CK_BBOOL ck_true = CK_TRUE;
++static const CK_BBOOL ck_false = CK_FALSE;
++static const CK_CERTIFICATE_TYPE ckc_x509 = CKC_X_509;
++static const CK_KEY_TYPE ckk_rsa = CKK_RSA;
++static const CK_OBJECT_CLASS cko_certificate = CKO_CERTIFICATE;
++static const CK_OBJECT_CLASS cko_private_key = CKO_PRIVATE_KEY;
++static const CK_OBJECT_CLASS cko_public_key = CKO_PUBLIC_KEY;
++static const CK_OBJECT_CLASS cko_trust = CKO_NETSCAPE_TRUST;
++static const CK_TRUST ckt_netscape_trusted = CKT_NETSCAPE_TRUSTED_DELEGATOR;
++static const NSSItem pem_trueItem = {
++    (void *) &ck_true, (PRUint32) sizeof(CK_BBOOL)
++};
++static const NSSItem pem_falseItem = {
++    (void *) &ck_false, (PRUint32) sizeof(CK_BBOOL)
++};
++static const NSSItem pem_x509Item = {
++    (void *) &ckc_x509, (PRUint32) sizeof(CK_ULONG)
++};
++static const NSSItem pem_rsaItem = {
++    (void *) &ckk_rsa, (PRUint32) sizeof(CK_KEY_TYPE)
++};
++static const NSSItem pem_certClassItem = {
++    (void *) &cko_certificate, (PRUint32) sizeof(CK_OBJECT_CLASS)
++};
++static const NSSItem pem_privKeyClassItem = {
++    (void *) &cko_private_key, (PRUint32) sizeof(CK_OBJECT_CLASS)
++};
++static const NSSItem pem_pubKeyClassItem = {
++    (void *) &cko_public_key, (PRUint32) sizeof(CK_OBJECT_CLASS)
++};
++static const NSSItem pem_trustClassItem = {
++    (void *) &cko_trust, (PRUint32) sizeof(CK_OBJECT_CLASS)
++};
++static const NSSItem pem_emptyItem = {
++    (void *) &ck_true, 0
++};
++static const NSSItem pem_trusted = {
++    (void *) &ckt_netscape_trusted, (PRUint32) sizeof(CK_TRUST)
++};
++
++/* SEC_SkipTemplate is already defined and exported by libnssutil */
++#ifdef SEC_SKIP_TEMPLATE
++/*
++ * Template for skipping a subitem.
++ *
++ * Note that it only makes sense to use this for decoding (when you want
++ * to decode something where you are only interested in one or two of
++ * the fields); you cannot encode a SKIP!
++ */
++const SEC_ASN1Template SEC_SkipTemplate[] = {
++    {SEC_ASN1_SKIP}
++};
++#endif
++
++/*
++ * Find the subjectName in a DER encoded certificate
++ */
++const SEC_ASN1Template SEC_CertSubjectTemplate[] = {
++    {SEC_ASN1_SEQUENCE,
++         0, NULL, sizeof(SECItem)} ,
++    {SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
++         SEC_ASN1_CONTEXT_SPECIFIC | 0,
++         0, SEC_SkipTemplate} ,  /* version */
++    {SEC_ASN1_SKIP},             /* serial number */
++    {SEC_ASN1_SKIP},             /* signature algorithm */
++    {SEC_ASN1_SKIP},             /* issuer */
++    {SEC_ASN1_SKIP},             /* validity */
++    {SEC_ASN1_ANY, 0, NULL},     /* subject */
++    {SEC_ASN1_SKIP_REST},
++    {0}
++};
++
++void
++pem_FetchLabel
++(
++    pemInternalObject * io
++)
++{
++    pemCertObject *co = &io->u.cert;
++
++    co->label.data = io->nickname;
++    co->label.size = strlen(io->nickname);
++}
++
++const NSSItem
++*pem_FetchCertAttribute
++(
++    pemInternalObject * io,
++    CK_ATTRIBUTE_TYPE type
++)
++{
++    switch (type) {
++    case CKA_CLASS:
++        plog("  fetch cert CKA_CLASS\n");
++        return &pem_certClassItem;
++    case CKA_TOKEN:
++        plog("  fetch cert CKA_TOKEN\n");
++        return &pem_trueItem;
++    case CKA_PRIVATE:
++        return &pem_falseItem;
++    case CKA_CERTIFICATE_TYPE:
++        plog("  fetch cert CKA_CERTIFICATE_TYPE\n");
++        return &pem_x509Item;
++    case CKA_LABEL:
++        if (0 == io->u.cert.label.size) {
++            pem_FetchLabel(io);
++        }
++        plog("  fetch cert CKA_LABEL %s\n", io->u.cert.label.data);
++        return &io->u.cert.label;
++    case CKA_SUBJECT:
++        plog("  fetch cert CKA_SUBJECT size %d\n", io->u.cert.subject.size);
++        return &io->u.cert.subject;
++    case CKA_ISSUER:
++        plog("  fetch cert CKA_ISSUER size %d\n", io->u.cert.issuer.size);
++        return &io->u.cert.issuer;
++    case CKA_SERIAL_NUMBER:
++        plog("  fetch cert CKA_SERIAL_NUMBER size %d value %08x\n", io->u.cert.serial.size, io->u.cert.serial.data);
++        return &io->u.cert.serial;
++    case CKA_VALUE:
++        if (0 == io->u.cert.derCert.size) {
++            io->u.cert.derCert.data = io->derCert->data;
++            io->u.cert.derCert.size = io->derCert->len;
++        }
++        plog("  fetch cert CKA_VALUE\n");
++        return &io->u.cert.derCert;
++    case CKA_ID:
++        plog("  fetch cert CKA_ID val=%s size=%d\n", (char *) io->id.data,
++             io->id.size);
++        return &io->id;
++    case CKA_TRUSTED:
++        plog("  fetch cert CKA_TRUSTED: returning NULL\n");
++        return NULL;
++    default:
++        plog("  fetching cert unknown type %d\n", type);
++        break;
++    }
++    return NULL;
++}
++
++const NSSItem *
++pem_FetchPrivKeyAttribute
++(
++    pemInternalObject * io,
++    CK_ATTRIBUTE_TYPE type
++)
++{
++    PRBool isCertType = (pemCert == io->type);
++    pemKeyParams *kp = isCertType ? &io->u.cert.key : &io->u.key.key;
++
++    switch (type) {
++    case CKA_CLASS:
++        return &pem_privKeyClassItem;
++    case CKA_TOKEN:
++    case CKA_LOCAL:
++    case CKA_SIGN:
++    case CKA_DECRYPT:
++    case CKA_SIGN_RECOVER:
++        return &pem_trueItem;
++    case CKA_SENSITIVE:
++    case CKA_PRIVATE: /* should move in the future */
++    case CKA_MODIFIABLE:
++    case CKA_DERIVE:
++    case CKA_UNWRAP:
++    case CKA_EXTRACTABLE: /* will probably move in the future */
++    case CKA_ALWAYS_SENSITIVE:
++    case CKA_NEVER_EXTRACTABLE:
++        return &pem_falseItem;
++    case CKA_KEY_TYPE:
++        return &pem_rsaItem;
++    case CKA_LABEL:
++        if (!isCertType) {
++            return &pem_emptyItem;
++        }
++        if (0 == io->u.cert.label.size) {
++            pem_FetchLabel(io);
++        }
++        plog("  fetch key CKA_LABEL %s\n", io->u.cert.label.data);
++        return &io->u.cert.label;
++    case CKA_SUBJECT:
++        if (!isCertType) {
++            return &pem_emptyItem;
++        }
++        plog("  fetch key CKA_SUBJECT %s\n", io->u.cert.label.data);
++        return &io->u.cert.subject;
++    case CKA_MODULUS:
++        if (0 == kp->modulus.size) {
++            pem_PopulateModulusExponent(io);
++        }
++        plog("  fetch key CKA_MODULUS\n");
++        return &kp->modulus;
++    case CKA_PUBLIC_EXPONENT:
++        if (0 == kp->modulus.size) {
++            pem_PopulateModulusExponent(io);
++        }
++        plog("  fetch key CKA_PUBLIC_EXPONENT\n");
++        return &kp->exponent;
++    case CKA_PRIVATE_EXPONENT:
++        if (0 == kp->privateExponent.size) {
++            pem_PopulateModulusExponent(io);
++        }
++        plog("  fetch key CKA_PRIVATE_EXPONENT\n");
++        return &kp->privateExponent;
++    case CKA_PRIME_1:
++        if (0 == kp->prime1.size) {
++            pem_PopulateModulusExponent(io);
++        }
++        plog("  fetch key CKA_PRIME_1\n");
++        return &kp->prime1;
++    case CKA_PRIME_2:
++        if (0 == kp->prime2.size) {
++            pem_PopulateModulusExponent(io);
++        }
++        plog("  fetch key CKA_PRIME_2\n");
++        return &kp->prime2;
++    case CKA_EXPONENT_1:
++        if (0 == kp->exponent1.size) {
++            pem_PopulateModulusExponent(io);
++        }
++        plog("  fetch key CKA_EXPONENT_1\n");
++        return &kp->exponent1;
++    case CKA_EXPONENT_2:
++        if (0 == kp->exponent2.size) {
++            pem_PopulateModulusExponent(io);
++        }
++        plog("  fetch key CKA_EXPONENT_2\n");
++        return &kp->exponent2;
++    case CKA_COEFFICIENT:
++        if (0 == kp->coefficient.size) {
++            pem_PopulateModulusExponent(io);
++        }
++        plog("  fetch key CKA_COEFFICIENT_2\n");
++        return &kp->coefficient;
++    case CKA_ID:
++        plog("  fetch key CKA_ID val=%s size=%d\n", (char *) io->id.data,
++             io->id.size);
++        return &io->id;
++    default:
++        return NULL;
++    }
++}
++
++const NSSItem *
++pem_FetchPubKeyAttribute
++(
++    pemInternalObject * io,
++    CK_ATTRIBUTE_TYPE type
++)
++{
++    PRBool isCertType = (pemCert == io->type);
++    pemKeyParams *kp = isCertType ? &io->u.cert.key : &io->u.key.key;
++
++    switch (type) {
++    case CKA_CLASS:
++        return &pem_pubKeyClassItem;
++    case CKA_TOKEN:
++    case CKA_LOCAL:
++    case CKA_ENCRYPT:
++    case CKA_VERIFY:
++    case CKA_VERIFY_RECOVER:
++        return &pem_trueItem;
++    case CKA_PRIVATE:
++    case CKA_MODIFIABLE:
++    case CKA_DERIVE:
++    case CKA_WRAP:
++        return &pem_falseItem;
++    case CKA_KEY_TYPE:
++        return &pem_rsaItem;
++    case CKA_LABEL:
++        if (!isCertType) {
++            return &pem_emptyItem;
++        }
++        if (0 == io->u.cert.label.size) {
++            pem_FetchLabel(io);
++        }
++        return &io->u.cert.label;
++    case CKA_SUBJECT:
++        if (!isCertType) {
++            return &pem_emptyItem;
++        }
++        return &io->u.cert.subject;
++    case CKA_MODULUS:
++        if (0 == kp->modulus.size) {
++            pem_PopulateModulusExponent(io);
++        }
++        return &kp->modulus;
++    case CKA_PUBLIC_EXPONENT:
++        if (0 == kp->modulus.size) {
++            pem_PopulateModulusExponent(io);
++        }
++        return &kp->exponent;
++    case CKA_ID:
++        return &io->id;
++    default:
++        break;
++    }
++    return NULL;
++}
++
++const NSSItem *
++pem_FetchTrustAttribute
++(
++    pemInternalObject * io,
++    CK_ATTRIBUTE_TYPE type
++)
++{
++    static NSSItem hash;
++    SECStatus rv;
++
++    switch (type) {
++    case CKA_CLASS:
++        return &pem_trustClassItem;
++    case CKA_TOKEN:
++        return &pem_trueItem;
++    case CKA_PRIVATE:
++        return &pem_falseItem;
++    case CKA_CERTIFICATE_TYPE:
++        return &pem_x509Item;
++    case CKA_LABEL:
++        if (0 == io->u.cert.label.size) {
++            pem_FetchLabel(io);
++        }
++        plog("  fetch trust CKA_LABEL %s\n", io->u.cert.label.data);
++        return &io->u.cert.label;
++    case CKA_SUBJECT:
++        plog("  fetch trust CKA_SUBJECT\n");
++        return NULL;
++    case CKA_ISSUER:
++        plog("  fetch trust CKA_ISSUER\n");
++        return &io->u.cert.issuer;
++    case CKA_SERIAL_NUMBER:
++        plog("  fetch trust CKA_SERIAL_NUMBER size %d value %08x\n", io->u.cert.serial.size, io->u.cert.serial.data);
++        return &io->u.cert.serial;
++    case CKA_VALUE:
++        return &pem_trueItem;
++    case CKA_ID:
++        plog("  fetch trust CKA_ID val=%s size=%d\n", (char *) io->id.data,
++             io->id.size);
++        return &io->id;
++    case CKA_TRUSTED:
++        return &pem_trusted;
++    case CKA_TRUST_SERVER_AUTH:
++        return &pem_trusted;
++    case CKA_TRUST_CLIENT_AUTH:
++        return &pem_trusted;
++    case CKA_TRUST_CODE_SIGNING:
++        return &pem_trusted;
++    case CKA_TRUST_EMAIL_PROTECTION:
++        return &pem_trusted;
++    case CKA_TRUST_IPSEC_END_SYSTEM:
++        return &pem_trusted;
++    case CKA_TRUST_IPSEC_TUNNEL:
++        return &pem_trusted;
++    case CKA_TRUST_IPSEC_USER:
++        return &pem_trusted;
++    case CKA_TRUST_TIME_STAMPING:
++        return &pem_trusted;
++    case CKA_TRUST_STEP_UP_APPROVED:
++        return &pem_falseItem;
++    case CKA_CERT_SHA1_HASH:
++        hash.size = 0;
++        hash.data = NULL;
++        nsslibc_memset(io->u.cert.sha1_hash, 0, SHA1_LENGTH);
++        rv = SHA1_HashBuf(io->u.cert.sha1_hash, io->derCert->data,
++                          io->derCert->len);
++        if (rv == SECSuccess) {
++            hash.data = io->u.cert.sha1_hash;
++            hash.size = sizeof(io->u.cert.sha1_hash);
++        }
++        return &hash;
++    case CKA_CERT_MD5_HASH:
++        hash.size = 0;
++        hash.data = NULL;
++        nsslibc_memset(io->u.cert.sha1_hash, 0, MD5_LENGTH);
++        rv = MD5_HashBuf(io->u.cert.sha1_hash, io->derCert->data,
++                         io->derCert->len);
++        if (rv == SECSuccess) {
++            hash.data = io->u.cert.sha1_hash;
++            hash.size = sizeof(io->u.cert.sha1_hash);
++        }
++        return &hash;
++    default:
++        return &pem_trusted;
++        break;
++    }
++    return NULL;
++}
++
++const NSSItem *
++pem_FetchAttribute
++(
++    pemInternalObject * io,
++    CK_ATTRIBUTE_TYPE type
++)
++{
++    CK_ULONG i;
++
++    if (io->type == pemRaw) {
++        for (i = 0; i < io->u.raw.n; i++) {
++            if (type == io->u.raw.types[i]) {
++                return &io->u.raw.items[i];
++            }
++        }
++        return NULL;
++    }
++    /* deal with the common attributes */
++    switch (io->objClass) {
++    case CKO_CERTIFICATE:
++        return pem_FetchCertAttribute(io, type);
++    case CKO_PRIVATE_KEY:
++        return pem_FetchPrivKeyAttribute(io, type);
++    case CKO_NETSCAPE_TRUST:
++        return pem_FetchTrustAttribute(io, type);
++    case CKO_PUBLIC_KEY:
++        return pem_FetchPubKeyAttribute(io, type);
++    }
++    return NULL;
++}
++
++/*
++ * Destroy internal object or list object if refCount becomes zero (after
++ * decrement). Safe to call with NULL argument.
++ */
++void
++pem_DestroyInternalObject
++(
++    pemInternalObject * io
++)
++{
++    if (NULL == io)
++        /* nothing to destroy */
++        return;
++
++    if (NULL != io->list) {
++        /* destroy list object */
++        pemObjectListItem *item = io->list;
++        while (item) {
++            pemObjectListItem *next = item->next;
++
++            /* recursion of maximal depth 1 */
++            pem_DestroyInternalObject(item->io);
++
++            nss_ZFreeIf(item);
++            item = next;
++        }
++        nss_ZFreeIf(io);
++        return;
++    }
++
++    io->refCount --;
++    if (0 < io->refCount)
++        return;
++
++    /* destroy internal object */
++    switch (io->type) {
++    case pemRaw:
++        return;
++    case pemCert:
++        nss_ZFreeIf(io->u.cert.labelData);
++        nss_ZFreeIf(io->u.cert.key.privateKey);
++        nss_ZFreeIf(io->u.cert.key.pubKey);
++        /* go through */
++    case pemTrust:
++        nss_ZFreeIf(io->id.data);
++        nss_ZFreeIf(io->nickname);
++        nss_ZFreeIf(io->derCert->data);
++        nss_ZFreeIf(io->derCert);
++        if (io->u.cert.subject.size > 0) {
++            nss_ZFreeIf(io->u.cert.subject.data);
++        }
++        if (io->u.cert.issuer.size > 0) {
++            nss_ZFreeIf(io->u.cert.issuer.data);
++        }
++        if (io->u.cert.serial.size > 0) {
++            nss_ZFreeIf(io->u.cert.serial.data);
++        }
++        break;
++    case pemBareKey:
++        SECITEM_FreeItem(io->u.key.key.privateKeyOrig, PR_TRUE);
++        nss_ZFreeIf(io->u.key.key.coefficient.data);
++        nss_ZFreeIf(io->u.key.key.exponent2.data);
++        nss_ZFreeIf(io->u.key.key.exponent1.data);
++        nss_ZFreeIf(io->u.key.key.prime2.data);
++        nss_ZFreeIf(io->u.key.key.prime1.data);
++        nss_ZFreeIf(io->u.key.key.privateExponent.data);
++        nss_ZFreeIf(io->u.key.key.exponent.data);
++        nss_ZFreeIf(io->u.key.key.modulus.data);
++        nss_ZFreeIf(io->u.key.key.privateKey->data);
++        nss_ZFreeIf(io->u.key.key.privateKey);
++        nss_ZFreeIf(io->u.key.key.pubKey);
++        nss_ZFreeIf(io->id.data);
++        nss_ZFreeIf(io->nickname);
++        nss_ZFreeIf(io->derCert->data);
++        nss_ZFreeIf(io->derCert);
++
++        /* strdup'd in ReadDERFromFile */
++        if (io->u.key.ivstring)
++            free(io->u.key.ivstring);
++        break;
++    }
++
++    if (NULL != gobj)
++        /* remove reference to self from the global array */
++        gobj[io->gobjIndex] = NULL;
++
++    nss_ZFreeIf(io);
++    return;
++}
++
++/*
++ * Finalize - needed
++ * Destroy - CKR_SESSION_READ_ONLY
++ * IsTokenObject - CK_TRUE
++ * GetAttributeCount
++ * GetAttributeTypes
++ * GetAttributeSize
++ * GetAttribute
++ * SetAttribute - unneeded
++ * GetObjectSize - unneeded
++ */
++
++static void
++pem_mdObject_Finalize
++(
++    NSSCKMDObject * mdObject,
++    NSSCKFWObject * fwObject,
++    NSSCKMDSession * mdSession,
++    NSSCKFWSession * fwSession,
++    NSSCKMDToken * mdToken,
++    NSSCKFWToken * fwToken,
++    NSSCKMDInstance * mdInstance,
++    NSSCKFWInstance * fwInstance
++)
++{
++    pem_DestroyInternalObject((pemInternalObject *) mdObject->etc);
++}
++
++static CK_RV
++pem_mdObject_Destroy
++(
++    NSSCKMDObject * mdObject,
++    NSSCKFWObject * fwObject,
++    NSSCKMDSession * mdSession,
++    NSSCKFWSession * fwSession,
++    NSSCKMDToken * mdToken,
++    NSSCKFWToken * fwToken,
++    NSSCKMDInstance * mdInstance,
++    NSSCKFWInstance * fwInstance
++)
++{
++    pemInternalObject *io = (pemInternalObject *) mdObject->etc;
++
++    pem_DestroyInternalObject(io);
++    return CKR_OK;
++}
++
++static CK_BBOOL
++pem_mdObject_IsTokenObject
++(
++    NSSCKMDObject * mdObject,
++    NSSCKFWObject * fwObject,
++    NSSCKMDSession * mdSession,
++    NSSCKFWSession * fwSession,
++    NSSCKMDToken * mdToken,
++    NSSCKFWToken * fwToken,
++    NSSCKMDInstance * mdInstance,
++    NSSCKFWInstance * fwInstance
++)
++{
++    return CK_TRUE;
++}
++
++static CK_ULONG
++pem_mdObject_GetAttributeCount
++(
++    NSSCKMDObject * mdObject,
++    NSSCKFWObject * fwObject,
++    NSSCKMDSession * mdSession,
++    NSSCKFWSession * fwSession,
++    NSSCKMDToken * mdToken,
++    NSSCKFWToken * fwToken,
++    NSSCKMDInstance * mdInstance,
++    NSSCKFWInstance * fwInstance,
++    CK_RV * pError
++)
++{
++    pemInternalObject *io = (pemInternalObject *) mdObject->etc;
++
++    if (NULL != io->list) {
++        /* list object --> use the first item in the list */
++        NSSCKMDObject *md = &(io->list->io->mdObject);
++        return md->GetAttributeCount(md, fwObject, mdSession, fwSession,
++                                     mdToken, fwToken, mdInstance, fwInstance,
++                                     pError);
++    }
++
++    if (pemRaw == io->type) {
++        return io->u.raw.n;
++    }
++    switch (io->objClass) {
++    case CKO_CERTIFICATE:
++        return certAttrsCount;
++    case CKO_PUBLIC_KEY:
++        return pubKeyAttrsCount;
++    case CKO_PRIVATE_KEY:
++        return privKeyAttrsCount;
++    case CKO_NETSCAPE_TRUST:
++        return trustAttrsCount;

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list