fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / external / nss / nss-pem.patch
blobc3f28bc74a6d5cd98ffca1c2a21f35aef297013e
1 diff --git a/a/nss/lib/ckfw/manifest.mn b/b/nss/lib/ckfw/manifest.mn
2 index 20bebeb..4f10563 100644
3 --- a/a/nss/lib/ckfw/manifest.mn
4 +++ b/b/nss/lib/ckfw/manifest.mn
5 @@ -5,7 +5,7 @@
7 CORE_DEPTH = ../..
9 -DIRS = builtins
10 +DIRS = builtins pem
12 PRIVATE_EXPORTS = \
13 ck.h \
14 diff --git a/a/nss/lib/ckfw/pem/Makefile b/b/nss/lib/ckfw/pem/Makefile
15 new file mode 100644
16 index 0000000..aec3bbd
17 --- /dev/null
18 +++ b/b/nss/lib/ckfw/pem/Makefile
19 @@ -0,0 +1,107 @@
20 +#
21 +# ***** BEGIN LICENSE BLOCK *****
22 +# Version: MPL 1.1/GPL 2.0/LGPL 2.1
24 +# The contents of this file are subject to the Mozilla Public License Version
25 +# 1.1 (the "License"); you may not use this file except in compliance with
26 +# the License. You may obtain a copy of the License at
27 +# http://www.mozilla.org/MPL/
29 +# Software distributed under the License is distributed on an "AS IS" basis,
30 +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
31 +# for the specific language governing rights and limitations under the
32 +# License.
34 +# The Original Code is the Netscape security libraries.
36 +# The Initial Developer of the Original Code is
37 +# Netscape Communications Corporation.
38 +# Portions created by the Initial Developer are Copyright (C) 1994-2000
39 +# the Initial Developer. All Rights Reserved.
41 +# Contributor(s):
43 +# Alternatively, the contents of this file may be used under the terms of
44 +# either the GNU General Public License Version 2 or later (the "GPL"), or
45 +# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
46 +# in which case the provisions of the GPL or the LGPL are applicable instead
47 +# of those above. If you wish to allow use of your version of this file only
48 +# under the terms of either the GPL or the LGPL, and not to allow others to
49 +# use your version of this file under the terms of the MPL, indicate your
50 +# decision by deleting the provisions above and replace them with the notice
51 +# and other provisions required by the GPL or the LGPL. If you do not delete
52 +# the provisions above, a recipient may use your version of this file under
53 +# the terms of any one of the MPL, the GPL or the LGPL.
55 +# ***** END LICENSE BLOCK *****
56 +MAKEFILE_CVS_ID = "@(#) $RCSfile: Makefile,v $ $Revision: 1.5 $ $Date: 2007/05/09 00:09:37 $"
58 +include manifest.mn
59 +include $(CORE_DEPTH)/coreconf/config.mk
60 +include config.mk
62 +EXTRA_LIBS = \
63 + $(DIST)/lib/$(LIB_PREFIX)nssckfw.$(LIB_SUFFIX) \
64 + $(DIST)/lib/$(LIB_PREFIX)nssb.$(LIB_SUFFIX) \
65 + $(DIST)/lib/$(LIB_PREFIX)freebl.$(LIB_SUFFIX) \
66 + $(DIST)/lib/$(LIB_PREFIX)nssutil.$(LIB_SUFFIX) \
67 + $(NULL)
69 +# can't do this in manifest.mn because OS_TARGET isn't defined there.
70 +ifeq (,$(filter-out WIN%,$(OS_TARGET)))
72 +ifdef NS_USE_GCC
73 +EXTRA_LIBS += \
74 + -L$(NSPR_LIB_DIR) \
75 + -lplc4 \
76 + -lplds4 \
77 + -lnspr4 \
78 + $(NULL)
79 +else
80 +EXTRA_SHARED_LIBS += \
81 + $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plc4.lib \
82 + $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plds4.lib \
83 + $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)nspr4.lib \
84 + crypt32.lib \
85 + advapi32.lib \
86 + rpcrt4.lib \
87 + $(NULL)
88 +endif # NS_USE_GCC
89 +else
91 +EXTRA_LIBS += \
92 + -L$(NSPR_LIB_DIR) \
93 + -lplc4 \
94 + -lplds4 \
95 + -lnspr4 \
96 + $(NULL)
97 +endif
100 +include $(CORE_DEPTH)/coreconf/rules.mk
102 +# Generate certdata.c.
103 +generate:
104 + $(PERL) certdata.perl < certdata.txt
106 +# This'll need some help from a build person.
109 +ifeq ($(OS_TARGET)$(OS_RELEASE), AIX4.1)
110 +DSO_LDOPTS = -bM:SRE -bh:4 -bnoentry
111 +EXTRA_DSO_LDOPTS = -lc
112 +MKSHLIB = xlC $(DSO_LDOPTS)
114 +$(SHARED_LIBRARY): $(OBJS)
115 + @$(MAKE_OBJDIR)
116 + rm -f $@
117 + $(MKSHLIB) -o $@ $(OBJS) $(EXTRA_LIBS) $(EXTRA_DSO_LDOPTS)
118 + chmod +x $@
120 +endif
122 +ifeq ($(OS_TARGET)$(OS_RELEASE), AIX4.2)
123 +LD += -G
124 +endif
127 diff --git a/a/nss/lib/ckfw/pem/anchor.c b/b/nss/lib/ckfw/pem/anchor.c
128 new file mode 100644
129 index 0000000..621f919
130 --- /dev/null
131 +++ b/b/nss/lib/ckfw/pem/anchor.c
132 @@ -0,0 +1,50 @@
133 +/* ***** BEGIN LICENSE BLOCK *****
134 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
136 + * The contents of this file are subject to the Mozilla Public License Version
137 + * 1.1 (the "License"); you may not use this file except in compliance with
138 + * the License. You may obtain a copy of the License at
139 + * http://www.mozilla.org/MPL/
141 + * Software distributed under the License is distributed on an "AS IS" basis,
142 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
143 + * for the specific language governing rights and limitations under the
144 + * License.
146 + * The Original Code is the Netscape security libraries.
148 + * The Initial Developer of the Original Code is
149 + * Netscape Communications Corporation.
150 + * Portions created by the Initial Developer are Copyright (C) 1994-2000
151 + * the Initial Developer. All Rights Reserved.
153 + * Contributor(s):
154 + * Rob Crittenden (rcritten@redhat.com)
156 + * Alternatively, the contents of this file may be used under the terms of
157 + * either the GNU General Public License Version 2 or later (the "GPL"), or
158 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
159 + * in which case the provisions of the GPL or the LGPL are applicable instead
160 + * of those above. If you wish to allow use of your version of this file only
161 + * under the terms of either the GPL or the LGPL, and not to allow others to
162 + * use your version of this file under the terms of the MPL, indicate your
163 + * decision by deleting the provisions above and replace them with the notice
164 + * and other provisions required by the GPL or the LGPL. If you do not delete
165 + * the provisions above, a recipient may use your version of this file under
166 + * the terms of any one of the MPL, the GPL or the LGPL.
168 + * ***** END LICENSE BLOCK ***** */
171 + * anchor.c
173 + * This file "anchors" the actual cryptoki entry points in this module's
174 + * shared library, which is required for dynamic loading. See the
175 + * comments in nssck.api for more information.
176 + */
178 +#include "ckpem.h"
180 +#define MODULE_NAME pem
181 +#define INSTANCE_NAME (NSSCKMDInstance *)&pem_mdInstance
182 +#include "nssck.api"
183 diff --git a/a/nss/lib/ckfw/pem/ckpem.h b/b/nss/lib/ckfw/pem/ckpem.h
184 new file mode 100644
185 index 0000000..9712ccd
186 --- /dev/null
187 +++ b/b/nss/lib/ckfw/pem/ckpem.h
188 @@ -0,0 +1,263 @@
189 +#ifndef CKPEM_H
190 +#define CKPEM_H
192 +#include "nssckmdt.h"
193 +#include "nssckfw.h"
194 +#include "ckfwtm.h"
195 +#include "ckfw.h"
196 +#include "secder.h"
197 +#include "secoid.h"
198 +#include "secasn1.h"
199 +#include "blapit.h"
200 +#include "softoken.h"
203 + * I'm including this for access to the arena functions.
204 + * Looks like we should publish that API.
205 + */
206 +#ifndef BASE_H
207 +#include "base.h"
208 +#endif /* BASE_H */
211 + * This is where the Netscape extensions live, at least for now.
212 + */
213 +#ifndef CKT_H
214 +#include "ckt.h"
215 +#endif /* CKT_H */
217 +#define NUM_SLOTS 8
220 + * statically defined raw objects. Allows us to data description objects
221 + * to this PKCS #11 module.
222 + */
223 +struct pemRawObjectStr {
224 + CK_ULONG n;
225 + const CK_ATTRIBUTE_TYPE *types;
226 + const NSSItem *items;
228 +typedef struct pemRawObjectStr pemRawObject;
231 + * common values needed for both bare keys and cert referenced keys.
232 + */
233 +struct pemKeyParamsStr {
234 + NSSItem modulus;
235 + NSSItem exponent;
236 + NSSItem privateExponent;
237 + NSSItem prime1;
238 + NSSItem prime2;
239 + NSSItem exponent1;
240 + NSSItem exponent2;
241 + NSSItem coefficient;
242 + unsigned char publicExponentData[sizeof(CK_ULONG)];
243 + SECItem *privateKey;
244 + SECItem *privateKeyOrig; /* deep copy of privateKey until decrypted */
245 + void *pubKey;
247 +typedef struct pemKeyParamsStr pemKeyParams;
249 + * Key objects. Handles bare keys which do not yet have certs associated
250 + * with them. These are usually short lived, but may exist for several days
251 + * while the CA is issuing the certificate.
252 + */
253 +struct pemKeyObjectStr {
254 + char *provName;
255 + char *containerName;
256 + pemKeyParams key;
257 + char *ivstring;
258 + int cipher;
260 +typedef struct pemKeyObjectStr pemKeyObject;
263 + * Certificate and certificate referenced keys.
264 + */
265 +struct pemCertObjectStr {
266 + const char *certStore;
267 + NSSItem label;
268 + NSSItem subject;
269 + NSSItem issuer;
270 + NSSItem serial;
271 + NSSItem derCert;
272 + unsigned char sha1_hash[SHA1_LENGTH];
273 + unsigned char md5_hash[MD5_LENGTH];
274 + pemKeyParams key;
275 + unsigned char *labelData;
276 + /* static data: to do, make this dynamic like labelData */
277 + unsigned char derSerial[128];
279 +typedef struct pemCertObjectStr pemCertObject;
282 + * Trust
283 + */
284 +struct pemTrustObjectStr {
285 + char *nickname;
287 +typedef struct pemTrustObjectStr pemTrustObject;
289 +typedef enum {
290 + pemAll = -1, /* matches all types */
291 + pemRaw,
292 + pemCert,
293 + pemBareKey,
294 + pemTrust
295 +} pemObjectType;
297 +typedef struct pemInternalObjectStr pemInternalObject;
298 +typedef struct pemObjectListItemStr pemObjectListItem;
301 + * singly-linked list of internal objects
302 + */
303 +struct pemObjectListItemStr {
304 + pemInternalObject *io;
305 + pemObjectListItem *next;
309 + * all the various types of objects are abstracted away in cobject and
310 + * cfind as pemInternalObjects.
311 + */
312 +struct pemInternalObjectStr {
313 + pemObjectType type;
314 + union {
315 + pemRawObject raw;
316 + pemCertObject cert;
317 + pemKeyObject key;
318 + pemTrustObject trust;
319 + } u;
320 + CK_OBJECT_CLASS objClass;
321 + NSSItem hashKey;
322 + NSSItem id;
323 + unsigned char hashKeyData[128];
324 + SECItem *derCert;
325 + char *nickname;
326 + NSSCKMDObject mdObject;
327 + CK_SLOT_ID slotID;
328 + CK_ULONG gobjIndex;
329 + int refCount;
331 + /* used by pem_mdFindObjects_Next */
332 + CK_BBOOL extRef;
334 + /* If list != NULL, the object contains no useful data except of the list
335 + * of slave objects */
336 + pemObjectListItem *list;
339 +struct pemTokenStr {
340 + PRBool logged_in;
342 +typedef struct pemTokenStr pemToken;
344 +/* our raw object data array */
345 +NSS_EXTERN_DATA pemInternalObject nss_pem_data[];
346 +NSS_EXTERN_DATA const PRUint32 nss_pem_nObjects;
348 +/* our raw object data array */
349 +NSS_EXTERN_DATA pemInternalObject nss_pem_data[];
350 +NSS_EXTERN_DATA const PRUint32 nss_pem_nObjects;
352 +NSS_EXTERN_DATA pemInternalObject pem_data[];
353 +NSS_EXTERN_DATA const PRUint32 pem_nObjects;
355 +NSS_EXTERN_DATA const CK_VERSION pem_CryptokiVersion;
356 +NSS_EXTERN_DATA const NSSUTF8 * pem_ManufacturerID;
357 +NSS_EXTERN_DATA const NSSUTF8 * pem_LibraryDescription;
358 +NSS_EXTERN_DATA const CK_VERSION pem_LibraryVersion;
359 +NSS_EXTERN_DATA const NSSUTF8 * pem_SlotDescription;
360 +NSS_EXTERN_DATA const CK_VERSION pem_HardwareVersion;
361 +NSS_EXTERN_DATA const CK_VERSION pem_FirmwareVersion;
362 +NSS_EXTERN_DATA const NSSUTF8 * pem_TokenLabel;
363 +NSS_EXTERN_DATA const NSSUTF8 * pem_TokenModel;
364 +NSS_EXTERN_DATA const NSSUTF8 * pem_TokenSerialNumber;
366 +NSS_EXTERN_DATA const NSSCKMDInstance pem_mdInstance;
367 +NSS_EXTERN_DATA const NSSCKMDSlot pem_mdSlot;
368 +NSS_EXTERN_DATA const NSSCKMDToken pem_mdToken;
369 +NSS_EXTERN_DATA const NSSCKMDMechanism pem_mdMechanismRSA;
371 +NSS_EXTERN NSSCKMDSession *
372 +pem_CreateSession
374 + NSSCKFWSession *fwSession,
375 + CK_RV *pError
378 +NSS_EXTERN NSSCKMDFindObjects *
379 +pem_FindObjectsInit
381 + NSSCKFWSession *fwSession,
382 + CK_ATTRIBUTE_PTR pTemplate,
383 + CK_ULONG ulAttributeCount,
384 + CK_RV *pError
387 +NSS_EXTERN NSSCKMDObject *
388 +pem_CreateMDObject
390 + NSSArena *arena,
391 + pemInternalObject *io,
392 + CK_RV *pError
395 +#define NSS_PEM_ARRAY_SIZE(x) ((sizeof (x))/(sizeof ((x)[0])))
397 +typedef enum {
398 + pemLOWKEYNullKey = 0,
399 + pemLOWKEYRSAKey = 1,
400 + pemLOWKEYDSAKey = 2,
401 + pemLOWKEYDHKey = 4,
402 + pemLOWKEYECKey = 5
403 +} pemLOWKEYType;
406 +** Low Level private key object
407 +** This is only used by the raw Crypto engines (crypto), keydb (keydb),
408 +** and PKCS #11. Everyone else uses the high level key structure.
410 +struct pemLOWKEYPrivateKeyStr {
411 + PLArenaPool *arena;
412 + pemLOWKEYType keyType;
413 + union {
414 + RSAPrivateKey rsa;
415 + DSAPrivateKey dsa;
416 + DHPrivateKey dh;
417 + ECPrivateKey ec;
418 + } u;
420 +typedef struct pemLOWKEYPrivateKeyStr pemLOWKEYPrivateKey;
422 +SECStatus ReadDERFromFile(SECItem ***derlist, char *filename, PRBool ascii, int *cipher, char **ivstring, PRBool certsonly);
423 +const NSSItem * pem_FetchAttribute ( pemInternalObject *io, CK_ATTRIBUTE_TYPE type);
424 +void pem_PopulateModulusExponent(pemInternalObject *io);
425 +NSSCKMDObject * pem_CreateObject(NSSCKFWInstance *fwInstance, NSSCKFWSession *fwSession, NSSCKMDToken *mdToken, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, CK_RV *pError);
426 +NSSCKMDSlot *pem_NewSlot( NSSCKFWInstance *fwInstance, CK_RV *pError);
429 +PRBool pem_ParseString(const char* inputstring, const char delimiter,
430 + PRInt32* numStrings, char*** returnedstrings);
431 +PRBool pem_FreeParsedStrings(PRInt32 numStrings, char** instrings);
433 +pemInternalObject *
434 +AddObjectIfNeeded(CK_OBJECT_CLASS objClass, pemObjectType type,
435 + SECItem *certDER, SECItem *keyDER, char *filename, int objid,
436 + CK_SLOT_ID slotID, PRBool *pAdded);
438 +void pem_DestroyInternalObject (pemInternalObject *io);
441 +/* prsa.c */
442 +unsigned int pem_PrivateModulusLen(pemLOWKEYPrivateKey *privk);
444 +/* ptoken.c */
445 +NSSCKMDToken * pem_NewToken(NSSCKFWInstance *fwInstance, CK_RV *pError);
447 +/* util.c */
448 +void open_log();
449 +void plog(const char *fmt, ...);
451 +#endif /* CKPEM_H */
452 diff --git a/a/nss/lib/ckfw/pem/ckpemver.c b/b/nss/lib/ckfw/pem/ckpemver.c
453 new file mode 100644
454 index 0000000..76ab5df
455 --- /dev/null
456 +++ b/b/nss/lib/ckfw/pem/ckpemver.c
457 @@ -0,0 +1,59 @@
458 +/* ***** BEGIN LICENSE BLOCK *****
459 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
461 + * The contents of this file are subject to the Mozilla Public License Version
462 + * 1.1 (the "License"); you may not use this file except in compliance with
463 + * the License. You may obtain a copy of the License at
464 + * http://www.mozilla.org/MPL/
466 + * Software distributed under the License is distributed on an "AS IS" basis,
467 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
468 + * for the specific language governing rights and limitations under the
469 + * License.
471 + * The Original Code is the Netscape security libraries.
473 + * The Initial Developer of the Original Code is
474 + * Netscape Communications Corporation.
475 + * Portions created by the Initial Developer are Copyright (C) 1994-2000
476 + * the Initial Developer. All Rights Reserved.
477 + * Portions created by Red Hat, Inc, are Copyright (C) 2005
479 + * Contributor(s):
480 + * Rob Crittenden (rcritten@redhat.com)
482 + * Alternatively, the contents of this file may be used under the terms of
483 + * either the GNU General Public License Version 2 or later (the "GPL"), or
484 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
485 + * in which case the provisions of the GPL or the LGPL are applicable instead
486 + * of those above. If you wish to allow use of your version of this file only
487 + * under the terms of either the GPL or the LGPL, and not to allow others to
488 + * use your version of this file under the terms of the MPL, indicate your
489 + * decision by deleting the provisions above and replace them with the notice
490 + * and other provisions required by the GPL or the LGPL. If you do not delete
491 + * the provisions above, a recipient may use your version of this file under
492 + * the terms of any one of the MPL, the GPL or the LGPL.
494 + * ***** END LICENSE BLOCK ***** */
495 +/* Library identity and versioning */
497 +#include "nsspem.h"
499 +#if defined(DEBUG)
500 +#define _DEBUG_STRING " (debug)"
501 +#else
502 +#define _DEBUG_STRING ""
503 +#endif
506 + * Version information for the 'ident' and 'what commands
508 + * NOTE: the first component of the concatenated rcsid string
509 + * must not end in a '$' to prevent rcs keyword substitution.
510 + */
511 +const char __nss_ckpem_rcsid[] = "$Header: NSS Access to Flat Files in PEM format"
512 + NSS_CKPEM_LIBRARY_VERSION _DEBUG_STRING
513 + " " __DATE__ " " __TIME__ " $";
514 +const char __nss_ckcapi_sccsid[] = "@(#)NSS Access to Flag Files in PEM format "
515 + NSS_CKPEM_LIBRARY_VERSION _DEBUG_STRING
516 + " " __DATE__ " " __TIME__;
517 diff --git a/a/nss/lib/ckfw/pem/config.mk b/b/nss/lib/ckfw/pem/config.mk
518 new file mode 100644
519 index 0000000..ff6cd9a
520 --- /dev/null
521 +++ b/b/nss/lib/ckfw/pem/config.mk
522 @@ -0,0 +1,71 @@
524 +# ***** BEGIN LICENSE BLOCK *****
525 +# Version: MPL 1.1/GPL 2.0/LGPL 2.1
527 +# The contents of this file are subject to the Mozilla Public License Version
528 +# 1.1 (the "License"); you may not use this file except in compliance with
529 +# the License. You may obtain a copy of the License at
530 +# http://www.mozilla.org/MPL/
532 +# Software distributed under the License is distributed on an "AS IS" basis,
533 +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
534 +# for the specific language governing rights and limitations under the
535 +# License.
537 +# The Original Code is the Netscape security libraries.
539 +# The Initial Developer of the Original Code is
540 +# Netscape Communications Corporation.
541 +# Portions created by the Initial Developer are Copyright (C) 1994-2000
542 +# the Initial Developer. All Rights Reserved.
544 +# Contributor(s):
546 +# Alternatively, the contents of this file may be used under the terms of
547 +# either the GNU General Public License Version 2 or later (the "GPL"), or
548 +# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
549 +# in which case the provisions of the GPL or the LGPL are applicable instead
550 +# of those above. If you wish to allow use of your version of this file only
551 +# under the terms of either the GPL or the LGPL, and not to allow others to
552 +# use your version of this file under the terms of the MPL, indicate your
553 +# decision by deleting the provisions above and replace them with the notice
554 +# and other provisions required by the GPL or the LGPL. If you do not delete
555 +# the provisions above, a recipient may use your version of this file under
556 +# the terms of any one of the MPL, the GPL or the LGPL.
558 +# ***** END LICENSE BLOCK *****
559 +CONFIG_CVS_ID = "@(#) $RCSfile: config.mk,v $ $Revision: 1.11 $ $Date: 2005/01/20 02:25:46 $"
562 +# Override TARGETS variable so that only shared libraries
563 +# are specifed as dependencies within rules.mk.
566 +TARGETS = $(SHARED_LIBRARY)
567 +LIBRARY =
568 +IMPORT_LIBRARY =
569 +PROGRAM =
571 +ifeq (,$(filter-out WIN%,$(OS_TARGET)))
572 + SHARED_LIBRARY = $(OBJDIR)/$(DLL_PREFIX)$(LIBRARY_NAME)$(LIBRARY_VERSION).$(DLL_SUFFIX)
573 + RES = $(OBJDIR)/$(LIBRARY_NAME).res
574 + RESNAME = $(LIBRARY_NAME).rc
575 +endif
577 +ifdef BUILD_IDG
578 + DEFINES += -DNSSDEBUG
579 +endif
582 +# To create a loadable module on Darwin, we must use -bundle.
584 +ifeq ($(OS_TARGET),Darwin)
585 +DSO_LDOPTS = -bundle
586 +endif
588 +ifeq ($(OS_TARGET),SunOS)
589 +# The -R '$ORIGIN' linker option instructs this library to search for its
590 +# dependencies in the same directory where it resides.
591 +MKSHLIB += -R '$$ORIGIN'
592 +endif
594 diff --git a/a/nss/lib/ckfw/pem/constants.c b/b/nss/lib/ckfw/pem/constants.c
595 new file mode 100644
596 index 0000000..0ceb443
597 --- /dev/null
598 +++ b/b/nss/lib/ckfw/pem/constants.c
599 @@ -0,0 +1,77 @@
600 +/* ***** BEGIN LICENSE BLOCK *****
601 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
603 + * The contents of this file are subject to the Mozilla Public License Version
604 + * 1.1 (the "License"); you may not use this file except in compliance with
605 + * the License. You may obtain a copy of the License at
606 + * http://www.mozilla.org/MPL/
608 + * Software distributed under the License is distributed on an "AS IS" basis,
609 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
610 + * for the specific language governing rights and limitations under the
611 + * License.
613 + * The Original Code is the Netscape security libraries.
615 + * The Initial Developer of the Original Code is
616 + * Netscape Communications Corporation.
617 + * Portions created by the Initial Developer are Copyright (C) 1994-2000
618 + * the Initial Developer. All Rights Reserved.
620 + * Contributor(s):
621 + * Rob Crittenden (rcritten@redhat.com)
623 + * Alternatively, the contents of this file may be used under the terms of
624 + * either the GNU General Public License Version 2 or later (the "GPL"), or
625 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
626 + * in which case the provisions of the GPL or the LGPL are applicable instead
627 + * of those above. If you wish to allow use of your version of this file only
628 + * under the terms of either the GPL or the LGPL, and not to allow others to
629 + * use your version of this file under the terms of the MPL, indicate your
630 + * decision by deleting the provisions above and replace them with the notice
631 + * and other provisions required by the GPL or the LGPL. If you do not delete
632 + * the provisions above, a recipient may use your version of this file under
633 + * the terms of any one of the MPL, the GPL or the LGPL.
635 + * ***** END LICENSE BLOCK ***** */
637 + * constants.c
639 + * Identification and other constants, all collected here in one place.
640 + */
642 +#ifndef NSSBASET_H
643 +#include "nssbaset.h"
644 +#endif /* NSSBASET_H */
646 +#ifndef NSSCKT_H
647 +#include "nssckt.h"
648 +#endif /* NSSCKT_H */
650 +#ifndef NSSCKBI_H
651 +#include "../builtins/nssckbi.h"
652 +#endif /* NSSCKBI_H */
654 +NSS_IMPLEMENT_DATA const CK_VERSION
655 +pem_CryptokiVersion = { 2, 1 };
657 +NSS_IMPLEMENT_DATA const NSSUTF8 *
658 +pem_ManufacturerID = (NSSUTF8 *) "Red Hat, Inc.";
660 +NSS_IMPLEMENT_DATA const NSSUTF8 *
661 +pem_LibraryDescription = (NSSUTF8 *) "PEM Reader Cryptoki Module";
663 +NSS_IMPLEMENT_DATA const CK_VERSION
664 +pem_LibraryVersion = { 1, 0 };
666 +NSS_IMPLEMENT_DATA const CK_VERSION
667 +pem_HardwareVersion = { 1, 0 };
669 +NSS_IMPLEMENT_DATA const CK_VERSION
670 +pem_FirmwareVersion = { 1, 0 };
672 +NSS_IMPLEMENT_DATA const NSSUTF8 *
673 +pem_TokenModel = (NSSUTF8 *) "1";
675 +NSS_IMPLEMENT_DATA const NSSUTF8 *
676 +pem_TokenSerialNumber = (NSSUTF8 *) "1";
677 diff --git a/a/nss/lib/ckfw/pem/manifest.mn b/b/nss/lib/ckfw/pem/manifest.mn
678 new file mode 100644
679 index 0000000..8de27d1
680 --- /dev/null
681 +++ b/b/nss/lib/ckfw/pem/manifest.mn
682 @@ -0,0 +1,68 @@
684 +# ***** BEGIN LICENSE BLOCK *****
685 +# Version: MPL 1.1/GPL 2.0/LGPL 2.1
687 +# The contents of this file are subject to the Mozilla Public License Version
688 +# 1.1 (the "License"); you may not use this file except in compliance with
689 +# the License. You may obtain a copy of the License at
690 +# http://www.mozilla.org/MPL/
692 +# Software distributed under the License is distributed on an "AS IS" basis,
693 +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
694 +# for the specific language governing rights and limitations under the
695 +# License.
697 +# The Original Code is the Netscape security libraries.
699 +# The Initial Developer of the Original Code is
700 +# Netscape Communications Corporation.
701 +# Portions created by the Initial Developer are Copyright (C) 1994-2000
702 +# the Initial Developer. All Rights Reserved.
704 +# Contributor(s):
706 +# Alternatively, the contents of this file may be used under the terms of
707 +# either the GNU General Public License Version 2 or later (the "GPL"), or
708 +# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
709 +# in which case the provisions of the GPL or the LGPL are applicable instead
710 +# of those above. If you wish to allow use of your version of this file only
711 +# under the terms of either the GPL or the LGPL, and not to allow others to
712 +# use your version of this file under the terms of the MPL, indicate your
713 +# decision by deleting the provisions above and replace them with the notice
714 +# and other provisions required by the GPL or the LGPL. If you do not delete
715 +# the provisions above, a recipient may use your version of this file under
716 +# the terms of any one of the MPL, the GPL or the LGPL.
718 +# ***** END LICENSE BLOCK *****
719 +MANIFEST_CVS_ID = "@(#) $RCSfile: manifest.mn,v $ $Revision: 1.1 $ $Date: 2005/11/04 02:05:04 $"
721 +CORE_DEPTH = ../../..
723 +MODULE = nss
724 +MAPFILE = $(OBJDIR)/nsspem.def
726 +EXPORTS = \
727 + nsspem.h \
728 + $(NULL)
730 +CSRCS = \
731 + anchor.c \
732 + constants.c \
733 + pargs.c \
734 + pfind.c \
735 + pinst.c \
736 + pobject.c \
737 + prsa.c \
738 + psession.c \
739 + pslot.c \
740 + ptoken.c \
741 + ckpemver.c \
742 + rsawrapr.c \
743 + util.c \
744 + $(NULL)
746 +REQUIRES = nspr
748 +LIBRARY_NAME = nsspem
750 +#EXTRA_SHARED_LIBS = -L$(DIST)/lib -lnssckfw -lnssb -lplc4 -lplds4
751 diff --git a/a/nss/lib/ckfw/pem/nsspem.def b/b/nss/lib/ckfw/pem/nsspem.def
752 new file mode 100644
753 index 0000000..4978252
754 --- /dev/null
755 +++ b/b/nss/lib/ckfw/pem/nsspem.def
756 @@ -0,0 +1,58 @@
757 +;+#
758 +;+# ***** BEGIN LICENSE BLOCK *****
759 +;+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
760 +;+#
761 +;+# The contents of this file are subject to the Mozilla Public License Version
762 +;+# 1.1 (the "License"); you may not use this file except in compliance with
763 +;+# the License. You may obtain a copy of the License at
764 +;+# http://www.mozilla.org/MPL/
765 +;+#
766 +;+# Software distributed under the License is distributed on an "AS IS" basis,
767 +;+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
768 +;+# for the specific language governing rights and limitations under the
769 +;+# License.
770 +;+#
771 +;+# The Original Code is the Netscape security libraries.
772 +;+#
773 +;+# The Initial Developer of the Original Code is
774 +;+# Netscape Communications Corporation.
775 +;+# Portions created by the Initial Developer are Copyright (C) 2003
776 +;+# the Initial Developer. All Rights Reserved.
777 +;+#
778 +;+# Contributor(s):
779 +;+#
780 +;+# Alternatively, the contents of this file may be used under the terms of
781 +;+# either the GNU General Public License Version 2 or later (the "GPL"), or
782 +;+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
783 +;+# in which case the provisions of the GPL or the LGPL are applicable instead
784 +;+# of those above. If you wish to allow use of your version of this file only
785 +;+# under the terms of either the GPL or the LGPL, and not to allow others to
786 +;+# use your version of this file under the terms of the MPL, indicate your
787 +;+# decision by deleting the provisions above and replace them with the notice
788 +;+# and other provisions required by the GPL or the LGPL. If you do not delete
789 +;+# the provisions above, a recipient may use your version of this file under
790 +;+# the terms of any one of the MPL, the GPL or the LGPL.
791 +;+#
792 +;+# ***** END LICENSE BLOCK *****
793 +;+#
794 +;+# OK, this file is meant to support SUN, LINUX, AIX and WINDOWS
795 +;+# 1. For all unix platforms, the string ";-" means "remove this line"
796 +;+# 2. For all unix platforms, the string " DATA " will be removed from any
797 +;+# line on which it occurs.
798 +;+# 3. Lines containing ";+" will have ";+" removed on SUN and LINUX.
799 +;+# On AIX, lines containing ";+" will be removed.
800 +;+# 4. For all unix platforms, the string ";;" will thave the ";;" removed.
801 +;+# 5. For all unix platforms, after the above processing has taken place,
802 +;+# all characters after the first ";" on the line will be removed.
803 +;+# And for AIX, the first ";" will also be removed.
804 +;+# This file is passed directly to windows. Since ';' is a comment, all UNIX
805 +;+# directives are hidden behind ";", ";+", and ";-"
807 +;+NSS_3.1 { # NSS 3.1 release
808 +;+ global:
809 +LIBRARY nsspem ;-
810 +EXPORTS ;-
811 +C_GetFunctionList;
812 +;+ local:
813 +;+*;
814 +;+};
815 diff --git a/a/nss/lib/ckfw/pem/nsspem.h b/b/nss/lib/ckfw/pem/nsspem.h
816 new file mode 100644
817 index 0000000..1547bf4
818 --- /dev/null
819 +++ b/b/nss/lib/ckfw/pem/nsspem.h
820 @@ -0,0 +1,75 @@
821 +/* ***** BEGIN LICENSE BLOCK *****
822 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
824 + * The contents of this file are subject to the Mozilla Public License Version
825 + * 1.1 (the "License"); you may not use this file except in compliance with
826 + * the License. You may obtain a copy of the License at
827 + * http://www.mozilla.org/MPL/
829 + * Software distributed under the License is distributed on an "AS IS" basis,
830 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
831 + * for the specific language governing rights and limitations under the
832 + * License.
834 + * The Original Code is the Netscape security libraries.
836 + * The Initial Developer of the Original Code is
837 + * Netscape Communications Corporation.
838 + * Portions created by the Initial Developer are Copyright (C) 1994-2000
839 + * the Initial Developer. All Rights Reserved.
840 + * Portions created by Red Hat, Inc, are Copyright (C) 2005
842 + * Contributor(s):
843 + * Rob Crittenden (rcritten@redhat.com)
845 + * Alternatively, the contents of this file may be used under the terms of
846 + * either the GNU General Public License Version 2 or later (the "GPL"), or
847 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
848 + * in which case the provisions of the GPL or the LGPL are applicable instead
849 + * of those above. If you wish to allow use of your version of this file only
850 + * under the terms of either the GPL or the LGPL, and not to allow others to
851 + * use your version of this file under the terms of the MPL, indicate your
852 + * decision by deleting the provisions above and replace them with the notice
853 + * and other provisions required by the GPL or the LGPL. If you do not delete
854 + * the provisions above, a recipient may use your version of this file under
855 + * the terms of any one of the MPL, the GPL or the LGPL.
857 + * ***** END LICENSE BLOCK ***** */
859 +#ifndef NSSPEM_H
860 +#define NSSPEM_H
863 + * NSS CKPEM Version numbers.
865 + * These are the version numbers for the capi module packaged with
866 + * this release on NSS. To determine the version numbers of the builtin
867 + * module you are using, use the appropriate PKCS #11 calls.
869 + * These version numbers detail changes to the PKCS #11 interface. They map
870 + * to the PKCS #11 spec versions.
871 + */
872 +#define NSS_CKPEM_CRYPTOKI_VERSION_MAJOR 2
873 +#define NSS_CKPEM_CRYPTOKI_VERSION_MINOR 20
875 +/* These version numbers detail the changes
876 + * to the list of trusted certificates.
878 + * NSS_CKPEM_LIBRARY_VERSION_MINOR is a CK_BYTE. It's not clear
879 + * whether we may use its full range (0-255) or only 0-99 because
880 + * of the comment in the CK_VERSION type definition.
881 + */
882 +#define NSS_CKPEM_LIBRARY_VERSION_MAJOR 1
883 +#define NSS_CKPEM_LIBRARY_VERSION_MINOR 1
884 +#define NSS_CKPEM_LIBRARY_VERSION "1.1"
886 +/* These version numbers detail the semantic changes to the ckfw engine. */
887 +#define NSS_CKPEM_HARDWARE_VERSION_MAJOR 1
888 +#define NSS_CKPEM_HARDWARE_VERSION_MINOR 0
890 +/* These version numbers detail the semantic changes to ckbi itself
891 + * (new PKCS #11 objects), etc. */
892 +#define NSS_CKPEM_FIRMWARE_VERSION_MAJOR 1
893 +#define NSS_CKPEM_FIRMWARE_VERSION_MINOR 0
895 +#endif /* NSSCKBI_H */
896 diff --git a/a/nss/lib/ckfw/pem/nsspem.rc b/b/nss/lib/ckfw/pem/nsspem.rc
897 new file mode 100644
898 index 0000000..eb208d6
899 --- /dev/null
900 +++ b/b/nss/lib/ckfw/pem/nsspem.rc
901 @@ -0,0 +1,64 @@
902 +/* This Source Code Form is subject to the terms of the Mozilla Public
903 + * License, v. 2.0. If a copy of the MPL was not distributed with this
904 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
906 +#include "nsspem.h"
907 +#include <winver.h>
909 +#define MY_LIBNAME "nsspem"
910 +#define MY_FILEDESCRIPTION "NSS PEM support"
912 +#ifdef _DEBUG
913 +#define MY_DEBUG_STR " (debug)"
914 +#define MY_FILEFLAGS_1 VS_FF_DEBUG
915 +#else
916 +#define MY_DEBUG_STR ""
917 +#define MY_FILEFLAGS_1 0x0L
918 +#endif
919 +#if NSS_BETA
920 +#define MY_FILEFLAGS_2 MY_FILEFLAGS_1|VS_FF_PRERELEASE
921 +#else
922 +#define MY_FILEFLAGS_2 MY_FILEFLAGS_1
923 +#endif
925 +#ifdef WINNT
926 +#define MY_FILEOS VOS_NT_WINDOWS32
927 +#else
928 +#define MY_FILEOS VOS__WINDOWS32
929 +#endif
931 +#define MY_INTERNAL_NAME MY_LIBNAME
933 +/////////////////////////////////////////////////////////////////////////////
935 +// Version-information resource
938 +VS_VERSION_INFO VERSIONINFO
939 + FILEVERSION NSS_CKPEM_LIBRARY_VERSION_MAJOR,NSS_CKPEM_LIBRARY_VERSION_MINOR,0,0
940 + PRODUCTVERSION NSS_CKPEM_LIBRARY_VERSION_MAJOR,NSS_CKPEM_LIBRARY_VERSION_MINOR,0,0
941 + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
942 + FILEFLAGS MY_FILEFLAGS_2
943 + FILEOS MY_FILEOS
944 + FILETYPE VFT_DLL
945 + FILESUBTYPE 0x0L // not used
947 +BEGIN
948 + BLOCK "StringFileInfo"
949 + BEGIN
950 + BLOCK "040904B0" // Lang=US English, CharSet=Unicode
951 + BEGIN
952 + VALUE "CompanyName", "Mozilla Foundation\0"
953 + VALUE "FileDescription", MY_FILEDESCRIPTION MY_DEBUG_STR "\0"
954 + VALUE "FileVersion", NSS_CKPEM_LIBRARY_VERSION "\0"
955 + VALUE "InternalName", MY_INTERNAL_NAME "\0"
956 + VALUE "OriginalFilename", MY_INTERNAL_NAME ".dll\0"
957 + VALUE "ProductName", "Network Security Services\0"
958 + VALUE "ProductVersion", NSS_CKPEM_LIBRARY_VERSION "\0"
959 + END
960 + END
961 + BLOCK "VarFileInfo"
962 + BEGIN
963 + VALUE "Translation", 0x409, 1200
964 + END
965 +END
966 diff --git a/a/nss/lib/ckfw/pem/pargs.c b/b/nss/lib/ckfw/pem/pargs.c
967 new file mode 100644
968 index 0000000..21291a8
969 --- /dev/null
970 +++ b/b/nss/lib/ckfw/pem/pargs.c
971 @@ -0,0 +1,164 @@
972 +/* ***** BEGIN LICENSE BLOCK *****
973 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
975 + * The contents of this file are subject to the Mozilla Public License Version
976 + * 1.1 (the "License"); you may not use this file except in compliance with
977 + * the License. You may obtain a copy of the License at
978 + * http://www.mozilla.org/MPL/
980 + * Software distributed under the License is distributed on an "AS IS" basis,
981 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
982 + * for the specific language governing rights and limitations under the
983 + * License.
985 + * The Original Code is the Netscape security libraries.
987 + * The Initial Developer of the Original Code is
988 + * Netscape Communications Corporation.
989 + * Portions created by the Initial Developer are Copyright (C) 1994-2000
990 + * the Initial Developer. All Rights Reserved.
992 + * Contributor(s):
993 + * Rob Crittenden (rcritten@redhat.com)
995 + * Alternatively, the contents of this file may be used under the terms of
996 + * either the GNU General Public License Version 2 or later (the "GPL"), or
997 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
998 + * in which case the provisions of the GPL or the LGPL are applicable instead
999 + * of those above. If you wish to allow use of your version of this file only
1000 + * under the terms of either the GPL or the LGPL, and not to allow others to
1001 + * use your version of this file under the terms of the MPL, indicate your
1002 + * decision by deleting the provisions above and replace them with the notice
1003 + * and other provisions required by the GPL or the LGPL. If you do not delete
1004 + * the provisions above, a recipient may use your version of this file under
1005 + * the terms of any one of the MPL, the GPL or the LGPL.
1007 + * ***** END LICENSE BLOCK ***** */
1009 +#include <string.h>
1010 +#include <nspr.h>
1012 +void *pem_Malloc(const PRInt32 sz)
1014 + return PR_Malloc(sz);
1017 +char *pem_StrNdup(const char *instr, PRInt32 inlen)
1019 + size_t len = inlen;
1020 + char *buffer;
1021 + if (!instr) {
1022 + return NULL;
1025 + if (!len) {
1026 + return NULL;
1028 + buffer = (char *) pem_Malloc(len + 1);
1029 + if (!buffer) {
1030 + return NULL;
1032 + memcpy(buffer, instr, len);
1033 + buffer[len] = 0; /* NULL termination */
1034 + return buffer;
1037 +char *pem_Strdup(const char *instr)
1039 + size_t len;
1040 + if (!instr) {
1041 + return NULL;
1044 + len = strlen(instr);
1045 + return pem_StrNdup(instr, len);
1048 +void pem_Free(char *instr)
1050 + if (!instr) {
1051 + PR_ASSERT(0);
1053 + PR_Free(instr);
1056 +void
1057 +addString(char ***returnedstrings, char *newstring, PRInt32 stringcount)
1059 + char **stringarray = NULL;
1060 + if (!returnedstrings || !newstring) {
1061 + return;
1063 + if (!stringcount) {
1064 + /* first string to be added, allocate buffer */
1065 + *returnedstrings =
1066 + (char **) PR_Malloc(sizeof(char *) * (stringcount + 1));
1067 + stringarray = *returnedstrings;
1068 + } else {
1069 + stringarray = (char **) PR_Realloc(*returnedstrings,
1070 + sizeof(char *) * (stringcount + 1));
1071 + if (stringarray) {
1072 + *returnedstrings = stringarray;
1075 + if (stringarray) {
1076 + stringarray[stringcount] = newstring;
1080 +PRBool
1081 +pem_ParseString(const char *inputstring, const char delimiter,
1082 + PRInt32 * numStrings, char ***returnedstrings)
1084 + char nextchar;
1085 + char *instring = (char *) inputstring;
1086 + if (!inputstring || !delimiter || !numStrings || !returnedstrings) {
1087 + /* we need a string and a non-zero delimiter, as well as
1088 + * a valid place to return the strings and count
1089 + */
1090 + return PR_FALSE;
1092 + *numStrings = 0;
1093 + *returnedstrings = NULL;
1095 + while ((nextchar = *instring)) {
1096 + unsigned long len = 0;
1097 + char *next = (char *) strchr(instring, delimiter);
1098 + if (next) {
1099 + /* current string string */
1100 + len = next - instring;
1101 + } else {
1102 + /* last string length */
1103 + len = strlen(instring);
1106 + if (len > 0) {
1107 + char *newstring = pem_StrNdup(instring, len);
1109 + addString(returnedstrings, newstring, (*numStrings)++);
1111 + instring += len;
1114 + if (delimiter == *instring) {
1115 + instring++; /* skip past next delimiter */
1118 + return PR_TRUE;
1121 +PRBool pem_FreeParsedStrings(PRInt32 numStrings, char **instrings)
1123 + PRInt32 counter;
1124 + if (!numStrings || !instrings) {
1125 + return PR_FALSE;
1127 + for (counter = 0; counter < numStrings; counter++) {
1128 + char *astring = instrings[counter];
1129 + if (astring) {
1130 + pem_Free(astring);
1133 + PR_Free((void *) instrings);
1134 + return PR_TRUE;
1136 diff --git a/a/nss/lib/ckfw/pem/pfind.c b/b/nss/lib/ckfw/pem/pfind.c
1137 new file mode 100644
1138 index 0000000..30b1174
1139 --- /dev/null
1140 +++ b/b/nss/lib/ckfw/pem/pfind.c
1141 @@ -0,0 +1,435 @@
1142 +/* ***** BEGIN LICENSE BLOCK *****
1143 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
1145 + * The contents of this file are subject to the Mozilla Public License Version
1146 + * 1.1 (the "License"); you may not use this file except in compliance with
1147 + * the License. You may obtain a copy of the License at
1148 + * http://www.mozilla.org/MPL/
1150 + * Software distributed under the License is distributed on an "AS IS" basis,
1151 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
1152 + * for the specific language governing rights and limitations under the
1153 + * License.
1155 + * The Original Code is the Netscape security libraries.
1157 + * The Initial Developer of the Original Code is
1158 + * Netscape Communications Corporation.
1159 + * Portions created by the Initial Developer are Copyright (C) 1994-2000
1160 + * the Initial Developer. All Rights Reserved.
1162 + * Contributor(s):
1163 + * Rob Crittenden (rcritten@redhat.com)
1165 + * Alternatively, the contents of this file may be used under the terms of
1166 + * either the GNU General Public License Version 2 or later (the "GPL"), or
1167 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
1168 + * in which case the provisions of the GPL or the LGPL are applicable instead
1169 + * of those above. If you wish to allow use of your version of this file only
1170 + * under the terms of either the GPL or the LGPL, and not to allow others to
1171 + * use your version of this file under the terms of the MPL, indicate your
1172 + * decision by deleting the provisions above and replace them with the notice
1173 + * and other provisions required by the GPL or the LGPL. If you do not delete
1174 + * the provisions above, a recipient may use your version of this file under
1175 + * the terms of any one of the MPL, the GPL or the LGPL.
1177 + * ***** END LICENSE BLOCK ***** */
1179 +#include "ckpem.h"
1182 + * pfind.c
1184 + * This file implements the NSSCKMDFindObjects object for the
1185 + * "PEM objects" cryptoki module.
1186 + */
1188 +NSS_EXTERN_DATA pemInternalObject **gobj;
1189 +NSS_EXTERN_DATA int pem_nobjs;
1191 +struct pemFOStr {
1192 + NSSArena *arena;
1193 + CK_ULONG n;
1194 + CK_ULONG i;
1195 + pemInternalObject **objs;
1198 +#define PEM_ITEM_CHUNK 512
1200 +#define PUT_Object(obj,err) \
1201 + { \
1202 + if (count >= size) { \
1203 + *listp = *listp ? \
1204 + nss_ZREALLOCARRAY(*listp, pemInternalObject *, \
1205 + (size+PEM_ITEM_CHUNK) ) : \
1206 + nss_ZNEWARRAY(NULL, pemInternalObject *, \
1207 + (size+PEM_ITEM_CHUNK) ) ; \
1208 + if ((pemInternalObject **)NULL == *listp) { \
1209 + err = CKR_HOST_MEMORY; \
1210 + goto loser; \
1211 + } \
1212 + size += PEM_ITEM_CHUNK; \
1213 + } \
1214 + (*listp)[ count ] = (obj); \
1215 + count++; \
1218 +static void
1219 +pem_mdFindObjects_Final
1221 + NSSCKMDFindObjects * mdFindObjects,
1222 + NSSCKFWFindObjects * fwFindObjects,
1223 + NSSCKMDSession * mdSession,
1224 + NSSCKFWSession * fwSession,
1225 + NSSCKMDToken * mdToken,
1226 + NSSCKFWToken * fwToken,
1227 + NSSCKMDInstance * mdInstance,
1228 + NSSCKFWInstance * fwInstance
1231 + struct pemFOStr *fo = (struct pemFOStr *) mdFindObjects->etc;
1232 + NSSArena *arena = fo->arena;
1234 + nss_ZFreeIf(fo->objs);
1235 + nss_ZFreeIf(fo);
1236 + nss_ZFreeIf(mdFindObjects);
1237 + if ((NSSArena *) NULL != arena) {
1238 + NSSArena_Destroy(arena);
1241 + return;
1244 +static NSSCKMDObject *
1245 +pem_mdFindObjects_Next
1247 + NSSCKMDFindObjects * mdFindObjects,
1248 + NSSCKFWFindObjects * fwFindObjects,
1249 + NSSCKMDSession * mdSession,
1250 + NSSCKFWSession * fwSession,
1251 + NSSCKMDToken * mdToken,
1252 + NSSCKFWToken * fwToken,
1253 + NSSCKMDInstance * mdInstance,
1254 + NSSCKFWInstance * fwInstance,
1255 + NSSArena * arena,
1256 + CK_RV * pError
1259 + struct pemFOStr *fo = (struct pemFOStr *) mdFindObjects->etc;
1260 + pemInternalObject *io;
1262 + plog("pem_FindObjects_Next: ");
1264 + if (fo->i == fo->n) {
1265 + plog("Done creating objects\n");
1266 + *pError = CKR_OK;
1267 + return (NSSCKMDObject *) NULL;
1270 + io = fo->objs[fo->i];
1271 + fo->i++;
1273 + plog("Creating object for type %d\n", io->type);
1275 + if (!io->extRef) {
1276 + /* increase reference count only once as ckfw will free the found
1277 + * object only once */
1278 + io->extRef = CK_TRUE;
1279 + io->refCount ++;
1282 + return pem_CreateMDObject(arena, io, pError);
1285 +#if 0
1286 +static int
1287 +pem_derUnwrapInt(unsigned char *src, int size, unsigned char **dest)
1289 + unsigned char *start = src;
1290 + int len = 0;
1292 + if (*src++ != 2) {
1293 + return 0;
1295 + len = *src++;
1296 + if (len & 0x80) {
1297 + int count = len & 0x7f;
1298 + len = 0;
1300 + if (count + 2 > size) {
1301 + return 0;
1303 + while (count-- > 0) {
1304 + len = (len << 8) | *src++;
1307 + if (len + (src - start) != size) {
1308 + return 0;
1310 + *dest = src;
1311 + return len;
1313 +#endif
1315 +static char * pem_attr_name(CK_ATTRIBUTE_TYPE type) {
1316 + switch(type) {
1317 + case CKA_CLASS:
1318 + return "CKA_CLASS";
1319 + case CKA_TOKEN:
1320 + return "CKA_TOKEN";
1321 + case CKA_PRIVATE:
1322 + return "CKA_PRIVATE";
1323 + case CKA_LABEL:
1324 + return "CKA_LABEL";
1325 + case CKA_APPLICATION:
1326 + return "CKA_APPLICATION";
1327 + case CKA_VALUE:
1328 + return "CKA_VALUE";
1329 + case CKA_OBJECT_ID:
1330 + return "CKA_OBJECT_ID";
1331 + case CKA_CERTIFICATE_TYPE:
1332 + return "CKA_CERTIFICATE_TYPE";
1333 + case CKA_ISSUER:
1334 + return "CKA_ISSUER";
1335 + case CKA_SERIAL_NUMBER:
1336 + return "CKA_SERIAL_NUMBER";
1337 + case CKA_ID:
1338 + return "CKA_ID";
1339 + default:
1340 + return "unknown";
1344 +static CK_BBOOL
1345 +pem_attrmatch(CK_ATTRIBUTE_PTR a, pemInternalObject * o) {
1346 + PRBool prb;
1347 + const NSSItem *b;
1349 + b = pem_FetchAttribute(o, a->type);
1350 + if (b == NULL) {
1351 + plog("pem_attrmatch %s %08x: CK_FALSE attr not found\n", pem_attr_name(a->type), a->type);
1352 + return CK_FALSE;
1355 + if (a->ulValueLen != b->size) {
1356 + plog("pem_attrmatch %s %08x: CK_FALSE size mismatch %d vs %d\n", pem_attr_name(a->type), a->type, a->ulValueLen, b->size);
1357 + return CK_FALSE;
1360 + prb = nsslibc_memequal(a->pValue, b->data, b->size, (PRStatus *) NULL);
1362 + if (PR_TRUE == prb) {
1363 + plog("pem_attrmatch %s %08x: CK_TRUE\n", pem_attr_name(a->type), a->type);
1364 + return CK_TRUE;
1365 + } else {
1366 + plog("pem_attrmatch %s %08x: CK_FALSE\n", pem_attr_name(a->type), a->type);
1367 + plog("type: %08x, label: %s a->pValue %08x, b->data %08x\n", o->objClass, o->u.cert.label.data, a->pValue, b->data);
1368 + return CK_FALSE;
1372 +static CK_BBOOL
1373 +pem_match
1375 + CK_ATTRIBUTE_PTR pTemplate,
1376 + CK_ULONG ulAttributeCount,
1377 + pemInternalObject * o
1380 + CK_ULONG i;
1382 + for (i = 0; i < ulAttributeCount; i++) {
1383 + if (CK_FALSE == pem_attrmatch(&pTemplate[i], o)) {
1384 + plog("pem_match: CK_FALSE\n");
1385 + return CK_FALSE;
1389 + /* Every attribute passed */
1390 + plog("pem_match: CK_TRUE\n");
1391 + return CK_TRUE;
1394 +CK_OBJECT_CLASS
1395 +pem_GetObjectClass(CK_ATTRIBUTE_PTR pTemplate,
1396 + CK_ULONG ulAttributeCount)
1398 + CK_ULONG i;
1400 + for (i = 0; i < ulAttributeCount; i++) {
1401 + if (pTemplate[i].type == CKA_CLASS) {
1402 + return *(CK_OBJECT_CLASS *) pTemplate[i].pValue;
1405 + /* need to return a value that says 'fetch them all' */
1406 + return CK_INVALID_HANDLE;
1409 +static PRUint32
1410 +collect_objects(CK_ATTRIBUTE_PTR pTemplate,
1411 + CK_ULONG ulAttributeCount,
1412 + pemInternalObject *** listp,
1413 + CK_RV * pError, CK_SLOT_ID slotID)
1415 + PRUint32 i;
1416 + PRUint32 count = 0;
1417 + PRUint32 size = 0;
1418 + pemObjectType type = pemRaw;
1419 + CK_OBJECT_CLASS objClass = pem_GetObjectClass(pTemplate, ulAttributeCount);
1421 + *pError = CKR_OK;
1423 + plog("collect_objects slot #%ld, ", slotID);
1424 + plog("%d attributes, ", ulAttributeCount);
1425 + plog("%d objects to look through.\n", pem_nobjs);
1426 + plog("Looking for: ");
1427 + /*
1428 + * now determine type of the object
1429 + */
1430 + switch (objClass) {
1431 + case CKO_CERTIFICATE:
1432 + plog("CKO_CERTIFICATE\n");
1433 + type = pemCert;
1434 + break;
1435 + case CKO_PUBLIC_KEY:
1436 + plog("CKO_PUBLIC_KEY\n");
1437 + type = pemBareKey;
1438 + break;
1439 + case CKO_PRIVATE_KEY:
1440 + type = pemBareKey;
1441 + plog("CKO_PRIVATE_KEY\n");
1442 + break;
1443 + case CKO_NETSCAPE_TRUST:
1444 + type = pemTrust;
1445 + plog("CKO_NETSCAPE_TRUST\n");
1446 + break;
1447 + case CKO_NETSCAPE_CRL:
1448 + plog("CKO_NETSCAPE_CRL\n");
1449 + goto done;
1450 + case CKO_NETSCAPE_SMIME:
1451 + plog("CKO_NETSCAPE_SMIME\n");
1452 + goto done;
1453 + case CKO_NETSCAPE_BUILTIN_ROOT_LIST:
1454 + plog("CKO_NETSCAPE_BUILTIN_ROOT_LIST\n");
1455 + goto done;
1456 + case CK_INVALID_HANDLE:
1457 + type = pemAll; /* look through all objectclasses - ignore the type field */
1458 + plog("CK_INVALID_HANDLE\n");
1459 + break;
1460 + default:
1461 + plog("no other object types %08x\n", objClass);
1462 + goto done; /* no other object types we understand in this module */
1465 + /* find objects */
1466 + for (i = 0; i < pem_nobjs; i++) {
1467 + int match = 1; /* matches type if type not specified */
1468 + if (NULL == gobj[i])
1469 + continue;
1471 + plog(" %d type = %d\n", i, gobj[i]->type);
1472 + if (type != pemAll) {
1473 + /* type specified - must match given type */
1474 + match = (type == gobj[i]->type);
1476 + if (match) {
1477 + match = (slotID == gobj[i]->slotID) &&
1478 + (CK_TRUE == pem_match(pTemplate, ulAttributeCount, gobj[i]));
1480 + if (match) {
1481 + pemInternalObject *o = gobj[i];
1482 + PUT_Object(o, *pError);
1486 + if (CKR_OK != *pError) {
1487 + goto loser;
1490 + done:
1491 + plog("collect_objects: Found %d\n", count);
1492 + return count;
1493 + loser:
1494 + nss_ZFreeIf(*listp);
1495 + return 0;
1499 +NSS_IMPLEMENT NSSCKMDFindObjects *
1500 +pem_FindObjectsInit
1502 + NSSCKFWSession * fwSession,
1503 + CK_ATTRIBUTE_PTR pTemplate,
1504 + CK_ULONG ulAttributeCount,
1505 + CK_RV * pError
1508 + NSSArena *arena = NULL;
1509 + NSSCKMDFindObjects *rv = (NSSCKMDFindObjects *) NULL;
1510 + struct pemFOStr *fo = (struct pemFOStr *) NULL;
1511 + pemInternalObject **temp = (pemInternalObject **) NULL;
1512 + NSSCKFWSlot *fwSlot;
1513 + CK_SLOT_ID slotID;
1515 + plog("pem_FindObjectsInit\n");
1516 + fwSlot = nssCKFWSession_GetFWSlot(fwSession);
1517 + if ((NSSCKFWSlot *) NULL == fwSlot) {
1518 + goto loser;
1520 + slotID = nssCKFWSlot_GetSlotID(fwSlot);
1522 + arena = NSSArena_Create();
1523 + if ((NSSArena *) NULL == arena) {
1524 + goto loser;
1527 + rv = nss_ZNEW(arena, NSSCKMDFindObjects);
1528 + if ((NSSCKMDFindObjects *) NULL == rv) {
1529 + *pError = CKR_HOST_MEMORY;
1530 + goto loser;
1533 + fo = nss_ZNEW(arena, struct pemFOStr);
1534 + if ((struct pemFOStr *) NULL == fo) {
1535 + *pError = CKR_HOST_MEMORY;
1536 + goto loser;
1539 + fo->arena = arena;
1540 + /* fo->n and fo->i are already zero */
1542 + rv->etc = (void *) fo;
1543 + rv->Final = pem_mdFindObjects_Final;
1544 + rv->Next = pem_mdFindObjects_Next;
1545 + rv->null = (void *) NULL;
1547 + fo->n =
1548 + collect_objects(pTemplate, ulAttributeCount, &temp, pError,
1549 + slotID);
1550 + if (*pError != CKR_OK) {
1551 + goto loser;
1554 + fo->objs = nss_ZNEWARRAY(arena, pemInternalObject *, fo->n);
1555 + if ((pemInternalObject **) NULL == fo->objs) {
1556 + *pError = CKR_HOST_MEMORY;
1557 + goto loser;
1560 + (void) nsslibc_memcpy(fo->objs, temp,
1561 + sizeof(pemInternalObject *) * fo->n);
1563 + nss_ZFreeIf(temp);
1564 + temp = (pemInternalObject **) NULL;
1566 + return rv;
1568 + loser:
1569 + nss_ZFreeIf(temp);
1570 + nss_ZFreeIf(fo);
1571 + nss_ZFreeIf(rv);
1572 + if ((NSSArena *) NULL != arena) {
1573 + NSSArena_Destroy(arena);
1575 + return (NSSCKMDFindObjects *) NULL;
1577 diff --git a/a/nss/lib/ckfw/pem/pinst.c b/b/nss/lib/ckfw/pem/pinst.c
1578 new file mode 100644
1579 index 0000000..9c98e89
1580 --- /dev/null
1581 +++ b/b/nss/lib/ckfw/pem/pinst.c
1582 @@ -0,0 +1,768 @@
1583 +/* ***** BEGIN LICENSE BLOCK *****
1584 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
1586 + * The contents of this file are subject to the Mozilla Public License Version
1587 + * 1.1 (the "License"); you may not use this file except in compliance with
1588 + * the License. You may obtain a copy of the License at
1589 + * http://www.mozilla.org/MPL/
1591 + * Software distributed under the License is distributed on an "AS IS" basis,
1592 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
1593 + * for the specific language governing rights and limitations under the
1594 + * License.
1596 + * The Original Code is the Netscape security libraries.
1598 + * The Initial Developer of the Original Code is
1599 + * Netscape Communications Corporation.
1600 + * Portions created by the Initial Developer are Copyright (C) 1994-2000
1601 + * the Initial Developer. All Rights Reserved.
1603 + * Contributor(s):
1604 + * Rob Crittenden (rcritten@redhat.com)
1606 + * Alternatively, the contents of this file may be used under the terms of
1607 + * either the GNU General Public License Version 2 or later (the "GPL"), or
1608 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
1609 + * in which case the provisions of the GPL or the LGPL are applicable instead
1610 + * of those above. If you wish to allow use of your version of this file only
1611 + * under the terms of either the GPL or the LGPL, and not to allow others to
1612 + * use your version of this file under the terms of the MPL, indicate your
1613 + * decision by deleting the provisions above and replace them with the notice
1614 + * and other provisions required by the GPL or the LGPL. If you do not delete
1615 + * the provisions above, a recipient may use your version of this file under
1616 + * the terms of any one of the MPL, the GPL or the LGPL.
1618 + * ***** END LICENSE BLOCK ***** */
1619 +#include <stdlib.h>
1620 +#include "ckpem.h"
1621 +#include "blapi.h"
1622 +#include "prprf.h"
1625 + * pinstance.c
1627 + * This file implements the NSSCKMDInstance object for the
1628 + * "PEM objects" cryptoki module.
1629 + */
1631 +static PRBool pemInitialized = PR_FALSE;
1633 +pemInternalObject **gobj;
1634 +int pem_nobjs = 0;
1635 +int token_needsLogin[NUM_SLOTS];
1637 +PRInt32 size = 0;
1638 +PRInt32 count = 0;
1640 +#define PEM_ITEM_CHUNK 512
1643 + * simple cert decoder to avoid the cost of asn1 engine
1644 + */
1645 +static unsigned char *
1646 +dataStart(unsigned char *buf, unsigned int length,
1647 + unsigned int *data_length,
1648 + PRBool includeTag, unsigned char *rettag)
1650 + unsigned char tag;
1651 + unsigned int used_length = 0;
1652 + if (!length)
1653 + return NULL;
1655 + tag = buf[used_length++];
1657 + if (rettag) {
1658 + *rettag = tag;
1661 + /* blow out when we come to the end */
1662 + if (tag == 0 || length <= used_length) {
1663 + return NULL;
1666 + *data_length = buf[used_length++];
1668 + if (*data_length & 0x80) {
1669 + int len_count = *data_length & 0x7f;
1671 + *data_length = 0;
1673 + while (len_count-- > 0) {
1674 + if (length <= used_length)
1675 + return NULL;
1677 + *data_length = (*data_length << 8) | buf[used_length++];
1681 + if (*data_length > (length - used_length)) {
1682 + *data_length = length - used_length;
1683 + return NULL;
1685 + if (includeTag)
1686 + *data_length += used_length;
1688 + return (buf + (includeTag ? 0 : used_length));
1691 +static int
1692 +GetCertFields(unsigned char *cert, int cert_length,
1693 + SECItem * issuer, SECItem * serial, SECItem * derSN,
1694 + SECItem * subject, SECItem * valid, SECItem * subjkey)
1696 + unsigned char *buf;
1697 + unsigned int buf_length;
1698 + unsigned char *dummy;
1699 + unsigned int dummylen;
1701 + /* get past the signature wrap */
1702 + buf = dataStart(cert, cert_length, &buf_length, PR_FALSE, NULL);
1703 + if (buf == NULL)
1704 + return SECFailure;
1705 + /* get into the raw cert data */
1706 + buf = dataStart(buf, buf_length, &buf_length, PR_FALSE, NULL);
1707 + if (buf == NULL)
1708 + return SECFailure;
1709 + /* skip past any optional version number */
1710 + if ((buf[0] & 0xa0) == 0xa0) {
1711 + dummy = dataStart(buf, buf_length, &dummylen, PR_FALSE, NULL);
1712 + if (dummy == NULL)
1713 + return SECFailure;
1714 + buf_length -= (dummy - buf) + dummylen;
1715 + buf = dummy + dummylen;
1717 + /* serial number */
1718 + if (derSN) {
1719 + derSN->data =
1720 + dataStart(buf, buf_length, &derSN->len, PR_TRUE, NULL);
1722 + serial->data =
1723 + dataStart(buf, buf_length, &serial->len, PR_FALSE, NULL);
1724 + if (serial->data == NULL)
1725 + return SECFailure;
1726 + buf_length -= (serial->data - buf) + serial->len;
1727 + buf = serial->data + serial->len;
1728 + /* skip the OID */
1729 + dummy = dataStart(buf, buf_length, &dummylen, PR_FALSE, NULL);
1730 + if (dummy == NULL)
1731 + return SECFailure;
1732 + buf_length -= (dummy - buf) + dummylen;
1733 + buf = dummy + dummylen;
1734 + /* issuer */
1735 + issuer->data = dataStart(buf, buf_length, &issuer->len, PR_TRUE, NULL);
1736 + if (issuer->data == NULL)
1737 + return SECFailure;
1738 + buf_length -= (issuer->data - buf) + issuer->len;
1739 + buf = issuer->data + issuer->len;
1741 + /* only wanted issuer/SN */
1742 + if (subject == NULL || valid == NULL || subjkey == NULL) {
1743 + return SECSuccess;
1745 + /* validity */
1746 + valid->data = dataStart(buf, buf_length, &valid->len, PR_FALSE, NULL);
1747 + if (valid->data == NULL)
1748 + return SECFailure;
1749 + buf_length -= (valid->data - buf) + valid->len;
1750 + buf = valid->data + valid->len;
1751 + /*subject */
1752 + subject->data =
1753 + dataStart(buf, buf_length, &subject->len, PR_TRUE, NULL);
1754 + if (subject->data == NULL)
1755 + return SECFailure;
1756 + buf_length -= (subject->data - buf) + subject->len;
1757 + buf = subject->data + subject->len;
1758 + /* subject key info */
1759 + subjkey->data =
1760 + dataStart(buf, buf_length, &subjkey->len, PR_TRUE, NULL);
1761 + if (subjkey->data == NULL)
1762 + return SECFailure;
1763 + buf_length -= (subjkey->data - buf) + subjkey->len;
1764 + buf = subjkey->data + subjkey->len;
1765 + return SECSuccess;
1768 +static CK_RV
1769 +assignObjectID(pemInternalObject *o, int objid)
1771 + char id[16];
1772 + int len;
1774 + sprintf(id, "%d", objid);
1775 + len = strlen(id) + 1; /* zero terminate */
1776 + o->id.size = len;
1777 + o->id.data = nss_ZAlloc(NULL, len);
1778 + if (o->id.data == NULL)
1779 + return CKR_HOST_MEMORY;
1781 + nsslibc_memcpy(o->id.data, id, len);
1782 + return CKR_OK;
1785 +static pemInternalObject *
1786 +CreateObject(CK_OBJECT_CLASS objClass,
1787 + pemObjectType type, SECItem * certDER,
1788 + SECItem * keyDER, char *filename,
1789 + int objid, CK_SLOT_ID slotID)
1791 + pemInternalObject *o;
1792 + SECItem subject;
1793 + SECItem issuer;
1794 + SECItem serial;
1795 + SECItem derSN;
1796 + SECItem valid;
1797 + SECItem subjkey;
1798 + char *nickname;
1800 + o = nss_ZNEW(NULL, pemInternalObject);
1801 + if ((pemInternalObject *) NULL == o) {
1802 + return NULL;
1805 + nickname = strrchr(filename, '/');
1806 + if (nickname)
1807 + nickname++;
1808 + else
1809 + nickname = filename;
1811 + switch (objClass) {
1812 + case CKO_CERTIFICATE:
1813 + plog("Creating cert nick %s id %d in slot %ld\n", nickname, objid, slotID);
1814 + memset(&o->u.cert, 0, sizeof(o->u.cert));
1815 + break;
1816 + case CKO_PRIVATE_KEY:
1817 + plog("Creating key id %d in slot %ld\n", objid, slotID);
1818 + memset(&o->u.key, 0, sizeof(o->u.key));
1819 + nickname = filename;
1820 + break;
1821 + case CKO_NETSCAPE_TRUST:
1822 + plog("Creating trust nick %s id %d in slot %ld\n", nickname, objid, slotID);
1823 + memset(&o->u.trust, 0, sizeof(o->u.trust));
1824 + break;
1827 + o->nickname = (char *) nss_ZAlloc(NULL, strlen(nickname) + 1);
1828 + if (o->nickname == NULL)
1829 + goto fail;
1830 + strcpy(o->nickname, nickname);
1832 + if (CKR_OK != assignObjectID(o, objid))
1833 + goto fail;
1835 + o->objClass = objClass;
1836 + o->type = type;
1837 + o->slotID = slotID;
1839 + o->derCert = nss_ZNEW(NULL, SECItem);
1840 + if (o->derCert == NULL)
1841 + goto fail;
1842 + o->derCert->data = (void *) nss_ZAlloc(NULL, certDER->len);
1843 + if (o->derCert->data == NULL)
1844 + goto fail;
1845 + o->derCert->len = certDER->len;
1846 + nsslibc_memcpy(o->derCert->data, certDER->data, certDER->len);
1848 + switch (objClass) {
1849 + case CKO_CERTIFICATE:
1850 + case CKO_NETSCAPE_TRUST:
1851 + if (SECSuccess != GetCertFields(o->derCert->data, o->derCert->len,
1852 + &issuer, &serial, &derSN, &subject,
1853 + &valid, &subjkey))
1854 + goto fail;
1856 + o->u.cert.subject.data = (void *) nss_ZAlloc(NULL, subject.len);
1857 + if (o->u.cert.subject.data == NULL)
1858 + goto fail;
1859 + o->u.cert.subject.size = subject.len;
1860 + nsslibc_memcpy(o->u.cert.subject.data, subject.data, subject.len);
1862 + o->u.cert.issuer.data = (void *) nss_ZAlloc(NULL, issuer.len);
1863 + if (o->u.cert.issuer.data == NULL) {
1864 + nss_ZFreeIf(o->u.cert.subject.data);
1865 + goto fail;
1867 + o->u.cert.issuer.size = issuer.len;
1868 + nsslibc_memcpy(o->u.cert.issuer.data, issuer.data, issuer.len);
1870 + o->u.cert.serial.data = (void *) nss_ZAlloc(NULL, serial.len);
1871 + if (o->u.cert.serial.data == NULL) {
1872 + nss_ZFreeIf(o->u.cert.issuer.data);
1873 + nss_ZFreeIf(o->u.cert.subject.data);
1874 + goto fail;
1876 + o->u.cert.serial.size = serial.len;
1877 + nsslibc_memcpy(o->u.cert.serial.data, serial.data, serial.len);
1878 + break;
1879 + case CKO_PRIVATE_KEY:
1880 + o->u.key.key.privateKey = nss_ZNEW(NULL, SECItem);
1881 + if (o->u.key.key.privateKey == NULL)
1882 + goto fail;
1883 + o->u.key.key.privateKey->data =
1884 + (void *) nss_ZAlloc(NULL, keyDER->len);
1885 + if (o->u.key.key.privateKey->data == NULL) {
1886 + nss_ZFreeIf(o->u.key.key.privateKey);
1887 + goto fail;
1890 + /* store deep copy of original key DER so we can compare it later on */
1891 + o->u.key.key.privateKeyOrig = SECITEM_DupItem(keyDER);
1892 + if (o->u.key.key.privateKeyOrig == NULL) {
1893 + nss_ZFreeIf(o->u.key.key.privateKey->data);
1894 + nss_ZFreeIf(o->u.key.key.privateKey);
1895 + goto fail;
1898 + o->u.key.key.privateKey->len = keyDER->len;
1899 + nsslibc_memcpy(o->u.key.key.privateKey->data, keyDER->data,
1900 + keyDER->len);
1904 + return o;
1906 +fail:
1907 + if (o) {
1908 + if (o->derCert) {
1909 + nss_ZFreeIf(o->derCert->data);
1910 + nss_ZFreeIf(o->derCert);
1912 + nss_ZFreeIf(o->id.data);
1913 + nss_ZFreeIf(o->nickname);
1914 + nss_ZFreeIf(o);
1916 + return NULL;
1919 +/* Compare the DER encoding of the internal object against those
1920 + * of the provided certDER or keyDER according to its objClass.
1921 + */
1922 +static PRBool
1923 +derEncodingsMatch(CK_OBJECT_CLASS objClass, pemInternalObject * obj,
1924 + SECItem * certDER, SECItem * keyDER)
1926 + SECComparison result;
1928 + switch (objClass) {
1929 + case CKO_CERTIFICATE:
1930 + case CKO_NETSCAPE_TRUST:
1931 + result = SECITEM_CompareItem(obj->derCert, certDER);
1932 + break;
1934 + case CKO_PRIVATE_KEY:
1935 + result = SECITEM_CompareItem(obj->u.key.key.privateKeyOrig, keyDER);
1936 + break;
1938 + default:
1939 + /* unhandled object class */
1940 + return PR_FALSE;
1943 + return SECEqual == result;
1946 +static CK_RV
1947 +LinkSharedKeyObject(int oldKeyIdx, int newKeyIdx)
1949 + int i;
1950 + for (i = 0; i < pem_nobjs; i++) {
1951 + CK_RV rv;
1952 + pemInternalObject *obj = gobj[i];
1953 + if (NULL == obj)
1954 + continue;
1956 + if (atoi(obj->id.data) != oldKeyIdx)
1957 + continue;
1959 + nss_ZFreeIf(obj->id.data);
1960 + rv = assignObjectID(obj, newKeyIdx);
1961 + if (CKR_OK != rv)
1962 + return rv;
1965 + return CKR_OK;
1968 +pemInternalObject *
1969 +AddObjectIfNeeded(CK_OBJECT_CLASS objClass,
1970 + pemObjectType type, SECItem * certDER,
1971 + SECItem * keyDER, char *filename,
1972 + int objid, CK_SLOT_ID slotID, PRBool *pAdded)
1974 + int i;
1975 + pemInternalObject *io;
1977 + /* FIXME: copy-pasted from CreateObject */
1978 + const char *nickname = strrchr(filename, '/');
1979 + if (nickname && CKO_PRIVATE_KEY != objClass)
1980 + nickname++;
1981 + else
1982 + nickname = filename;
1984 + if (pAdded)
1985 + *pAdded = PR_FALSE;
1987 + /* first look for the object in gobj, it might be already there */
1988 + for (i = 0; i < pem_nobjs; i++) {
1989 + if (NULL == gobj[i])
1990 + continue;
1992 + /* Comparing DER encodings is dependable and frees the PEM module
1993 + * from having to require clients to provide unique nicknames.
1994 + */
1995 + if ((gobj[i]->objClass == objClass)
1996 + && (gobj[i]->type == type)
1997 + && (gobj[i]->slotID == slotID)
1998 + && derEncodingsMatch(objClass, gobj[i], certDER, keyDER)) {
2000 + /* While adding a client certificate we (wrongly?) assumed that the
2001 + * key object will follow right after the cert object. However, if
2002 + * the key object is shared by multiple client certificates, such
2003 + * an assumption does not hold. We have to update the references.
2004 + */
2005 + LinkSharedKeyObject(pem_nobjs, i);
2007 + plog("AddObjectIfNeeded: re-using internal object #%i\n", i);
2008 + gobj[i]->refCount ++;
2009 + return gobj[i];
2013 + /* object not found, we need to create it */
2014 + io = CreateObject(objClass, type, certDER, keyDER,
2015 + filename, objid, slotID);
2016 + if (io == NULL)
2017 + return NULL;
2019 + /* initialize pointers to functions */
2020 + pem_CreateMDObject(NULL, io, NULL);
2022 + io->gobjIndex = count;
2024 + /* add object to global array */
2025 + if (count >= size) {
2026 + gobj = gobj ?
2027 + nss_ZREALLOCARRAY(gobj, pemInternalObject *,
2028 + (size+PEM_ITEM_CHUNK) ) :
2029 + nss_ZNEWARRAY(NULL, pemInternalObject *,
2030 + (size+PEM_ITEM_CHUNK) ) ;
2032 + if ((pemInternalObject **)NULL == gobj)
2033 + return NULL;
2034 + size += PEM_ITEM_CHUNK;
2036 + gobj[count] = io;
2037 + count++;
2038 + pem_nobjs++;
2040 + if (pAdded)
2041 + *pAdded = PR_TRUE;
2043 + io->refCount ++;
2044 + return io;
2047 +CK_RV
2048 +AddCertificate(char *certfile, char *keyfile, PRBool cacert,
2049 + CK_SLOT_ID slotID)
2051 + pemInternalObject *o;
2052 + CK_RV error = 0;
2053 + int objid, i;
2054 + int nobjs = 0;
2055 + SECItem **objs = NULL;
2056 + char *ivstring = NULL;
2057 + int cipher;
2059 + nobjs = ReadDERFromFile(&objs, certfile, PR_TRUE, &cipher, &ivstring, PR_TRUE /* certs only */);
2060 + if (nobjs <= 0) {
2061 + nss_ZFreeIf(objs);
2062 + return CKR_GENERAL_ERROR;
2065 + /* For now load as many certs as are in the file for CAs only */
2066 + if (cacert) {
2067 + for (i = 0; i < nobjs; i++) {
2068 + char nickname[1024];
2069 + objid = pem_nobjs + 1;
2071 + PR_snprintf(nickname, 1024, "%s - %d", certfile, i);
2073 + o = AddObjectIfNeeded(CKO_CERTIFICATE, pemCert, objs[i], NULL,
2074 + nickname, 0, slotID, NULL);
2075 + if (o == NULL) {
2076 + error = CKR_GENERAL_ERROR;
2077 + goto loser;
2080 + /* Add the CA trust object */
2081 + o = AddObjectIfNeeded(CKO_NETSCAPE_TRUST, pemTrust, objs[i], NULL,
2082 + nickname, 0, slotID, NULL);
2083 + if (o == NULL) {
2084 + error = CKR_GENERAL_ERROR;
2085 + goto loser;
2087 + } /* for */
2088 + } else {
2089 + objid = pem_nobjs + 1;
2090 + o = AddObjectIfNeeded(CKO_CERTIFICATE, pemCert, objs[0], NULL, certfile,
2091 + objid, slotID, NULL);
2092 + if (o == NULL) {
2093 + error = CKR_GENERAL_ERROR;
2094 + goto loser;
2097 + o = NULL;
2099 + if (keyfile) { /* add the private key */
2100 + SECItem **keyobjs = NULL;
2101 + int kobjs = 0;
2102 + kobjs =
2103 + ReadDERFromFile(&keyobjs, keyfile, PR_TRUE, &cipher,
2104 + &ivstring, PR_FALSE);
2105 + if (kobjs < 1) {
2106 + error = CKR_GENERAL_ERROR;
2107 + goto loser;
2109 + o = AddObjectIfNeeded(CKO_PRIVATE_KEY, pemBareKey, objs[0],
2110 + keyobjs[0], certfile, objid, slotID, NULL);
2111 + if (o == NULL) {
2112 + error = CKR_GENERAL_ERROR;
2113 + goto loser;
2118 + nss_ZFreeIf(objs);
2119 + return CKR_OK;
2121 + loser:
2122 + nss_ZFreeIf(objs);
2123 + nss_ZFreeIf(o);
2124 + return error;
2127 +CK_RV
2128 +pem_Initialize
2130 + NSSCKMDInstance * mdInstance,
2131 + NSSCKFWInstance * fwInstance,
2132 + NSSUTF8 * configurationData
2135 + CK_RV rv;
2136 + /* parse the initialization string */
2137 + char **certstrings = NULL;
2138 + char *modparms = NULL;
2139 + PRInt32 numcerts = 0;
2140 + PRBool status, error = PR_FALSE;
2141 + int i;
2142 + CK_C_INITIALIZE_ARGS_PTR modArgs = NULL;
2144 + if (!fwInstance) return CKR_ARGUMENTS_BAD;
2146 + modArgs = NSSCKFWInstance_GetInitArgs(fwInstance);
2147 + if (modArgs &&
2148 + ((modArgs->flags & CKF_OS_LOCKING_OK) || (modArgs->CreateMutex != 0))) {
2149 + return CKR_CANT_LOCK;
2152 + if (pemInitialized) {
2153 + return CKR_OK;
2156 + RNG_RNGInit();
2158 + open_log();
2160 + plog("pem_Initialize\n");
2162 + if (!modArgs || !modArgs->LibraryParameters) {
2163 + goto done;
2165 + modparms = (char *) modArgs->LibraryParameters;
2166 + plog("Initialized with %s\n", modparms);
2168 + /*
2169 + * The initialization string format is a space-delimited file of
2170 + * pairs of paths which are delimited by a semi-colon. The first
2171 + * entry of the pair is the path to the certificate file. The
2172 + * second is the path to the key file.
2174 + * CA certificates do not need the semi-colon.
2176 + * Example:
2177 + * /etc/certs/server.pem;/etc/certs/server.key /etc/certs/ca.pem
2179 + */
2180 + status =
2181 + pem_ParseString(modparms, ' ', &numcerts,
2182 + &certstrings);
2183 + if (status == PR_FALSE) {
2184 + return CKR_ARGUMENTS_BAD;
2187 + for (i = 0; i < numcerts && error != PR_TRUE; i++) {
2188 + char *cert = certstrings[i];
2189 + PRInt32 attrcount = 0;
2190 + char **certattrs = NULL;
2191 + status = pem_ParseString(cert, ';', &attrcount, &certattrs);
2192 + if (status == PR_FALSE) {
2193 + error = PR_TRUE;
2194 + break;
2197 + if (error == PR_FALSE) {
2198 + if (attrcount == 1) /* CA certificate */
2199 + rv = AddCertificate(certattrs[0], NULL, PR_TRUE, 0);
2200 + else
2201 + rv = AddCertificate(certattrs[0], certattrs[1], PR_FALSE,
2202 + 0);
2204 + if (rv != CKR_OK) {
2205 + error = PR_TRUE;
2206 + status = PR_FALSE;
2209 + pem_FreeParsedStrings(attrcount, certattrs);
2211 + pem_FreeParsedStrings(numcerts, certstrings);
2213 + if (status == PR_FALSE) {
2214 + return CKR_ARGUMENTS_BAD;
2217 + for (i = 0; i < NUM_SLOTS; i++)
2218 + token_needsLogin[i] = PR_FALSE;
2220 + done:
2222 + PR_AtomicSet(&pemInitialized, PR_TRUE);
2224 + return CKR_OK;
2227 +void
2228 +pem_Finalize
2230 + NSSCKMDInstance * mdInstance,
2231 + NSSCKFWInstance * fwInstance
2234 + plog("pem_Finalize\n");
2235 + if (!pemInitialized)
2236 + return;
2238 + nss_ZFreeIf(gobj);
2239 + gobj = NULL;
2241 + pem_nobjs = 0;
2242 + size = 0;
2243 + count = 0;
2245 + PR_AtomicSet(&pemInitialized, PR_FALSE);
2247 + return;
2251 + * NSSCKMDInstance methods
2252 + */
2254 +static CK_ULONG
2255 +pem_mdInstance_GetNSlots
2257 + NSSCKMDInstance * mdInstance,
2258 + NSSCKFWInstance * fwInstance,
2259 + CK_RV * pError
2262 + return (CK_ULONG) NUM_SLOTS;
2265 +static CK_VERSION
2266 +pem_mdInstance_GetCryptokiVersion
2268 + NSSCKMDInstance * mdInstance,
2269 + NSSCKFWInstance * fwInstance
2272 + return pem_CryptokiVersion;
2275 +static NSSUTF8 *
2276 +pem_mdInstance_GetManufacturerID
2278 + NSSCKMDInstance * mdInstance,
2279 + NSSCKFWInstance * fwInstance,
2280 + CK_RV * pError
2283 + return (NSSUTF8 *) pem_ManufacturerID;
2286 +static NSSUTF8 *
2287 +pem_mdInstance_GetLibraryDescription
2289 + NSSCKMDInstance * mdInstance,
2290 + NSSCKFWInstance * fwInstance,
2291 + CK_RV * pError
2294 + return (NSSUTF8 *) pem_LibraryDescription;
2297 +static CK_VERSION
2298 +pem_mdInstance_GetLibraryVersion
2300 + NSSCKMDInstance * mdInstance,
2301 + NSSCKFWInstance * fwInstance
2304 + return pem_LibraryVersion;
2307 +static CK_RV
2308 +pem_mdInstance_GetSlots
2310 + NSSCKMDInstance * mdInstance,
2311 + NSSCKFWInstance * fwInstance,
2312 + NSSCKMDSlot * slots[]
2315 + int i;
2316 + CK_RV pError;
2318 + for (i = 0; i < NUM_SLOTS; i++) {
2319 + slots[i] = (NSSCKMDSlot *) pem_NewSlot(fwInstance, &pError);
2320 + if (pError != CKR_OK)
2321 + return pError;
2323 + return CKR_OK;
2326 +CK_BBOOL
2327 +pem_mdInstance_ModuleHandlesSessionObjects
2329 + NSSCKMDInstance * mdInstance,
2330 + NSSCKFWInstance * fwInstance
2333 + return CK_TRUE;
2336 +NSS_IMPLEMENT_DATA const NSSCKMDInstance
2337 +pem_mdInstance = {
2338 + (void *) NULL, /* etc */
2339 + pem_Initialize, /* Initialize */
2340 + pem_Finalize, /* Finalize */
2341 + pem_mdInstance_GetNSlots,
2342 + pem_mdInstance_GetCryptokiVersion,
2343 + pem_mdInstance_GetManufacturerID,
2344 + pem_mdInstance_GetLibraryDescription,
2345 + pem_mdInstance_GetLibraryVersion,
2346 + pem_mdInstance_ModuleHandlesSessionObjects,
2347 + pem_mdInstance_GetSlots,
2348 + NULL, /* WaitForSlotEvent */
2349 + (void *) NULL /* null terminator */
2351 diff --git a/a/nss/lib/ckfw/pem/pobject.c b/b/nss/lib/ckfw/pem/pobject.c
2352 new file mode 100644
2353 index 0000000..a13e531
2354 --- /dev/null
2355 +++ b/b/nss/lib/ckfw/pem/pobject.c
2356 @@ -0,0 +1,1240 @@
2357 +/* ***** BEGIN LICENSE BLOCK *****
2358 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
2360 + * The contents of this file are subject to the Mozilla Public License Version
2361 + * 1.1 (the "License"); you may not use this file except in compliance with
2362 + * the License. You may obtain a copy of the License at
2363 + * http://www.mozilla.org/MPL/
2365 + * Software distributed under the License is distributed on an "AS IS" basis,
2366 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
2367 + * for the specific language governing rights and limitations under the
2368 + * License.
2370 + * The Original Code is the Netscape security libraries.
2372 + * The Initial Developer of the Original Code is
2373 + * Netscape Communications Corporation.
2374 + * Portions created by the Initial Developer are Copyright (C) 1994-2000
2375 + * the Initial Developer. All Rights Reserved.
2377 + * Contributor(s):
2378 + * Rob Crittenden (rcritten@redhat.com)
2380 + * Alternatively, the contents of this file may be used under the terms of
2381 + * either the GNU General Public License Version 2 or later (the "GPL"), or
2382 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
2383 + * in which case the provisions of the GPL or the LGPL are applicable instead
2384 + * of those above. If you wish to allow use of your version of this file only
2385 + * under the terms of either the GPL or the LGPL, and not to allow others to
2386 + * use your version of this file under the terms of the MPL, indicate your
2387 + * decision by deleting the provisions above and replace them with the notice
2388 + * and other provisions required by the GPL or the LGPL. If you do not delete
2389 + * the provisions above, a recipient may use your version of this file under
2390 + * the terms of any one of the MPL, the GPL or the LGPL.
2392 + * ***** END LICENSE BLOCK ***** */
2394 +#include "ckpem.h"
2395 +#include "secasn1.h"
2396 +#include "certt.h"
2397 +#include "prprf.h"
2398 +#include "pk11pub.h"
2401 + * pobject.c
2403 + * This file implements the NSSCKMDObject object for the
2404 + * "PEM objects" cryptoki module.
2405 + */
2407 +NSS_EXTERN_DATA pemInternalObject **gobj;
2408 +NSS_EXTERN_DATA int pem_nobjs;
2409 +NSS_EXTERN_DATA int token_needsLogin[NUM_SLOTS];
2411 +#define APPEND_LIST_ITEM(item) do { \
2412 + item->next = nss_ZNEW(NULL, pemObjectListItem); \
2413 + if (NULL == item->next) \
2414 + goto loser; \
2415 + item = item->next; \
2416 +} while (0)
2418 +const CK_ATTRIBUTE_TYPE certAttrs[] = {
2419 + CKA_CLASS,
2420 + CKA_TOKEN,
2421 + CKA_PRIVATE,
2422 + CKA_MODIFIABLE,
2423 + CKA_LABEL,
2424 + CKA_CERTIFICATE_TYPE,
2425 + CKA_SUBJECT,
2426 + CKA_ISSUER,
2427 + CKA_SERIAL_NUMBER,
2428 + CKA_VALUE
2430 +const PRUint32 certAttrsCount = NSS_PEM_ARRAY_SIZE(certAttrs);
2432 +/* private keys, for now only support RSA */
2433 +const CK_ATTRIBUTE_TYPE privKeyAttrs[] = {
2434 + CKA_CLASS,
2435 + CKA_TOKEN,
2436 + CKA_PRIVATE,
2437 + CKA_MODIFIABLE,
2438 + CKA_LABEL,
2439 + CKA_KEY_TYPE,
2440 + CKA_DERIVE,
2441 + CKA_LOCAL,
2442 + CKA_SUBJECT,
2443 + CKA_SENSITIVE,
2444 + CKA_DECRYPT,
2445 + CKA_SIGN,
2446 + CKA_SIGN_RECOVER,
2447 + CKA_UNWRAP,
2448 + CKA_EXTRACTABLE,
2449 + CKA_ALWAYS_SENSITIVE,
2450 + CKA_NEVER_EXTRACTABLE,
2451 + CKA_MODULUS,
2452 + CKA_PUBLIC_EXPONENT,
2454 +const PRUint32 privKeyAttrsCount = NSS_PEM_ARRAY_SIZE(privKeyAttrs);
2456 +/* public keys, for now only support RSA */
2457 +const CK_ATTRIBUTE_TYPE pubKeyAttrs[] = {
2458 + CKA_CLASS,
2459 + CKA_TOKEN,
2460 + CKA_PRIVATE,
2461 + CKA_MODIFIABLE,
2462 + CKA_LABEL,
2463 + CKA_KEY_TYPE,
2464 + CKA_DERIVE,
2465 + CKA_LOCAL,
2466 + CKA_SUBJECT,
2467 + CKA_ENCRYPT,
2468 + CKA_VERIFY,
2469 + CKA_VERIFY_RECOVER,
2470 + CKA_WRAP,
2471 + CKA_MODULUS,
2472 + CKA_PUBLIC_EXPONENT,
2474 +const PRUint32 pubKeyAttrsCount = NSS_PEM_ARRAY_SIZE(pubKeyAttrs);
2476 +/* Trust */
2477 +const CK_ATTRIBUTE_TYPE trustAttrs[] = {
2478 + CKA_CLASS,
2479 + CKA_TOKEN,
2480 + CKA_LABEL,
2481 + CKA_CERT_SHA1_HASH,
2482 + CKA_CERT_MD5_HASH,
2483 + CKA_ISSUER,
2484 + CKA_SUBJECT,
2485 + CKA_TRUST_SERVER_AUTH,
2486 + CKA_TRUST_CLIENT_AUTH,
2487 + CKA_TRUST_EMAIL_PROTECTION,
2488 + CKA_TRUST_CODE_SIGNING
2490 +const PRUint32 trustAttrsCount = NSS_PEM_ARRAY_SIZE(trustAttrs);
2492 +static const CK_BBOOL ck_true = CK_TRUE;
2493 +static const CK_BBOOL ck_false = CK_FALSE;
2494 +static const CK_CERTIFICATE_TYPE ckc_x509 = CKC_X_509;
2495 +static const CK_KEY_TYPE ckk_rsa = CKK_RSA;
2496 +static const CK_OBJECT_CLASS cko_certificate = CKO_CERTIFICATE;
2497 +static const CK_OBJECT_CLASS cko_private_key = CKO_PRIVATE_KEY;
2498 +static const CK_OBJECT_CLASS cko_public_key = CKO_PUBLIC_KEY;
2499 +static const CK_OBJECT_CLASS cko_trust = CKO_NETSCAPE_TRUST;
2500 +static const CK_TRUST ckt_netscape_trusted = CKT_NETSCAPE_TRUSTED_DELEGATOR;
2501 +static const NSSItem pem_trueItem = {
2502 + (void *) &ck_true, (PRUint32) sizeof(CK_BBOOL)
2504 +static const NSSItem pem_falseItem = {
2505 + (void *) &ck_false, (PRUint32) sizeof(CK_BBOOL)
2507 +static const NSSItem pem_x509Item = {
2508 + (void *) &ckc_x509, (PRUint32) sizeof(CK_ULONG)
2510 +static const NSSItem pem_rsaItem = {
2511 + (void *) &ckk_rsa, (PRUint32) sizeof(CK_KEY_TYPE)
2513 +static const NSSItem pem_certClassItem = {
2514 + (void *) &cko_certificate, (PRUint32) sizeof(CK_OBJECT_CLASS)
2516 +static const NSSItem pem_privKeyClassItem = {
2517 + (void *) &cko_private_key, (PRUint32) sizeof(CK_OBJECT_CLASS)
2519 +static const NSSItem pem_pubKeyClassItem = {
2520 + (void *) &cko_public_key, (PRUint32) sizeof(CK_OBJECT_CLASS)
2522 +static const NSSItem pem_trustClassItem = {
2523 + (void *) &cko_trust, (PRUint32) sizeof(CK_OBJECT_CLASS)
2525 +static const NSSItem pem_emptyItem = {
2526 + (void *) &ck_true, 0
2528 +static const NSSItem pem_trusted = {
2529 + (void *) &ckt_netscape_trusted, (PRUint32) sizeof(CK_TRUST)
2532 +/* SEC_SkipTemplate is already defined and exported by libnssutil */
2533 +#ifdef SEC_SKIP_TEMPLATE
2535 + * Template for skipping a subitem.
2537 + * Note that it only makes sense to use this for decoding (when you want
2538 + * to decode something where you are only interested in one or two of
2539 + * the fields); you cannot encode a SKIP!
2540 + */
2541 +const SEC_ASN1Template SEC_SkipTemplate[] = {
2542 + {SEC_ASN1_SKIP}
2544 +#endif
2547 + * Find the subjectName in a DER encoded certificate
2548 + */
2549 +const SEC_ASN1Template SEC_CertSubjectTemplate[] = {
2550 + {SEC_ASN1_SEQUENCE,
2551 + 0, NULL, sizeof(SECItem)} ,
2552 + {SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
2553 + SEC_ASN1_CONTEXT_SPECIFIC | 0,
2554 + 0, SEC_SkipTemplate} , /* version */
2555 + {SEC_ASN1_SKIP}, /* serial number */
2556 + {SEC_ASN1_SKIP}, /* signature algorithm */
2557 + {SEC_ASN1_SKIP}, /* issuer */
2558 + {SEC_ASN1_SKIP}, /* validity */
2559 + {SEC_ASN1_ANY, 0, NULL}, /* subject */
2560 + {SEC_ASN1_SKIP_REST},
2561 + {0}
2564 +void
2565 +pem_FetchLabel
2567 + pemInternalObject * io
2570 + pemCertObject *co = &io->u.cert;
2572 + co->label.data = io->nickname;
2573 + co->label.size = strlen(io->nickname);
2576 +const NSSItem
2577 +*pem_FetchCertAttribute
2579 + pemInternalObject * io,
2580 + CK_ATTRIBUTE_TYPE type
2583 + switch (type) {
2584 + case CKA_CLASS:
2585 + plog(" fetch cert CKA_CLASS\n");
2586 + return &pem_certClassItem;
2587 + case CKA_TOKEN:
2588 + plog(" fetch cert CKA_TOKEN\n");
2589 + return &pem_trueItem;
2590 + case CKA_PRIVATE:
2591 + return &pem_falseItem;
2592 + case CKA_CERTIFICATE_TYPE:
2593 + plog(" fetch cert CKA_CERTIFICATE_TYPE\n");
2594 + return &pem_x509Item;
2595 + case CKA_LABEL:
2596 + if (0 == io->u.cert.label.size) {
2597 + pem_FetchLabel(io);
2599 + plog(" fetch cert CKA_LABEL %s\n", io->u.cert.label.data);
2600 + return &io->u.cert.label;
2601 + case CKA_SUBJECT:
2602 + plog(" fetch cert CKA_SUBJECT size %d\n", io->u.cert.subject.size);
2603 + return &io->u.cert.subject;
2604 + case CKA_ISSUER:
2605 + plog(" fetch cert CKA_ISSUER size %d\n", io->u.cert.issuer.size);
2606 + return &io->u.cert.issuer;
2607 + case CKA_SERIAL_NUMBER:
2608 + plog(" fetch cert CKA_SERIAL_NUMBER size %d value %08x\n", io->u.cert.serial.size, io->u.cert.serial.data);
2609 + return &io->u.cert.serial;
2610 + case CKA_VALUE:
2611 + if (0 == io->u.cert.derCert.size) {
2612 + io->u.cert.derCert.data = io->derCert->data;
2613 + io->u.cert.derCert.size = io->derCert->len;
2615 + plog(" fetch cert CKA_VALUE\n");
2616 + return &io->u.cert.derCert;
2617 + case CKA_ID:
2618 + plog(" fetch cert CKA_ID val=%s size=%d\n", (char *) io->id.data,
2619 + io->id.size);
2620 + return &io->id;
2621 + case CKA_TRUSTED:
2622 + plog(" fetch cert CKA_TRUSTED: returning NULL\n");
2623 + return NULL;
2624 + default:
2625 + plog(" fetching cert unknown type %d\n", type);
2626 + break;
2628 + return NULL;
2631 +const NSSItem *
2632 +pem_FetchPrivKeyAttribute
2634 + pemInternalObject * io,
2635 + CK_ATTRIBUTE_TYPE type
2638 + PRBool isCertType = (pemCert == io->type);
2639 + pemKeyParams *kp = isCertType ? &io->u.cert.key : &io->u.key.key;
2641 + switch (type) {
2642 + case CKA_CLASS:
2643 + return &pem_privKeyClassItem;
2644 + case CKA_TOKEN:
2645 + case CKA_LOCAL:
2646 + case CKA_SIGN:
2647 + case CKA_DECRYPT:
2648 + case CKA_SIGN_RECOVER:
2649 + return &pem_trueItem;
2650 + case CKA_SENSITIVE:
2651 + case CKA_PRIVATE: /* should move in the future */
2652 + case CKA_MODIFIABLE:
2653 + case CKA_DERIVE:
2654 + case CKA_UNWRAP:
2655 + case CKA_EXTRACTABLE: /* will probably move in the future */
2656 + case CKA_ALWAYS_SENSITIVE:
2657 + case CKA_NEVER_EXTRACTABLE:
2658 + return &pem_falseItem;
2659 + case CKA_KEY_TYPE:
2660 + return &pem_rsaItem;
2661 + case CKA_LABEL:
2662 + if (!isCertType) {
2663 + return &pem_emptyItem;
2665 + if (0 == io->u.cert.label.size) {
2666 + pem_FetchLabel(io);
2668 + plog(" fetch key CKA_LABEL %s\n", io->u.cert.label.data);
2669 + return &io->u.cert.label;
2670 + case CKA_SUBJECT:
2671 + if (!isCertType) {
2672 + return &pem_emptyItem;
2674 + plog(" fetch key CKA_SUBJECT %s\n", io->u.cert.label.data);
2675 + return &io->u.cert.subject;
2676 + case CKA_MODULUS:
2677 + if (0 == kp->modulus.size) {
2678 + pem_PopulateModulusExponent(io);
2680 + plog(" fetch key CKA_MODULUS\n");
2681 + return &kp->modulus;
2682 + case CKA_PUBLIC_EXPONENT:
2683 + if (0 == kp->modulus.size) {
2684 + pem_PopulateModulusExponent(io);
2686 + plog(" fetch key CKA_PUBLIC_EXPONENT\n");
2687 + return &kp->exponent;
2688 + case CKA_PRIVATE_EXPONENT:
2689 + if (0 == kp->privateExponent.size) {
2690 + pem_PopulateModulusExponent(io);
2692 + plog(" fetch key CKA_PRIVATE_EXPONENT\n");
2693 + return &kp->privateExponent;
2694 + case CKA_PRIME_1:
2695 + if (0 == kp->prime1.size) {
2696 + pem_PopulateModulusExponent(io);
2698 + plog(" fetch key CKA_PRIME_1\n");
2699 + return &kp->prime1;
2700 + case CKA_PRIME_2:
2701 + if (0 == kp->prime2.size) {
2702 + pem_PopulateModulusExponent(io);
2704 + plog(" fetch key CKA_PRIME_2\n");
2705 + return &kp->prime2;
2706 + case CKA_EXPONENT_1:
2707 + if (0 == kp->exponent1.size) {
2708 + pem_PopulateModulusExponent(io);
2710 + plog(" fetch key CKA_EXPONENT_1\n");
2711 + return &kp->exponent1;
2712 + case CKA_EXPONENT_2:
2713 + if (0 == kp->exponent2.size) {
2714 + pem_PopulateModulusExponent(io);
2716 + plog(" fetch key CKA_EXPONENT_2\n");
2717 + return &kp->exponent2;
2718 + case CKA_COEFFICIENT:
2719 + if (0 == kp->coefficient.size) {
2720 + pem_PopulateModulusExponent(io);
2722 + plog(" fetch key CKA_COEFFICIENT_2\n");
2723 + return &kp->coefficient;
2724 + case CKA_ID:
2725 + plog(" fetch key CKA_ID val=%s size=%d\n", (char *) io->id.data,
2726 + io->id.size);
2727 + return &io->id;
2728 + default:
2729 + return NULL;
2733 +const NSSItem *
2734 +pem_FetchPubKeyAttribute
2736 + pemInternalObject * io,
2737 + CK_ATTRIBUTE_TYPE type
2740 + PRBool isCertType = (pemCert == io->type);
2741 + pemKeyParams *kp = isCertType ? &io->u.cert.key : &io->u.key.key;
2743 + switch (type) {
2744 + case CKA_CLASS:
2745 + return &pem_pubKeyClassItem;
2746 + case CKA_TOKEN:
2747 + case CKA_LOCAL:
2748 + case CKA_ENCRYPT:
2749 + case CKA_VERIFY:
2750 + case CKA_VERIFY_RECOVER:
2751 + return &pem_trueItem;
2752 + case CKA_PRIVATE:
2753 + case CKA_MODIFIABLE:
2754 + case CKA_DERIVE:
2755 + case CKA_WRAP:
2756 + return &pem_falseItem;
2757 + case CKA_KEY_TYPE:
2758 + return &pem_rsaItem;
2759 + case CKA_LABEL:
2760 + if (!isCertType) {
2761 + return &pem_emptyItem;
2763 + if (0 == io->u.cert.label.size) {
2764 + pem_FetchLabel(io);
2766 + return &io->u.cert.label;
2767 + case CKA_SUBJECT:
2768 + if (!isCertType) {
2769 + return &pem_emptyItem;
2771 + return &io->u.cert.subject;
2772 + case CKA_MODULUS:
2773 + if (0 == kp->modulus.size) {
2774 + pem_PopulateModulusExponent(io);
2776 + return &kp->modulus;
2777 + case CKA_PUBLIC_EXPONENT:
2778 + if (0 == kp->modulus.size) {
2779 + pem_PopulateModulusExponent(io);
2781 + return &kp->exponent;
2782 + case CKA_ID:
2783 + return &io->id;
2784 + default:
2785 + break;
2787 + return NULL;
2790 +const NSSItem *
2791 +pem_FetchTrustAttribute
2793 + pemInternalObject * io,
2794 + CK_ATTRIBUTE_TYPE type
2797 + static NSSItem hash;
2798 + SECStatus rv;
2800 + switch (type) {
2801 + case CKA_CLASS:
2802 + return &pem_trustClassItem;
2803 + case CKA_TOKEN:
2804 + return &pem_trueItem;
2805 + case CKA_PRIVATE:
2806 + return &pem_falseItem;
2807 + case CKA_CERTIFICATE_TYPE:
2808 + return &pem_x509Item;
2809 + case CKA_LABEL:
2810 + if (0 == io->u.cert.label.size) {
2811 + pem_FetchLabel(io);
2813 + plog(" fetch trust CKA_LABEL %s\n", io->u.cert.label.data);
2814 + return &io->u.cert.label;
2815 + case CKA_SUBJECT:
2816 + plog(" fetch trust CKA_SUBJECT\n");
2817 + return NULL;
2818 + case CKA_ISSUER:
2819 + plog(" fetch trust CKA_ISSUER\n");
2820 + return &io->u.cert.issuer;
2821 + case CKA_SERIAL_NUMBER:
2822 + plog(" fetch trust CKA_SERIAL_NUMBER size %d value %08x\n", io->u.cert.serial.size, io->u.cert.serial.data);
2823 + return &io->u.cert.serial;
2824 + case CKA_VALUE:
2825 + return &pem_trueItem;
2826 + case CKA_ID:
2827 + plog(" fetch trust CKA_ID val=%s size=%d\n", (char *) io->id.data,
2828 + io->id.size);
2829 + return &io->id;
2830 + case CKA_TRUSTED:
2831 + return &pem_trusted;
2832 + case CKA_TRUST_SERVER_AUTH:
2833 + return &pem_trusted;
2834 + case CKA_TRUST_CLIENT_AUTH:
2835 + return &pem_trusted;
2836 + case CKA_TRUST_CODE_SIGNING:
2837 + return &pem_trusted;
2838 + case CKA_TRUST_EMAIL_PROTECTION:
2839 + return &pem_trusted;
2840 + case CKA_TRUST_IPSEC_END_SYSTEM:
2841 + return &pem_trusted;
2842 + case CKA_TRUST_IPSEC_TUNNEL:
2843 + return &pem_trusted;
2844 + case CKA_TRUST_IPSEC_USER:
2845 + return &pem_trusted;
2846 + case CKA_TRUST_TIME_STAMPING:
2847 + return &pem_trusted;
2848 + case CKA_TRUST_STEP_UP_APPROVED:
2849 + return &pem_falseItem;
2850 + case CKA_CERT_SHA1_HASH:
2851 + hash.size = 0;
2852 + hash.data = NULL;
2853 + nsslibc_memset(io->u.cert.sha1_hash, 0, SHA1_LENGTH);
2854 + rv = SHA1_HashBuf(io->u.cert.sha1_hash, io->derCert->data,
2855 + io->derCert->len);
2856 + if (rv == SECSuccess) {
2857 + hash.data = io->u.cert.sha1_hash;
2858 + hash.size = sizeof(io->u.cert.sha1_hash);
2860 + return &hash;
2861 + case CKA_CERT_MD5_HASH:
2862 + hash.size = 0;
2863 + hash.data = NULL;
2864 + nsslibc_memset(io->u.cert.sha1_hash, 0, MD5_LENGTH);
2865 + rv = MD5_HashBuf(io->u.cert.sha1_hash, io->derCert->data,
2866 + io->derCert->len);
2867 + if (rv == SECSuccess) {
2868 + hash.data = io->u.cert.sha1_hash;
2869 + hash.size = sizeof(io->u.cert.sha1_hash);
2871 + return &hash;
2872 + default:
2873 + return &pem_trusted;
2874 + break;
2876 + return NULL;
2879 +const NSSItem *
2880 +pem_FetchAttribute
2882 + pemInternalObject * io,
2883 + CK_ATTRIBUTE_TYPE type
2886 + CK_ULONG i;
2888 + if (io->type == pemRaw) {
2889 + for (i = 0; i < io->u.raw.n; i++) {
2890 + if (type == io->u.raw.types[i]) {
2891 + return &io->u.raw.items[i];
2894 + return NULL;
2896 + /* deal with the common attributes */
2897 + switch (io->objClass) {
2898 + case CKO_CERTIFICATE:
2899 + return pem_FetchCertAttribute(io, type);
2900 + case CKO_PRIVATE_KEY:
2901 + return pem_FetchPrivKeyAttribute(io, type);
2902 + case CKO_NETSCAPE_TRUST:
2903 + return pem_FetchTrustAttribute(io, type);
2904 + case CKO_PUBLIC_KEY:
2905 + return pem_FetchPubKeyAttribute(io, type);
2907 + return NULL;
2911 + * Destroy internal object or list object if refCount becomes zero (after
2912 + * decrement). Safe to call with NULL argument.
2913 + */
2914 +void
2915 +pem_DestroyInternalObject
2917 + pemInternalObject * io
2920 + if (NULL == io)
2921 + /* nothing to destroy */
2922 + return;
2924 + if (NULL != io->list) {
2925 + /* destroy list object */
2926 + pemObjectListItem *item = io->list;
2927 + while (item) {
2928 + pemObjectListItem *next = item->next;
2930 + /* recursion of maximal depth 1 */
2931 + pem_DestroyInternalObject(item->io);
2933 + nss_ZFreeIf(item);
2934 + item = next;
2936 + nss_ZFreeIf(io);
2937 + return;
2940 + io->refCount --;
2941 + if (0 < io->refCount)
2942 + return;
2944 + /* destroy internal object */
2945 + switch (io->type) {
2946 + case pemRaw:
2947 + return;
2948 + case pemCert:
2949 + nss_ZFreeIf(io->u.cert.labelData);
2950 + nss_ZFreeIf(io->u.cert.key.privateKey);
2951 + nss_ZFreeIf(io->u.cert.key.pubKey);
2952 + /* go through */
2953 + case pemTrust:
2954 + nss_ZFreeIf(io->id.data);
2955 + nss_ZFreeIf(io->nickname);
2956 + nss_ZFreeIf(io->derCert->data);
2957 + nss_ZFreeIf(io->derCert);
2958 + if (io->u.cert.subject.size > 0) {
2959 + nss_ZFreeIf(io->u.cert.subject.data);
2961 + if (io->u.cert.issuer.size > 0) {
2962 + nss_ZFreeIf(io->u.cert.issuer.data);
2964 + if (io->u.cert.serial.size > 0) {
2965 + nss_ZFreeIf(io->u.cert.serial.data);
2967 + break;
2968 + case pemBareKey:
2969 + SECITEM_FreeItem(io->u.key.key.privateKeyOrig, PR_TRUE);
2970 + nss_ZFreeIf(io->u.key.key.coefficient.data);
2971 + nss_ZFreeIf(io->u.key.key.exponent2.data);
2972 + nss_ZFreeIf(io->u.key.key.exponent1.data);
2973 + nss_ZFreeIf(io->u.key.key.prime2.data);
2974 + nss_ZFreeIf(io->u.key.key.prime1.data);
2975 + nss_ZFreeIf(io->u.key.key.privateExponent.data);
2976 + nss_ZFreeIf(io->u.key.key.exponent.data);
2977 + nss_ZFreeIf(io->u.key.key.modulus.data);
2978 + nss_ZFreeIf(io->u.key.key.privateKey->data);
2979 + nss_ZFreeIf(io->u.key.key.privateKey);
2980 + nss_ZFreeIf(io->u.key.key.pubKey);
2981 + nss_ZFreeIf(io->id.data);
2982 + nss_ZFreeIf(io->nickname);
2983 + nss_ZFreeIf(io->derCert->data);
2984 + nss_ZFreeIf(io->derCert);
2986 + /* strdup'd in ReadDERFromFile */
2987 + if (io->u.key.ivstring)
2988 + free(io->u.key.ivstring);
2989 + break;
2992 + if (NULL != gobj)
2993 + /* remove reference to self from the global array */
2994 + gobj[io->gobjIndex] = NULL;
2996 + nss_ZFreeIf(io);
2997 + return;
3001 + * Finalize - needed
3002 + * Destroy - CKR_SESSION_READ_ONLY
3003 + * IsTokenObject - CK_TRUE
3004 + * GetAttributeCount
3005 + * GetAttributeTypes
3006 + * GetAttributeSize
3007 + * GetAttribute
3008 + * SetAttribute - unneeded
3009 + * GetObjectSize - unneeded
3010 + */
3012 +static void
3013 +pem_mdObject_Finalize
3015 + NSSCKMDObject * mdObject,
3016 + NSSCKFWObject * fwObject,
3017 + NSSCKMDSession * mdSession,
3018 + NSSCKFWSession * fwSession,
3019 + NSSCKMDToken * mdToken,
3020 + NSSCKFWToken * fwToken,
3021 + NSSCKMDInstance * mdInstance,
3022 + NSSCKFWInstance * fwInstance
3025 + pem_DestroyInternalObject((pemInternalObject *) mdObject->etc);
3028 +static CK_RV
3029 +pem_mdObject_Destroy
3031 + NSSCKMDObject * mdObject,
3032 + NSSCKFWObject * fwObject,
3033 + NSSCKMDSession * mdSession,
3034 + NSSCKFWSession * fwSession,
3035 + NSSCKMDToken * mdToken,
3036 + NSSCKFWToken * fwToken,
3037 + NSSCKMDInstance * mdInstance,
3038 + NSSCKFWInstance * fwInstance
3041 + pemInternalObject *io = (pemInternalObject *) mdObject->etc;
3043 + pem_DestroyInternalObject(io);
3044 + return CKR_OK;
3047 +static CK_BBOOL
3048 +pem_mdObject_IsTokenObject
3050 + NSSCKMDObject * mdObject,
3051 + NSSCKFWObject * fwObject,
3052 + NSSCKMDSession * mdSession,
3053 + NSSCKFWSession * fwSession,
3054 + NSSCKMDToken * mdToken,
3055 + NSSCKFWToken * fwToken,
3056 + NSSCKMDInstance * mdInstance,
3057 + NSSCKFWInstance * fwInstance
3060 + return CK_TRUE;
3063 +static CK_ULONG
3064 +pem_mdObject_GetAttributeCount
3066 + NSSCKMDObject * mdObject,
3067 + NSSCKFWObject * fwObject,
3068 + NSSCKMDSession * mdSession,
3069 + NSSCKFWSession * fwSession,
3070 + NSSCKMDToken * mdToken,
3071 + NSSCKFWToken * fwToken,
3072 + NSSCKMDInstance * mdInstance,
3073 + NSSCKFWInstance * fwInstance,
3074 + CK_RV * pError
3077 + pemInternalObject *io = (pemInternalObject *) mdObject->etc;
3079 + if (NULL != io->list) {
3080 + /* list object --> use the first item in the list */
3081 + NSSCKMDObject *md = &(io->list->io->mdObject);
3082 + return md->GetAttributeCount(md, fwObject, mdSession, fwSession,
3083 + mdToken, fwToken, mdInstance, fwInstance,
3084 + pError);
3087 + if (pemRaw == io->type) {
3088 + return io->u.raw.n;
3090 + switch (io->objClass) {
3091 + case CKO_CERTIFICATE:
3092 + return certAttrsCount;
3093 + case CKO_PUBLIC_KEY:
3094 + return pubKeyAttrsCount;
3095 + case CKO_PRIVATE_KEY:
3096 + return privKeyAttrsCount;
3097 + case CKO_NETSCAPE_TRUST:
3098 + return trustAttrsCount;
3099 + default:
3100 + break;
3102 + return 0;
3105 +static CK_RV
3106 +pem_mdObject_GetAttributeTypes
3108 + NSSCKMDObject * mdObject,
3109 + NSSCKFWObject * fwObject,
3110 + NSSCKMDSession * mdSession,
3111 + NSSCKFWSession * fwSession,
3112 + NSSCKMDToken * mdToken,
3113 + NSSCKFWToken * fwToken,
3114 + NSSCKMDInstance * mdInstance,
3115 + NSSCKFWInstance * fwInstance,
3116 + CK_ATTRIBUTE_TYPE_PTR typeArray,
3117 + CK_ULONG ulCount
3120 + pemInternalObject *io = (pemInternalObject *) mdObject->etc;
3121 + CK_ULONG i;
3122 + CK_RV error = CKR_OK;
3123 + const CK_ATTRIBUTE_TYPE *attrs = NULL;
3124 + CK_ULONG size;
3126 + if (NULL != io->list) {
3127 + /* list object --> use the first item in the list */
3128 + NSSCKMDObject *md = &(io->list->io->mdObject);
3129 + return md->GetAttributeTypes(md, fwObject, mdSession, fwSession,
3130 + mdToken, fwToken, mdInstance, fwInstance,
3131 + typeArray, ulCount);
3134 + size = pem_mdObject_GetAttributeCount(mdObject, fwObject, mdSession,
3135 + fwSession, mdToken, fwToken, mdInstance,
3136 + fwInstance, &error);
3138 + if (size != ulCount) {
3139 + return CKR_BUFFER_TOO_SMALL;
3141 + if (io->type == pemRaw) {
3142 + attrs = io->u.raw.types;
3143 + } else
3144 + switch (io->objClass) {
3145 + case CKO_CERTIFICATE:
3146 + attrs = certAttrs;
3147 + break;
3148 + case CKO_PUBLIC_KEY:
3149 + attrs = pubKeyAttrs;
3150 + break;
3151 + case CKO_PRIVATE_KEY:
3152 + attrs = privKeyAttrs;
3153 + break;
3154 + default:
3155 + return CKR_OK;
3158 + for (i = 0; i < size; i++) {
3159 + typeArray[i] = attrs[i];
3162 + return CKR_OK;
3165 +static CK_ULONG
3166 +pem_mdObject_GetAttributeSize
3168 + NSSCKMDObject * mdObject,
3169 + NSSCKFWObject * fwObject,
3170 + NSSCKMDSession * mdSession,
3171 + NSSCKFWSession * fwSession,
3172 + NSSCKMDToken * mdToken,
3173 + NSSCKFWToken * fwToken,
3174 + NSSCKMDInstance * mdInstance,
3175 + NSSCKFWInstance * fwInstance,
3176 + CK_ATTRIBUTE_TYPE attribute,
3177 + CK_RV * pError
3180 + pemInternalObject *io = (pemInternalObject *) mdObject->etc;
3181 + const NSSItem *b;
3183 + if (NULL != io->list) {
3184 + /* list object --> use the first item in the list */
3185 + NSSCKMDObject *md = &(io->list->io->mdObject);
3186 + return md->GetAttributeSize(md, fwObject, mdSession, fwSession,
3187 + mdToken, fwToken, mdInstance, fwInstance,
3188 + attribute, pError);
3191 + b = pem_FetchAttribute(io, attribute);
3193 + if ((const NSSItem *) NULL == b) {
3194 + *pError = CKR_ATTRIBUTE_TYPE_INVALID;
3195 + return 0;
3197 + return b->size;
3200 +static NSSCKFWItem
3201 +pem_mdObject_GetAttribute
3203 + NSSCKMDObject * mdObject,
3204 + NSSCKFWObject * fwObject,
3205 + NSSCKMDSession * mdSession,
3206 + NSSCKFWSession * fwSession,
3207 + NSSCKMDToken * mdToken,
3208 + NSSCKFWToken * fwToken,
3209 + NSSCKMDInstance * mdInstance,
3210 + NSSCKFWInstance * fwInstance,
3211 + CK_ATTRIBUTE_TYPE attribute,
3212 + CK_RV * pError
3215 + NSSCKFWItem mdItem;
3216 + pemInternalObject *io = (pemInternalObject *) mdObject->etc;
3218 + if (NULL != io->list) {
3219 + /* list object --> use the first item in the list */
3220 + NSSCKMDObject *md = &(io->list->io->mdObject);
3221 + return md->GetAttribute(md, fwObject, mdSession, fwSession,
3222 + mdToken, fwToken, mdInstance, fwInstance,
3223 + attribute, pError);
3226 + mdItem.needsFreeing = PR_FALSE;
3227 + mdItem.item = (NSSItem *) pem_FetchAttribute(io, attribute);
3229 + if ((NSSItem *) NULL == mdItem.item) {
3230 + *pError = CKR_ATTRIBUTE_TYPE_INVALID;
3233 + return mdItem;
3237 + * get an attribute from a template. Value is returned in NSS item.
3238 + * data for the item is owned by the template.
3239 + */
3240 +CK_RV
3241 +pem_GetAttribute
3243 + CK_ATTRIBUTE_TYPE type,
3244 + CK_ATTRIBUTE * template,
3245 + CK_ULONG templateSize,
3246 + NSSItem * item
3249 + CK_ULONG i;
3251 + for (i = 0; i < templateSize; i++) {
3252 + if (template[i].type == type) {
3253 + item->data = template[i].pValue;
3254 + item->size = template[i].ulValueLen;
3255 + return CKR_OK;
3258 + return CKR_TEMPLATE_INCOMPLETE;
3262 + * get an attribute which is type CK_ULONG.
3263 + */
3264 +CK_ULONG
3265 +pem_GetULongAttribute
3267 + CK_ATTRIBUTE_TYPE type,
3268 + CK_ATTRIBUTE * template,
3269 + CK_ULONG templateSize,
3270 + CK_RV * pError
3273 + NSSItem item;
3275 + *pError = pem_GetAttribute(type, template, templateSize, &item);
3276 + if (CKR_OK != *pError) {
3277 + return (CK_ULONG) 0;
3279 + if (item.size != sizeof(CK_ULONG)) {
3280 + *pError = CKR_ATTRIBUTE_VALUE_INVALID;
3281 + return (CK_ULONG) 0;
3283 + return *(CK_ULONG *) item.data;
3286 +/*
3287 + * get an attribute which is type CK_BBOOL.
3288 + */
3289 +CK_BBOOL
3290 +pem_GetBoolAttribute
3292 + CK_ATTRIBUTE_TYPE type,
3293 + CK_ATTRIBUTE * template,
3294 + CK_ULONG templateSize,
3295 + CK_RV * pError
3298 + NSSItem item;
3300 + *pError = pem_GetAttribute(type, template, templateSize, &item);
3301 + if (CKR_OK != *pError) {
3302 + return (CK_BBOOL) 0;
3304 + if (item.size != sizeof(CK_BBOOL)) {
3305 + *pError = CKR_ATTRIBUTE_VALUE_INVALID;
3306 + return (CK_BBOOL) 0;
3308 + return *(CK_BBOOL *) item.data;
3312 + * Get a string attribute. Caller needs to free this.
3313 + */
3314 +char *
3315 +pem_GetStringAttribute
3317 + CK_ATTRIBUTE_TYPE type,
3318 + CK_ATTRIBUTE * template,
3319 + CK_ULONG templateSize,
3320 + CK_RV * pError
3323 + NSSItem item;
3324 + char *str;
3326 + /* get the attribute */
3327 + *pError = pem_GetAttribute(type, template, templateSize, &item);
3328 + if (CKR_OK != *pError) {
3329 + return (char *) NULL;
3331 + /* make sure it is null terminated */
3332 + str = nss_ZNEWARRAY(NULL, char, item.size + 1);
3333 + if ((char *) NULL == str) {
3334 + *pError = CKR_HOST_MEMORY;
3335 + return (char *) NULL;
3338 + nsslibc_memcpy(str, item.data, item.size);
3339 + str[item.size] = 0;
3341 + return str;
3344 +static const NSSCKMDObject
3345 +pem_prototype_mdObject = {
3346 + (void *) NULL, /* etc */
3347 + pem_mdObject_Finalize,
3348 + pem_mdObject_Destroy,
3349 + pem_mdObject_IsTokenObject,
3350 + pem_mdObject_GetAttributeCount,
3351 + pem_mdObject_GetAttributeTypes,
3352 + pem_mdObject_GetAttributeSize,
3353 + pem_mdObject_GetAttribute,
3354 + NULL, /* FreeAttribute */
3355 + NULL, /* SetAttribute */
3356 + NULL, /* GetObjectSize */
3357 + (void *) NULL /* null terminator */
3360 +NSS_IMPLEMENT NSSCKMDObject *
3361 +pem_CreateMDObject
3363 + NSSArena * arena,
3364 + pemInternalObject * io,
3365 + CK_RV * pError
3368 + if ((void *) NULL == io->mdObject.etc) {
3369 + (void) nsslibc_memcpy(&io->mdObject, &pem_prototype_mdObject,
3370 + sizeof(pem_prototype_mdObject));
3371 + io->mdObject.etc = (void *) io;
3374 + return &io->mdObject;
3378 + * Each object has an identifier. For a certificate and key pair this id
3379 + * needs to be the same so we use the right combination. If the target object
3380 + * is a key we first look to see if its certificate was already added and if
3381 + * so, use that id. The same thing is done when a key is added.
3382 + */
3383 +NSS_EXTERN NSSCKMDObject *
3384 +pem_CreateObject
3386 + NSSCKFWInstance * fwInstance,
3387 + NSSCKFWSession * fwSession,
3388 + NSSCKMDToken * mdToken,
3389 + CK_ATTRIBUTE_PTR pTemplate,
3390 + CK_ULONG ulAttributeCount,
3391 + CK_RV * pError
3394 + CK_OBJECT_CLASS objClass;
3395 + CK_BBOOL isToken;
3396 + NSSCKFWSlot *fwSlot;
3397 + CK_SLOT_ID slotID;
3398 + CK_BBOOL cacert;
3399 + char *filename;
3400 + SECItem **derlist = NULL;
3401 + int nobjs = 0;
3402 + int i;
3403 + int objid;
3404 + pemToken *token;
3405 + int cipher;
3406 + char *ivstring = NULL;
3407 + pemInternalObject *listObj = NULL;
3408 + pemObjectListItem *listItem = NULL;
3410 + /*
3411 + * only create token objects
3412 + */
3413 + isToken = pem_GetBoolAttribute(CKA_TOKEN, pTemplate,
3414 + ulAttributeCount, pError);
3415 + if (CKR_OK != *pError) {
3416 + return (NSSCKMDObject *) NULL;
3418 + if (!isToken) {
3419 + *pError = CKR_ATTRIBUTE_VALUE_INVALID;
3420 + return (NSSCKMDObject *) NULL;
3423 + /* What slot are we adding the object to? */
3424 + fwSlot = nssCKFWSession_GetFWSlot(fwSession);
3425 + if ((NSSCKFWSlot *) NULL == fwSlot) {
3426 + *pError = CKR_ATTRIBUTE_VALUE_INVALID;
3427 + *pError = CKR_GENERAL_ERROR;
3428 + return (NSSCKMDObject *) NULL;
3431 + slotID = nssCKFWSlot_GetSlotID(fwSlot);
3433 + token = (pemToken *) mdToken->etc;
3435 + /*
3436 + * only create keys and certs.
3437 + */
3438 + objClass = pem_GetULongAttribute(CKA_CLASS, pTemplate,
3439 + ulAttributeCount, pError);
3440 + if (CKR_OK != *pError) {
3441 + return (NSSCKMDObject *) NULL;
3444 + cacert = pem_GetBoolAttribute(CKA_TRUST, pTemplate,
3445 + ulAttributeCount, pError);
3447 + filename = pem_GetStringAttribute(CKA_LABEL, pTemplate,
3448 + ulAttributeCount, pError);
3449 + if (CKR_OK != *pError) {
3450 + return (NSSCKMDObject *) NULL;
3453 +#ifdef notdef
3454 + if (objClass == CKO_PUBLIC_KEY) {
3455 + return CKR_OK; /* fake public key creation, happens as a side effect of
3456 + * private key creation */
3458 +#endif
3460 + listObj = nss_ZNEW(NULL, pemInternalObject);
3461 + if (NULL == listObj) {
3462 + nss_ZFreeIf(filename);
3463 + return NULL;
3466 + listItem = listObj->list = nss_ZNEW(NULL, pemObjectListItem);
3467 + if (NULL == listItem) {
3468 + nss_ZFreeIf(listObj);
3469 + nss_ZFreeIf(filename);
3470 + return NULL;
3473 + if (objClass == CKO_CERTIFICATE) {
3474 + nobjs = ReadDERFromFile(&derlist, filename, PR_TRUE, &cipher, &ivstring, PR_TRUE /* certs only */);
3475 + if (nobjs < 1)
3476 + goto loser;
3478 + /* We're just adding a cert, we'll assume the key is next */
3479 + objid = pem_nobjs + 1;
3481 + if (cacert) {
3482 + /* Add the certificate. There may be more than one */
3483 + int c;
3484 + for (c = 0; c < nobjs; c++) {
3485 + char nickname[1024];
3486 + objid = pem_nobjs + 1;
3488 + PR_snprintf(nickname, 1024, "%s - %d", filename, c);
3490 + if (c)
3491 + APPEND_LIST_ITEM(listItem);
3492 + listItem->io = AddObjectIfNeeded(CKO_CERTIFICATE, pemCert,
3493 + derlist[c], NULL, nickname, 0,
3494 + slotID, NULL);
3495 + if (listItem->io == NULL)
3496 + goto loser;
3498 + /* Add the trust object */
3499 + APPEND_LIST_ITEM(listItem);
3500 + listItem->io = AddObjectIfNeeded(CKO_NETSCAPE_TRUST, pemTrust,
3501 + derlist[c], NULL, nickname, 0,
3502 + slotID, NULL);
3503 + if (listItem->io == NULL)
3504 + goto loser;
3506 + } else {
3507 + listItem->io = AddObjectIfNeeded(CKO_CERTIFICATE, pemCert,
3508 + derlist[0], NULL, filename, objid,
3509 + slotID, NULL);
3510 + if (listItem->io == NULL)
3511 + goto loser;
3513 + } else if (objClass == CKO_PRIVATE_KEY) {
3514 + /* Brute force: find the id of the certificate, if any, in this slot */
3515 + int i;
3516 + SECItem certDER;
3517 + CK_SESSION_HANDLE hSession;
3518 + PRBool added;
3520 + nobjs = ReadDERFromFile(&derlist, filename, PR_TRUE, &cipher, &ivstring, PR_FALSE /* keys only */);
3521 + if (nobjs < 1)
3522 + goto loser;
3524 + certDER.len = 0; /* in case there is no equivalent cert */
3525 + certDER.data = NULL;
3527 + objid = -1;
3528 + for (i = 0; i < pem_nobjs; i++) {
3529 + if (NULL == gobj[i])
3530 + continue;
3532 + if ((slotID == gobj[i]->slotID) && (gobj[i]->type == pemCert)) {
3533 + objid = atoi(gobj[i]->id.data);
3534 + certDER.data =
3535 + (void *) nss_ZAlloc(NULL, gobj[i]->derCert->len);
3537 + if (certDER.data == NULL)
3538 + goto loser;
3540 + certDER.len = gobj[i]->derCert->len;
3541 + nsslibc_memcpy(certDER.data, gobj[i]->derCert->data,
3542 + gobj[i]->derCert->len);
3546 + /* We're just adding a key, we'll assume the cert is next */
3547 + if (objid == -1)
3548 + objid = pem_nobjs + 1;
3550 + listItem->io = AddObjectIfNeeded(CKO_PRIVATE_KEY, pemBareKey, &certDER,
3551 + derlist[0], filename, objid, slotID,
3552 + &added);
3553 + if (listItem->io == NULL)
3554 + goto loser;
3556 + listItem->io->u.key.ivstring = ivstring;
3557 + listItem->io->u.key.cipher = cipher;
3558 + nss_ZFreeIf(certDER.data);
3560 + /* If the key was encrypted then free the session to make it appear that
3561 + * the token was removed so we can force a login.
3562 + */
3563 + if (cipher && added) {
3564 + /* FIXME: Why 1.0s? Is it enough? Isn't it too much?
3565 + * What about e.g. 3.14s? */
3566 + PRIntervalTime onesec = PR_SecondsToInterval(1);
3567 + token_needsLogin[slotID - 1] = PR_TRUE;
3569 + /* We have to sleep so that NSS will notice that the token was
3570 + * removed.
3571 + */
3572 + PR_Sleep(onesec);
3573 + hSession =
3574 + nssCKFWInstance_FindSessionHandle(fwInstance, fwSession);
3575 + nssCKFWInstance_DestroySessionHandle(fwInstance, hSession);
3576 + } else {
3577 + *pError = CKR_KEY_UNEXTRACTABLE;
3579 + } else {
3580 + *pError = CKR_ATTRIBUTE_VALUE_INVALID;
3583 + loser:
3585 + for (i = 0; i < nobjs; i++) {
3586 + free(derlist[i]->data);
3587 + free(derlist[i]);
3589 + nss_ZFreeIf(filename);
3590 + nss_ZFreeIf(derlist);
3591 + if ((pemInternalObject *) NULL == listItem->io) {
3592 + pem_DestroyInternalObject(listObj);
3593 + return (NSSCKMDObject *) NULL;
3595 + return pem_CreateMDObject(NULL, listObj, pError);
3597 diff --git a/a/nss/lib/ckfw/pem/prsa.c b/b/nss/lib/ckfw/pem/prsa.c
3598 new file mode 100644
3599 index 0000000..d42e9f7
3600 --- /dev/null
3601 +++ b/b/nss/lib/ckfw/pem/prsa.c
3602 @@ -0,0 +1,702 @@
3603 +/* ***** BEGIN LICENSE BLOCK *****
3604 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3606 + * The contents of this file are subject to the Mozilla Public License Version
3607 + * 1.1 (the "License"); you may not use this file except in compliance with
3608 + * the License. You may obtain a copy of the License at
3609 + * http://www.mozilla.org/MPL/
3611 + * Software distributed under the License is distributed on an "AS IS" basis,
3612 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
3613 + * for the specific language governing rights and limitations under the
3614 + * License.
3616 + * The Original Code is the Netscape security libraries.
3618 + * The Initial Developer of the Original Code is
3619 + * Netscape Communications Corporation.
3620 + * Portions created by the Initial Developer are Copyright (C) 1994-2000
3621 + * the Initial Developer. All Rights Reserved.
3623 + * Contributor(s):
3624 + * Rob Crittenden (rcritten@redhat.com)
3626 + * Alternatively, the contents of this file may be used under the terms of
3627 + * either the GNU General Public License Version 2 or later (the "GPL"), or
3628 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
3629 + * in which case the provisions of the GPL or the LGPL are applicable instead
3630 + * of those above. If you wish to allow use of your version of this file only
3631 + * under the terms of either the GPL or the LGPL, and not to allow others to
3632 + * use your version of this file under the terms of the MPL, indicate your
3633 + * decision by deleting the provisions above and replace them with the notice
3634 + * and other provisions required by the GPL or the LGPL. If you do not delete
3635 + * the provisions above, a recipient may use your version of this file under
3636 + * the terms of any one of the MPL, the GPL or the LGPL.
3638 + * ***** END LICENSE BLOCK ***** */
3640 +#include "ckpem.h"
3641 +#include "secdert.h"
3642 +#include "secoid.h"
3643 +#include "nssckmdt.h"
3645 +#define SSL3_SHAMD5_HASH_SIZE 36 /* LEN_MD5 (16) + LEN_SHA1 (20) */
3647 +SEC_ASN1_MKSUB(SEC_AnyTemplate)
3648 +SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
3651 + * prsa.c
3653 + * This file implements the NSSCKMDMechnaism and NSSCKMDCryptoOperation objects
3654 + * for the RSA operation.
3655 + */
3657 +const SEC_ASN1Template pem_RSAPrivateKeyTemplate[] = {
3658 + {SEC_ASN1_SEQUENCE, 0, NULL, sizeof(pemLOWKEYPrivateKey)} ,
3659 + {SEC_ASN1_INTEGER, offsetof(pemLOWKEYPrivateKey, u.rsa.version)},
3660 + {SEC_ASN1_INTEGER, offsetof(pemLOWKEYPrivateKey, u.rsa.modulus)},
3661 + {SEC_ASN1_INTEGER, offsetof(pemLOWKEYPrivateKey, u.rsa.publicExponent)},
3662 + {SEC_ASN1_INTEGER, offsetof(pemLOWKEYPrivateKey, u.rsa.privateExponent)},
3663 + {SEC_ASN1_INTEGER, offsetof(pemLOWKEYPrivateKey, u.rsa.prime1)},
3664 + {SEC_ASN1_INTEGER, offsetof(pemLOWKEYPrivateKey, u.rsa.prime2)},
3665 + {SEC_ASN1_INTEGER, offsetof(pemLOWKEYPrivateKey, u.rsa.exponent1)},
3666 + {SEC_ASN1_INTEGER, offsetof(pemLOWKEYPrivateKey, u.rsa.exponent2)},
3667 + {SEC_ASN1_INTEGER, offsetof(pemLOWKEYPrivateKey, u.rsa.coefficient)},
3668 + {0}
3671 +static const SEC_ASN1Template pem_AttributeTemplate[] = {
3672 + { SEC_ASN1_SEQUENCE,
3673 + 0, NULL, sizeof(NSSLOWKEYAttribute) },
3674 + { SEC_ASN1_OBJECT_ID, offsetof(NSSLOWKEYAttribute, attrType) },
3675 + { SEC_ASN1_SET_OF | SEC_ASN1_XTRN, offsetof(NSSLOWKEYAttribute, attrValue),
3676 + SEC_ASN1_SUB(SEC_AnyTemplate) },
3677 + { 0 }
3680 +static const SEC_ASN1Template pem_SetOfAttributeTemplate[] = {
3681 + { SEC_ASN1_SET_OF, 0, pem_AttributeTemplate },
3684 +const SEC_ASN1Template pem_PrivateKeyInfoTemplate[] = {
3685 + { SEC_ASN1_SEQUENCE,
3686 + 0, NULL, sizeof(NSSLOWKEYPrivateKeyInfo) },
3687 + { SEC_ASN1_INTEGER,
3688 + offsetof(NSSLOWKEYPrivateKeyInfo,version) },
3689 + { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
3690 + offsetof(NSSLOWKEYPrivateKeyInfo,algorithm),
3691 + SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
3692 + { SEC_ASN1_OCTET_STRING,
3693 + offsetof(NSSLOWKEYPrivateKeyInfo,privateKey) },
3694 + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
3695 + offsetof(NSSLOWKEYPrivateKeyInfo, attributes),
3696 + pem_SetOfAttributeTemplate },
3697 + { 0 }
3700 +/* Declarations */
3701 +SECStatus pem_RSA_Sign(pemLOWKEYPrivateKey * key, unsigned char *output,
3702 + unsigned int *outputLen, unsigned int maxOutputLen,
3703 + unsigned char *input, unsigned int inputLen);
3704 +SECStatus pem_RSA_DecryptBlock(pemLOWKEYPrivateKey * key,
3705 + unsigned char *output, unsigned int *outputLen,
3706 + unsigned int maxOutputLen, unsigned char *input,
3707 + unsigned int inputLen);
3709 +void prepare_low_rsa_priv_key_for_asn1(pemLOWKEYPrivateKey * key)
3711 + key->u.rsa.modulus.type = siUnsignedInteger;
3712 + key->u.rsa.publicExponent.type = siUnsignedInteger;
3713 + key->u.rsa.privateExponent.type = siUnsignedInteger;
3714 + key->u.rsa.prime1.type = siUnsignedInteger;
3715 + key->u.rsa.prime2.type = siUnsignedInteger;
3716 + key->u.rsa.exponent1.type = siUnsignedInteger;
3717 + key->u.rsa.exponent2.type = siUnsignedInteger;
3718 + key->u.rsa.coefficient.type = siUnsignedInteger;
3721 +unsigned int
3722 +pem_PrivateModulusLen(pemLOWKEYPrivateKey * privk)
3725 + unsigned char b0;
3727 + switch (privk->keyType) {
3728 + case pemLOWKEYRSAKey:
3729 + b0 = privk->u.rsa.modulus.data[0];
3730 + return b0 ? privk->u.rsa.modulus.len : privk->u.rsa.modulus.len -
3731 + 1;
3732 + default:
3733 + break;
3735 + return 0;
3738 +struct SFTKHashSignInfoStr {
3739 + SECOidTag hashOid;
3740 + pemLOWKEYPrivateKey *key;
3742 +typedef struct SFTKHashSignInfoStr SFTKHashSignInfo;
3744 +void
3745 +pem_DestroyPrivateKey(pemLOWKEYPrivateKey * privk)
3747 + if (privk && privk->arena) {
3748 + PORT_FreeArena(privk->arena, PR_TRUE);
3750 + nss_ZFreeIf(privk);
3753 +/* decode and parse the rawkey into the lpk structure */
3754 +static pemLOWKEYPrivateKey *
3755 +pem_getPrivateKey(PLArenaPool *arena, SECItem *rawkey, CK_RV * pError, NSSItem *modulus)
3757 + pemLOWKEYPrivateKey *lpk = NULL;
3758 + SECStatus rv = SECFailure;
3759 + NSSLOWKEYPrivateKeyInfo *pki = NULL;
3760 + SECItem *keysrc = NULL;
3762 + /* make sure SECOID is initialized - not sure why we have to do this outside of nss_Init */
3763 + if (SECSuccess != (rv = SECOID_Init())) {
3764 + *pError = CKR_GENERAL_ERROR;
3765 + return NULL; /* wha???? */
3768 + pki = (NSSLOWKEYPrivateKeyInfo*)PORT_ArenaZAlloc(arena,
3769 + sizeof(NSSLOWKEYPrivateKeyInfo));
3770 + if(!pki) {
3771 + *pError = CKR_HOST_MEMORY;
3772 + goto done;
3775 + /* let's first see if this is a "raw" RSA private key or an RSA private key in PKCS#8 format */
3776 + rv = SEC_ASN1DecodeItem(arena, pki, pem_PrivateKeyInfoTemplate, rawkey);
3777 + if (rv != SECSuccess) {
3778 + /* not PKCS#8 - assume it's a "raw" RSA private key */
3779 + keysrc = rawkey;
3780 + } else if (SECOID_GetAlgorithmTag(&pki->algorithm) == SEC_OID_PKCS1_RSA_ENCRYPTION) {
3781 + keysrc = &pki->privateKey;
3782 + } else { /* unsupported */
3783 + *pError = CKR_FUNCTION_NOT_SUPPORTED;
3784 + goto done;
3787 + lpk = (pemLOWKEYPrivateKey *) nss_ZAlloc(NULL,
3788 + sizeof(pemLOWKEYPrivateKey));
3789 + if (lpk == NULL) {
3790 + *pError = CKR_HOST_MEMORY;
3791 + goto done;
3794 + lpk->arena = arena;
3795 + lpk->keyType = pemLOWKEYRSAKey;
3796 + prepare_low_rsa_priv_key_for_asn1(lpk);
3798 + /* I don't know what this is supposed to accomplish. We free the old
3799 + modulus data and set it again, making a copy of the new data.
3800 + But we just allocated a new empty key structure above with
3801 + nss_ZAlloc. So lpk->u.rsa.modulus.data is NULL and
3802 + lpk->u.rsa.modulus.len. If the intention is to free the old
3803 + modulus data, why not just set it to NULL after freeing? Why
3804 + go through this unnecessary and confusing copying code?
3805 + */
3806 + if (modulus) {
3807 + nss_ZFreeIf(modulus->data);
3808 + modulus->data = (void *) nss_ZAlloc(NULL, lpk->u.rsa.modulus.len);
3809 + modulus->size = lpk->u.rsa.modulus.len;
3810 + nsslibc_memcpy(modulus->data, lpk->u.rsa.modulus.data,
3811 + lpk->u.rsa.modulus.len);
3814 + /* decode the private key and any algorithm parameters */
3815 + rv = SEC_QuickDERDecodeItem(arena, lpk, pem_RSAPrivateKeyTemplate,
3816 + keysrc);
3818 + if (rv != SECSuccess) {
3819 + goto done;
3822 +done:
3823 + return lpk;
3826 +void
3827 +pem_PopulateModulusExponent(pemInternalObject * io)
3829 + const NSSItem *classItem = pem_FetchAttribute(io, CKA_CLASS);
3830 + const NSSItem *keyType = pem_FetchAttribute(io, CKA_KEY_TYPE);
3831 + pemLOWKEYPrivateKey *lpk = NULL;
3832 + PLArenaPool *arena;
3833 + CK_RV pError = 0;
3835 + /* make sure we have the right objects */
3836 + if (((const NSSItem *) NULL == classItem) ||
3837 + (sizeof(CK_OBJECT_CLASS) != classItem->size) ||
3838 + (CKO_PRIVATE_KEY != *(CK_OBJECT_CLASS *) classItem->data) ||
3839 + ((const NSSItem *) NULL == keyType) ||
3840 + (sizeof(CK_KEY_TYPE) != keyType->size) ||
3841 + (CKK_RSA != *(CK_KEY_TYPE *) keyType->data)) {
3842 + return;
3845 + arena = PORT_NewArena(2048);
3846 + if (!arena) {
3847 + return;
3850 + lpk = pem_getPrivateKey(arena, io->u.key.key.privateKey, &pError, NULL);
3851 + if (lpk == NULL) {
3852 + PORT_FreeArena(arena, PR_FALSE);
3853 + return;
3856 + nss_ZFreeIf(io->u.key.key.modulus.data);
3857 + io->u.key.key.modulus.data =
3858 + (void *) nss_ZAlloc(NULL, lpk->u.rsa.modulus.len);
3859 + io->u.key.key.modulus.size = lpk->u.rsa.modulus.len;
3860 + nsslibc_memcpy(io->u.key.key.modulus.data, lpk->u.rsa.modulus.data,
3861 + lpk->u.rsa.modulus.len);
3863 + nss_ZFreeIf(io->u.key.key.exponent.data);
3864 + io->u.key.key.exponent.data =
3865 + (void *) nss_ZAlloc(NULL, lpk->u.rsa.publicExponent.len);
3866 + io->u.key.key.exponent.size = lpk->u.rsa.publicExponent.len;
3867 + nsslibc_memcpy(io->u.key.key.exponent.data,
3868 + lpk->u.rsa.publicExponent.data,
3869 + lpk->u.rsa.publicExponent.len);
3871 + nss_ZFreeIf(io->u.key.key.privateExponent.data);
3872 + io->u.key.key.privateExponent.data =
3873 + (void *) nss_ZAlloc(NULL, lpk->u.rsa.privateExponent.len);
3874 + io->u.key.key.privateExponent.size = lpk->u.rsa.privateExponent.len;
3875 + nsslibc_memcpy(io->u.key.key.privateExponent.data,
3876 + lpk->u.rsa.privateExponent.data,
3877 + lpk->u.rsa.privateExponent.len);
3879 + nss_ZFreeIf(io->u.key.key.prime1.data);
3880 + io->u.key.key.prime1.data =
3881 + (void *) nss_ZAlloc(NULL, lpk->u.rsa.prime1.len);
3882 + io->u.key.key.prime1.size = lpk->u.rsa.prime1.len;
3883 + nsslibc_memcpy(io->u.key.key.prime1.data, lpk->u.rsa.prime1.data,
3884 + lpk->u.rsa.prime1.len);
3886 + nss_ZFreeIf(io->u.key.key.prime2.data);
3887 + io->u.key.key.prime2.data =
3888 + (void *) nss_ZAlloc(NULL, lpk->u.rsa.prime2.len);
3889 + io->u.key.key.prime2.size = lpk->u.rsa.prime2.len;
3890 + nsslibc_memcpy(io->u.key.key.prime2.data, lpk->u.rsa.prime2.data,
3891 + lpk->u.rsa.prime2.len);
3893 + nss_ZFreeIf(io->u.key.key.exponent1.data);
3894 + io->u.key.key.exponent1.data =
3895 + (void *) nss_ZAlloc(NULL, lpk->u.rsa.exponent1.len);
3896 + io->u.key.key.exponent1.size = lpk->u.rsa.exponent1.len;
3897 + nsslibc_memcpy(io->u.key.key.exponent1.data, lpk->u.rsa.exponent1.data,
3898 + lpk->u.rsa.exponent1.len);
3900 + nss_ZFreeIf(io->u.key.key.exponent2.data);
3901 + io->u.key.key.exponent2.data =
3902 + (void *) nss_ZAlloc(NULL, lpk->u.rsa.exponent2.len);
3903 + io->u.key.key.exponent2.size = lpk->u.rsa.exponent2.len;
3904 + nsslibc_memcpy(io->u.key.key.exponent2.data, lpk->u.rsa.exponent2.data,
3905 + lpk->u.rsa.exponent2.len);
3907 + nss_ZFreeIf(io->u.key.key.coefficient.data);
3908 + io->u.key.key.coefficient.data =
3909 + (void *) nss_ZAlloc(NULL, lpk->u.rsa.coefficient.len);
3910 + io->u.key.key.coefficient.size = lpk->u.rsa.coefficient.len;
3911 + nsslibc_memcpy(io->u.key.key.coefficient.data,
3912 + lpk->u.rsa.coefficient.data,
3913 + lpk->u.rsa.coefficient.len);
3915 + pem_DestroyPrivateKey(lpk);
3916 + return;
3919 +typedef struct pemInternalCryptoOperationRSAPrivStr
3920 + pemInternalCryptoOperationRSAPriv;
3921 +struct pemInternalCryptoOperationRSAPrivStr
3923 + NSSCKMDCryptoOperation mdOperation;
3924 + NSSCKMDMechanism *mdMechanism;
3925 + pemInternalObject *iKey;
3926 + pemLOWKEYPrivateKey *lpk;
3927 + NSSItem *buffer;
3931 + * pem_mdCryptoOperationRSAPriv_Create
3932 + */
3933 +static NSSCKMDCryptoOperation *
3934 +pem_mdCryptoOperationRSAPriv_Create
3936 + const NSSCKMDCryptoOperation * proto,
3937 + NSSCKMDMechanism * mdMechanism,
3938 + NSSCKMDObject * mdKey,
3939 + CK_RV * pError
3942 + pemInternalObject *iKey = (pemInternalObject *) mdKey->etc;
3943 + const NSSItem *classItem = pem_FetchAttribute(iKey, CKA_CLASS);
3944 + const NSSItem *keyType = pem_FetchAttribute(iKey, CKA_KEY_TYPE);
3945 + pemInternalCryptoOperationRSAPriv *iOperation;
3946 + pemLOWKEYPrivateKey *lpk = NULL;
3947 + PLArenaPool *arena;
3949 + /* make sure we have the right objects */
3950 + if (((const NSSItem *) NULL == classItem) ||
3951 + (sizeof(CK_OBJECT_CLASS) != classItem->size) ||
3952 + (CKO_PRIVATE_KEY != *(CK_OBJECT_CLASS *) classItem->data) ||
3953 + ((const NSSItem *) NULL == keyType) ||
3954 + (sizeof(CK_KEY_TYPE) != keyType->size) ||
3955 + (CKK_RSA != *(CK_KEY_TYPE *) keyType->data)) {
3956 + *pError = CKR_KEY_TYPE_INCONSISTENT;
3957 + return (NSSCKMDCryptoOperation *) NULL;
3960 + arena = PORT_NewArena(2048);
3961 + if (!arena) {
3962 + *pError = CKR_HOST_MEMORY;
3963 + return (NSSCKMDCryptoOperation *) NULL;
3966 + lpk = pem_getPrivateKey(arena, iKey->u.key.key.privateKey, pError, &iKey->u.key.key.modulus);
3967 + if (lpk == NULL) {
3968 + PORT_FreeArena(arena, PR_FALSE);
3969 + return (NSSCKMDCryptoOperation *) NULL;
3972 + iOperation = nss_ZNEW(NULL, pemInternalCryptoOperationRSAPriv);
3973 + if ((pemInternalCryptoOperationRSAPriv *) NULL == iOperation) {
3974 + *pError = CKR_HOST_MEMORY;
3975 + return (NSSCKMDCryptoOperation *) NULL;
3977 + iOperation->mdMechanism = mdMechanism;
3978 + iOperation->iKey = iKey;
3979 + iOperation->lpk = lpk;
3981 + nsslibc_memcpy(&iOperation->mdOperation,
3982 + proto, sizeof(NSSCKMDCryptoOperation));
3983 + iOperation->mdOperation.etc = iOperation;
3985 + return &iOperation->mdOperation;
3988 +static void
3989 +pem_mdCryptoOperationRSAPriv_Destroy
3991 + NSSCKMDCryptoOperation * mdOperation,
3992 + NSSCKFWCryptoOperation * fwOperation,
3993 + NSSCKMDInstance * mdInstance,
3994 + NSSCKFWInstance * fwInstance
3997 + pemInternalCryptoOperationRSAPriv *iOperation =
3998 + (pemInternalCryptoOperationRSAPriv *) mdOperation->etc;
4000 + if (iOperation->buffer) {
4001 + nssItem_Destroy(iOperation->buffer);
4002 + iOperation->buffer = NULL;
4004 + pem_DestroyPrivateKey(iOperation->lpk);
4005 + iOperation->lpk = NULL;
4006 + nss_ZFreeIf(iOperation);
4009 +static CK_ULONG
4010 +pem_mdCryptoOperationRSA_GetFinalLength
4012 + NSSCKMDCryptoOperation * mdOperation,
4013 + NSSCKFWCryptoOperation * fwOperation,
4014 + NSSCKMDSession * mdSession,
4015 + NSSCKFWSession * fwSession,
4016 + NSSCKMDToken * mdToken,
4017 + NSSCKFWToken * fwToken,
4018 + NSSCKMDInstance * mdInstance,
4019 + NSSCKFWInstance * fwInstance,
4020 + CK_RV * pError
4023 + pemInternalCryptoOperationRSAPriv *iOperation =
4024 + (pemInternalCryptoOperationRSAPriv *) mdOperation->etc;
4025 + const NSSItem *modulus =
4026 + pem_FetchAttribute(iOperation->iKey, CKA_MODULUS);
4028 + if (NULL == modulus) {
4029 + *pError = CKR_FUNCTION_FAILED;
4030 + return 0;
4033 + return modulus->size;
4038 + * pem_mdCryptoOperationRSADecrypt_GetOperationLength
4039 + * we won't know the length until we actually decrypt the
4040 + * input block. Since we go to all the work to decrypt the
4041 + * the block, we'll save if for when the block is asked for
4042 + */
4043 +static CK_ULONG
4044 +pem_mdCryptoOperationRSADecrypt_GetOperationLength
4046 + NSSCKMDCryptoOperation * mdOperation,
4047 + NSSCKFWCryptoOperation * fwOperation,
4048 + NSSCKMDSession * mdSession,
4049 + NSSCKFWSession * fwSession,
4050 + NSSCKMDToken * mdToken,
4051 + NSSCKFWToken * fwToken,
4052 + NSSCKMDInstance * mdInstance,
4053 + NSSCKFWInstance * fwInstance,
4054 + const NSSItem * input,
4055 + CK_RV * pError
4058 + pemInternalCryptoOperationRSAPriv *iOperation =
4059 + (pemInternalCryptoOperationRSAPriv *) mdOperation->etc;
4060 + SECStatus rv;
4062 + /* FIXME: Just because Microsoft is broken doesn't mean I have to be.
4063 + * but this is faster to do for now */
4065 + /* Microsoft's Decrypt operation works in place. Since we don't want
4066 + * to trash our input buffer, we make a copy of it */
4067 + iOperation->buffer = nssItem_Duplicate((NSSItem *) input, NULL, NULL);
4068 + if ((NSSItem *) NULL == iOperation->buffer) {
4069 + *pError = CKR_HOST_MEMORY;
4070 + return 0;
4073 + rv = pem_RSA_DecryptBlock(iOperation->lpk, iOperation->buffer->data,
4074 + &iOperation->buffer->size,
4075 + iOperation->buffer->size, input->data,
4076 + input->size);
4078 + if (rv != SECSuccess) {
4079 + return 0;
4082 + return iOperation->buffer->size;
4086 + * pem_mdCryptoOperationRSADecrypt_UpdateFinal
4088 + * NOTE: pem_mdCryptoOperationRSADecrypt_GetOperationLength is presumed to
4089 + * have been called previously.
4090 + */
4091 +static CK_RV
4092 +pem_mdCryptoOperationRSADecrypt_UpdateFinal
4094 + NSSCKMDCryptoOperation * mdOperation,
4095 + NSSCKFWCryptoOperation * fwOperation,
4096 + NSSCKMDSession * mdSession,
4097 + NSSCKFWSession * fwSession,
4098 + NSSCKMDToken * mdToken,
4099 + NSSCKFWToken * fwToken,
4100 + NSSCKMDInstance * mdInstance,
4101 + NSSCKFWInstance * fwInstance,
4102 + const NSSItem * input,
4103 + NSSItem * output
4106 + pemInternalCryptoOperationRSAPriv *iOperation =
4107 + (pemInternalCryptoOperationRSAPriv *) mdOperation->etc;
4108 + NSSItem *buffer = iOperation->buffer;
4110 + if ((NSSItem *) NULL == buffer) {
4111 + return CKR_GENERAL_ERROR;
4113 + nsslibc_memcpy(output->data, buffer->data, buffer->size);
4114 + output->size = buffer->size;
4115 + return CKR_OK;
4119 + * pem_mdCryptoOperationRSASign_UpdateFinal
4121 + */
4122 +static CK_RV
4123 +pem_mdCryptoOperationRSASign_UpdateFinal
4125 + NSSCKMDCryptoOperation * mdOperation,
4126 + NSSCKFWCryptoOperation * fwOperation,
4127 + NSSCKMDSession * mdSession,
4128 + NSSCKFWSession * fwSession,
4129 + NSSCKMDToken * mdToken,
4130 + NSSCKFWToken * fwToken,
4131 + NSSCKMDInstance * mdInstance,
4132 + NSSCKFWInstance * fwInstance,
4133 + const NSSItem * input,
4134 + NSSItem * output
4137 + pemInternalCryptoOperationRSAPriv *iOperation =
4138 + (pemInternalCryptoOperationRSAPriv *) mdOperation->etc;
4139 + CK_RV error = CKR_OK;
4140 + SECStatus rv = SECSuccess;
4142 + rv = pem_RSA_Sign(iOperation->lpk, output->data, &output->size,
4143 + output->size, input->data, input->size);
4145 + if (rv != SECSuccess) {
4146 + error = CKR_GENERAL_ERROR;
4149 + return error;
4152 +NSS_IMPLEMENT_DATA const NSSCKMDCryptoOperation
4153 +pem_mdCryptoOperationRSADecrypt_proto = {
4154 + NULL, /* etc */
4155 + pem_mdCryptoOperationRSAPriv_Destroy,
4156 + NULL, /* GetFinalLengh - not needed for one shot Decrypt/Encrypt */
4157 + pem_mdCryptoOperationRSADecrypt_GetOperationLength,
4158 + NULL, /* Final - not needed for one shot operation */
4159 + NULL, /* Update - not needed for one shot operation */
4160 + NULL, /* DigestUpdate - not needed for one shot operation */
4161 + pem_mdCryptoOperationRSADecrypt_UpdateFinal,
4162 + NULL, /* UpdateCombo - not needed for one shot operation */
4163 + NULL, /* DigestKey - not needed for one shot operation */
4164 + (void *) NULL /* null terminator */
4167 +NSS_IMPLEMENT_DATA const NSSCKMDCryptoOperation
4168 +pem_mdCryptoOperationRSASign_proto = {
4169 + NULL, /* etc */
4170 + pem_mdCryptoOperationRSAPriv_Destroy,
4171 + pem_mdCryptoOperationRSA_GetFinalLength,
4172 + NULL, /* GetOperationLengh - not needed for one shot Sign/Verify */
4173 + NULL, /* Final - not needed for one shot operation */
4174 + NULL, /* Update - not needed for one shot operation */
4175 + NULL, /* DigestUpdate - not needed for one shot operation */
4176 + pem_mdCryptoOperationRSASign_UpdateFinal,
4177 + NULL, /* UpdateCombo - not needed for one shot operation */
4178 + NULL, /* DigestKey - not needed for one shot operation */
4179 + (void *) NULL /* null terminator */
4182 +/********** NSSCKMDMechansim functions ***********************/
4184 + * pem_mdMechanismRSA_Destroy
4185 + */
4186 +static void
4187 +pem_mdMechanismRSA_Destroy
4189 + NSSCKMDMechanism * mdMechanism,
4190 + NSSCKFWMechanism * fwMechanism,
4191 + NSSCKMDInstance * mdInstance,
4192 + NSSCKFWInstance * fwInstance
4195 + nss_ZFreeIf(fwMechanism);
4199 + * pem_mdMechanismRSA_GetMinKeySize
4200 + */
4201 +static CK_ULONG
4202 +pem_mdMechanismRSA_GetMinKeySize
4204 + NSSCKMDMechanism * mdMechanism,
4205 + NSSCKFWMechanism * fwMechanism,
4206 + NSSCKMDToken * mdToken,
4207 + NSSCKFWToken * fwToken,
4208 + NSSCKMDInstance * mdInstance,
4209 + NSSCKFWInstance * fwInstance,
4210 + CK_RV * pError
4213 + return 384;
4217 + * pem_mdMechanismRSA_GetMaxKeySize
4218 + */
4219 +static CK_ULONG
4220 +pem_mdMechanismRSA_GetMaxKeySize
4222 + NSSCKMDMechanism * mdMechanism,
4223 + NSSCKFWMechanism * fwMechanism,
4224 + NSSCKMDToken * mdToken,
4225 + NSSCKFWToken * fwToken,
4226 + NSSCKMDInstance * mdInstance,
4227 + NSSCKFWInstance * fwInstance,
4228 + CK_RV * pError
4231 + return 16384;
4235 + * pem_mdMechanismRSA_DecryptInit
4236 + */
4237 +static NSSCKMDCryptoOperation *
4238 +pem_mdMechanismRSA_DecryptInit
4240 + NSSCKMDMechanism * mdMechanism,
4241 + NSSCKFWMechanism * fwMechanism,
4242 + CK_MECHANISM * pMechanism,
4243 + NSSCKMDSession * mdSession,
4244 + NSSCKFWSession * fwSession,
4245 + NSSCKMDToken * mdToken,
4246 + NSSCKFWToken * fwToken,
4247 + NSSCKMDInstance * mdInstance,
4248 + NSSCKFWInstance * fwInstance,
4249 + NSSCKMDObject * mdKey,
4250 + NSSCKFWObject * fwKey,
4251 + CK_RV * pError
4254 + return pem_mdCryptoOperationRSAPriv_Create
4255 + (&pem_mdCryptoOperationRSADecrypt_proto, mdMechanism, mdKey,
4256 + pError);
4260 + * pem_mdMechanismRSA_SignInit
4261 + */
4262 +static NSSCKMDCryptoOperation *
4263 +pem_mdMechanismRSA_SignInit
4265 + NSSCKMDMechanism * mdMechanism,
4266 + NSSCKFWMechanism * fwMechanism,
4267 + CK_MECHANISM * pMechanism,
4268 + NSSCKMDSession * mdSession,
4269 + NSSCKFWSession * fwSession,
4270 + NSSCKMDToken * mdToken,
4271 + NSSCKFWToken * fwToken,
4272 + NSSCKMDInstance * mdInstance,
4273 + NSSCKFWInstance * fwInstance,
4274 + NSSCKMDObject * mdKey,
4275 + NSSCKFWObject * fwKey,
4276 + CK_RV * pError
4279 + return pem_mdCryptoOperationRSAPriv_Create
4280 + (&pem_mdCryptoOperationRSASign_proto, mdMechanism, mdKey, pError);
4283 +NSS_IMPLEMENT_DATA const NSSCKMDMechanism
4284 +pem_mdMechanismRSA = {
4285 + (void *) NULL, /* etc */
4286 + pem_mdMechanismRSA_Destroy,
4287 + pem_mdMechanismRSA_GetMinKeySize,
4288 + pem_mdMechanismRSA_GetMaxKeySize,
4289 + NULL, /* GetInHardware - default false */
4290 + NULL, /* EncryptInit - default errs */
4291 + pem_mdMechanismRSA_DecryptInit,
4292 + NULL, /* DigestInit - default errs */
4293 + pem_mdMechanismRSA_SignInit,
4294 + NULL, /* VerifyInit - default errs */
4295 + pem_mdMechanismRSA_SignInit, /* SignRecoverInit */
4296 + NULL, /* VerifyRecoverInit - default errs */
4297 + NULL, /* GenerateKey - default errs */
4298 + NULL, /* GenerateKeyPair - default errs */
4299 + NULL, /* GetWrapKeyLength - default errs */
4300 + NULL, /* WrapKey - default errs */
4301 + NULL, /* UnwrapKey - default errs */
4302 + NULL, /* DeriveKey - default errs */
4303 + (void *) NULL /* null terminator */
4305 diff --git a/a/nss/lib/ckfw/pem/psession.c b/b/nss/lib/ckfw/pem/psession.c
4306 new file mode 100644
4307 index 0000000..70c5407
4308 --- /dev/null
4309 +++ b/b/nss/lib/ckfw/pem/psession.c
4310 @@ -0,0 +1,388 @@
4311 +/* ***** BEGIN LICENSE BLOCK *****
4312 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4314 + * The contents of this file are subject to the Mozilla Public License Version
4315 + * 1.1 (the "License"); you may not use this file except in compliance with
4316 + * the License. You may obtain a copy of the License at
4317 + * http://www.mozilla.org/MPL/
4319 + * Software distributed under the License is distributed on an "AS IS" basis,
4320 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
4321 + * for the specific language governing rights and limitations under the
4322 + * License.
4324 + * The Original Code is the Netscape security libraries.
4326 + * The Initial Developer of the Original Code is
4327 + * Netscape Communications Corporation.
4328 + * Portions created by the Initial Developer are Copyright (C) 1994-2000
4329 + * the Initial Developer. All Rights Reserved.
4331 + * Contributor(s):
4332 + * Rob Crittenden (rcritten@redhat.com)
4334 + * Alternatively, the contents of this file may be used under the terms of
4335 + * either the GNU General Public License Version 2 or later (the "GPL"), or
4336 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
4337 + * in which case the provisions of the GPL or the LGPL are applicable instead
4338 + * of those above. If you wish to allow use of your version of this file only
4339 + * under the terms of either the GPL or the LGPL, and not to allow others to
4340 + * use your version of this file under the terms of the MPL, indicate your
4341 + * decision by deleting the provisions above and replace them with the notice
4342 + * and other provisions required by the GPL or the LGPL. If you do not delete
4343 + * the provisions above, a recipient may use your version of this file under
4344 + * the terms of any one of the MPL, the GPL or the LGPL.
4346 + * ***** END LICENSE BLOCK ***** */
4348 +#include "ckpem.h"
4349 +#include "secmodt.h"
4350 +#include "pk11pub.h"
4351 +#include "base64.h"
4352 +#include "blapi.h"
4355 + * psession.c
4357 + * This file implements the NSSCKMDSession object for the
4358 + * "PEM objects" cryptoki module.
4359 + */
4361 +NSS_EXTERN_DATA pemInternalObject **gobj;
4362 +NSS_EXTERN_DATA int pem_nobjs;
4363 +NSS_EXTERN_DATA int token_needsLogin[NUM_SLOTS];
4364 +NSS_EXTERN_DATA const SEC_ASN1Template pem_RSAPrivateKeyTemplate[];
4366 +void prepare_low_rsa_priv_key_for_asn1(NSSLOWKEYPrivateKey * key);
4367 +void pem_DestroyPrivateKey(NSSLOWKEYPrivateKey * privk);
4370 + * Convert a hex string into bytes.
4371 + */
4372 +static unsigned char *convert_iv(char *src, int num)
4374 + int i;
4375 + char conv[3];
4376 + unsigned char *c;
4378 + c = (unsigned char *) malloc((num) + 1);
4379 + if (c == NULL)
4380 + return NULL;
4382 + conv[2] = '\0';
4383 + memset(c, 0, num);
4384 + for (i = 0; i < num; i++) {
4385 + conv[0] = src[(i * 2)];
4386 + conv[1] = src[(i * 2) + 1];
4387 + c[i] = strtol(conv, NULL, 16);
4389 + return c;
4393 + * The key is a 24-bit hash. The first 16 bits are the MD5 hash of the
4394 + * password and the IV (salt). This has is then re-hashed with the
4395 + * password and IV again and the first 8 bytes of that are the remaining
4396 + * bytes of the 24-bit key.
4397 + */
4398 +static int
4399 +make_key(const unsigned char *salt, const unsigned char *data, int len,
4400 + unsigned char *key)
4402 + int nkey = 0;
4403 + MD5Context *Md5Ctx = MD5_NewContext();
4404 + unsigned int digestLen;
4405 + int count, i;
4406 + unsigned char H[25];
4408 + nkey = 24;
4409 + count = 0;
4411 + while (nkey > 0) {
4412 + MD5_Begin(Md5Ctx);
4413 + if (count)
4414 + MD5_Update(Md5Ctx, (const unsigned char *) H, digestLen);
4415 + MD5_Update(Md5Ctx, (const unsigned char *) data, len);
4416 + MD5_Update(Md5Ctx, (const unsigned char *) salt, 8);
4417 + MD5_End(Md5Ctx, (unsigned char *) H, &digestLen, sizeof(H));
4419 + i = 0;
4420 + while (nkey && (i != digestLen)) {
4421 + *(key++) = H[i];
4422 + nkey--;
4423 + i++;
4425 + count++;
4427 + MD5_DestroyContext(Md5Ctx, PR_TRUE);
4429 + return 24;
4432 +static NSSCKMDFindObjects *
4433 +pem_mdSession_FindObjectsInit
4435 + NSSCKMDSession * mdSession,
4436 + NSSCKFWSession * fwSession,
4437 + NSSCKMDToken * mdToken,
4438 + NSSCKFWToken * fwToken,
4439 + NSSCKMDInstance * mdInstance,
4440 + NSSCKFWInstance * fwInstance,
4441 + CK_ATTRIBUTE_PTR pTemplate,
4442 + CK_ULONG ulAttributeCount,
4443 + CK_RV * pError
4446 + plog("mdSession_FindObjectsInit\n");
4447 + return pem_FindObjectsInit(fwSession, pTemplate, ulAttributeCount,
4448 + pError);
4451 +static NSSCKMDObject *
4452 +pem_mdSession_CreateObject
4454 + NSSCKMDSession * mdSession,
4455 + NSSCKFWSession * fwSession,
4456 + NSSCKMDToken * mdToken,
4457 + NSSCKFWToken * fwToken,
4458 + NSSCKMDInstance * mdInstance,
4459 + NSSCKFWInstance * fwInstance,
4460 + NSSArena * arena,
4461 + CK_ATTRIBUTE_PTR pTemplate,
4462 + CK_ULONG ulAttributeCount,
4463 + CK_RV * pError
4466 + plog("mdSession_CreateObject\n");
4467 + return pem_CreateObject(fwInstance, fwSession, mdToken, pTemplate,
4468 + ulAttributeCount, pError);
4472 + * increase refCount of internal object(s)
4473 + */
4474 +NSSCKMDObject *
4475 +pem_mdSession_CopyObject
4477 + NSSCKMDSession * mdSession,
4478 + NSSCKFWSession * fwSession,
4479 + NSSCKMDToken * mdToken,
4480 + NSSCKFWToken * fwToken,
4481 + NSSCKMDInstance * mdInstance,
4482 + NSSCKFWInstance * fwInstance,
4483 + NSSCKMDObject * mdOldObject,
4484 + NSSCKFWObject * fwOldObject,
4485 + NSSArena * arena,
4486 + CK_ATTRIBUTE_PTR pTemplate,
4487 + CK_ULONG ulAttributeCount,
4488 + CK_RV * pError
4491 + NSSCKMDObject *rvmdObject = NULL;
4492 + pemInternalObject *io = (pemInternalObject *) mdOldObject->etc;
4494 + /* make a new mdObject */
4495 + rvmdObject = nss_ZNEW(arena, NSSCKMDObject);
4496 + if ((NSSCKMDObject *) NULL == rvmdObject) {
4497 + *pError = CKR_HOST_MEMORY;
4498 + return (NSSCKMDObject *) NULL;
4501 + if (NULL == io->list) {
4502 + io->refCount ++;
4503 + } else {
4504 + /* go through list of objects */
4505 + pemObjectListItem *item = io->list;
4506 + while (item) {
4507 + item->io->refCount ++;
4508 + item = item->next;
4511 + /* struct (shallow) copy the old one */
4512 + *rvmdObject = *mdOldObject;
4514 + return rvmdObject;
4517 +CK_RV
4518 +pem_mdSession_Login
4520 + NSSCKMDSession * mdSession,
4521 + NSSCKFWSession * fwSession,
4522 + NSSCKMDToken * mdToken,
4523 + NSSCKFWToken * fwToken,
4524 + NSSCKMDInstance * mdInstance,
4525 + NSSCKFWInstance * fwInstance,
4526 + CK_USER_TYPE userType,
4527 + NSSItem * pin,
4528 + CK_STATE oldState,
4529 + CK_STATE newState
4532 + NSSCKFWSlot *fwSlot;
4533 + CK_SLOT_ID slotID;
4534 + pemInternalObject *io = NULL;
4535 + unsigned char *iv = 0;
4536 + unsigned char mykey[32];
4537 + unsigned char *output = NULL;
4538 + DESContext *cx = NULL;
4539 + SECStatus rv;
4540 + unsigned int len = 0;
4541 + NSSLOWKEYPrivateKey *lpk = NULL;
4542 + PLArenaPool *arena;
4543 + SECItem plain;
4544 + int i;
4546 + fwSlot = NSSCKFWToken_GetFWSlot(fwToken);
4547 + slotID = nssCKFWSlot_GetSlotID(fwSlot);
4549 + arena = PORT_NewArena(2048);
4550 + if (!arena) {
4551 + return CKR_HOST_MEMORY;
4554 + plog("pem_mdSession_Login '%s'\n", (char *) pin->data);
4556 + token_needsLogin[slotID - 1] = PR_FALSE;
4558 + /* Find the right key object */
4559 + for (i = 0; i < pem_nobjs; i++) {
4560 + if (NULL == gobj[i])
4561 + continue;
4563 + if ((slotID == gobj[i]->slotID) && (gobj[i]->type == pemBareKey)) {
4564 + io = gobj[i];
4565 + break;
4569 + if (NULL == io) {
4570 + rv = CKR_SLOT_ID_INVALID;
4571 + goto loser;
4574 + /* Convert the IV from hex into an array of bytes */
4575 + iv = convert_iv(io->u.key.ivstring, 8);
4577 + /* Convert the PIN and IV into a DES key */
4578 + make_key(iv, pin->data, pin->size, mykey);
4580 + output =
4581 + (unsigned char *) nss_ZAlloc(NULL,
4582 + (io->u.key.key.privateKey->len + 1));
4583 + if (!output) {
4584 + rv = CKR_HOST_MEMORY;
4585 + goto loser;
4588 + cx = DES_CreateContext((const unsigned char *) mykey, iv,
4589 + io->u.key.cipher, PR_FALSE);
4590 + if (!cx) {
4591 + rv = CKR_HOST_MEMORY;
4592 + goto loser;
4595 + rv = DES_Decrypt(cx, output, &len, io->u.key.key.privateKey->len,
4596 + io->u.key.key.privateKey->data,
4597 + io->u.key.key.privateKey->len);
4598 + DES_DestroyContext(cx, PR_TRUE);
4600 + if (iv) {
4601 + free(iv);
4602 + iv = NULL;
4604 + if (rv != SECSuccess) {
4605 + rv = CKR_PIN_INCORRECT;
4606 + goto loser;
4609 + lpk = (NSSLOWKEYPrivateKey *) nss_ZAlloc(NULL,
4610 + sizeof (NSSLOWKEYPrivateKey));
4611 + if (lpk == NULL) {
4612 + rv = CKR_HOST_MEMORY;
4613 + goto loser;
4616 + lpk->arena = arena;
4617 + lpk->keyType = NSSLOWKEYRSAKey;
4618 + prepare_low_rsa_priv_key_for_asn1(lpk);
4621 + /* Decode the resulting blob and see if it is a decodable DER that fits
4622 + * our private key template. If so we declare success and move on. If not
4623 + * then we return an error.
4624 + */
4625 + memset(&plain, 0, sizeof(plain));
4626 + plain.data = output;
4627 + plain.len = len - output[len - 1];
4628 + rv = SEC_QuickDERDecodeItem(arena, lpk, pem_RSAPrivateKeyTemplate,
4629 + &plain);
4630 + pem_DestroyPrivateKey(lpk);
4631 + arena = NULL;
4632 + if (rv != SECSuccess)
4633 + goto loser;
4635 + nss_ZFreeIf(io->u.key.key.privateKey->data);
4636 + io->u.key.key.privateKey->len = len - output[len - 1];
4637 + io->u.key.key.privateKey->data =
4638 + (void *) nss_ZAlloc(NULL, io->u.key.key.privateKey->len);
4639 + memcpy(io->u.key.key.privateKey->data, output, len - output[len - 1]);
4641 + rv = CKR_OK;
4643 + loser:
4644 + if (arena)
4645 + PORT_FreeArena(arena, PR_FALSE);
4646 + if (iv)
4647 + free(iv);
4648 + nss_ZFreeIf(output);
4650 + return rv;
4653 +NSS_IMPLEMENT NSSCKMDSession *
4654 +pem_CreateSession
4656 + NSSCKFWSession * fwSession,
4657 + CK_RV * pError
4660 + NSSArena *arena;
4661 + NSSCKMDSession *rv;
4663 + plog("pem_CreateSession returning new session\n");
4664 + arena = NSSCKFWSession_GetArena(fwSession, pError);
4665 + if ((NSSArena *) NULL == arena) {
4666 + return (NSSCKMDSession *) NULL;
4669 + rv = nss_ZNEW(arena, NSSCKMDSession);
4670 + if ((NSSCKMDSession *) NULL == rv) {
4671 + *pError = CKR_HOST_MEMORY;
4672 + return (NSSCKMDSession *) NULL;
4675 + /*
4676 + * rv was zeroed when allocated, so we only
4677 + * need to set the non-zero members.
4678 + */
4680 + rv->etc = (void *) fwSession;
4681 + /* rv->Close */
4682 + /* rv->GetDeviceError */
4683 + rv->Login = pem_mdSession_Login;
4684 + /* rv->Logout */
4685 + /* rv->InitPIN */
4686 + /* rv->SetPIN */
4687 + /* rv->GetOperationStateLen */
4688 + /* rv->GetOperationState */
4689 + /* rv->SetOperationState */
4690 + rv->CreateObject = pem_mdSession_CreateObject;
4691 + rv->CopyObject = pem_mdSession_CopyObject;
4692 + rv->FindObjectsInit = pem_mdSession_FindObjectsInit;
4693 + /* rv->SeedRandom */
4694 + /* rv->GetRandom */
4695 + /* rv->null */
4697 + return rv;
4699 diff --git a/a/nss/lib/ckfw/pem/pslot.c b/b/nss/lib/ckfw/pem/pslot.c
4700 new file mode 100644
4701 index 0000000..2f9901b
4702 --- /dev/null
4703 +++ b/b/nss/lib/ckfw/pem/pslot.c
4704 @@ -0,0 +1,183 @@
4705 +/* ***** BEGIN LICENSE BLOCK *****
4706 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4708 + * The contents of this file are subject to the Mozilla Public License Version
4709 + * 1.1 (the "License"); you may not use this file except in compliance with
4710 + * the License. You may obtain a copy of the License at
4711 + * http://www.mozilla.org/MPL/
4713 + * Software distributed under the License is distributed on an "AS IS" basis,
4714 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
4715 + * for the specific language governing rights and limitations under the
4716 + * License.
4718 + * The Original Code is the Netscape security libraries.
4720 + * The Initial Developer of the Original Code is
4721 + * Netscape Communications Corporation.
4722 + * Portions created by the Initial Developer are Copyright (C) 1994-2000
4723 + * the Initial Developer. All Rights Reserved.
4725 + * Contributor(s):
4726 + * Rob Crittenden (rcritten@redhat.com)
4728 + * Alternatively, the contents of this file may be used under the terms of
4729 + * either the GNU General Public License Version 2 or later (the "GPL"), or
4730 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
4731 + * in which case the provisions of the GPL or the LGPL are applicable instead
4732 + * of those above. If you wish to allow use of your version of this file only
4733 + * under the terms of either the GPL or the LGPL, and not to allow others to
4734 + * use your version of this file under the terms of the MPL, indicate your
4735 + * decision by deleting the provisions above and replace them with the notice
4736 + * and other provisions required by the GPL or the LGPL. If you do not delete
4737 + * the provisions above, a recipient may use your version of this file under
4738 + * the terms of any one of the MPL, the GPL or the LGPL.
4740 + * ***** END LICENSE BLOCK ***** */
4742 +#include "ckpem.h"
4743 +#include "prprf.h"
4746 + * pslot.c
4748 + * This file implements the NSSCKMDSlot object for the
4749 + * "PEM objects" cryptoki module.
4750 + */
4752 +static NSSUTF8 *
4753 +pem_mdSlot_GetSlotDescription
4755 + NSSCKMDSlot * mdSlot,
4756 + NSSCKFWSlot * fwSlot,
4757 + NSSCKMDInstance * mdInstance,
4758 + NSSCKFWInstance * fwInstance,
4759 + CK_RV * pError
4762 + CK_SLOT_ID slotID;
4763 + NSSArena *arena;
4764 + char *slotid;
4766 + arena = NSSCKFWInstance_GetArena(fwInstance, pError);
4767 + slotID = nssCKFWSlot_GetSlotID(fwSlot);
4769 + slotid = (char *) nss_ZAlloc(arena, 256);
4770 + PR_snprintf(slotid, 256, "PEM Slot #%ld", slotID);
4772 + return (NSSUTF8 *) slotid;
4775 +static NSSUTF8 *
4776 +pem_mdSlot_GetManufacturerID
4778 + NSSCKMDSlot * mdSlot,
4779 + NSSCKFWSlot * fwSlot,
4780 + NSSCKMDInstance * mdInstance,
4781 + NSSCKFWInstance * fwInstance,
4782 + CK_RV * pError
4785 + return (NSSUTF8 *) pem_ManufacturerID;
4788 +static CK_VERSION
4789 +pem_mdSlot_GetHardwareVersion
4791 + NSSCKMDSlot * mdSlot,
4792 + NSSCKFWSlot * fwSlot,
4793 + NSSCKMDInstance * mdInstance,
4794 + NSSCKFWInstance * fwInstance
4797 + return pem_HardwareVersion;
4800 +static CK_VERSION
4801 +pem_mdSlot_GetFirmwareVersion
4803 + NSSCKMDSlot * mdSlot,
4804 + NSSCKFWSlot * fwSlot,
4805 + NSSCKMDInstance * mdInstance,
4806 + NSSCKFWInstance * fwInstance
4809 + return pem_FirmwareVersion;
4812 +static NSSCKMDToken *
4813 +pem_mdSlot_GetToken
4815 + NSSCKMDSlot * mdSlot,
4816 + NSSCKFWSlot * fwSlot,
4817 + NSSCKMDInstance * mdInstance,
4818 + NSSCKFWInstance * fwInstance,
4819 + CK_RV * pError
4822 + return (NSSCKMDToken *) mdSlot->etc;
4825 +CK_BBOOL
4826 +pem_mdSlot_GetRemovableDevice
4828 + NSSCKMDSlot * mdSlot,
4829 + NSSCKFWSlot * fwSlot,
4830 + NSSCKMDInstance * mdInstance,
4831 + NSSCKFWInstance * fwInstance
4834 + return CK_TRUE;
4837 +NSSCKMDSlot *
4838 +pem_NewSlot
4840 + NSSCKFWInstance * fwInstance,
4841 + CK_RV * pError
4844 + NSSArena *arena;
4845 + NSSCKMDSlot *mdSlot;
4847 + plog("pem_NewSlot\n");
4848 + arena = NSSCKFWInstance_GetArena(fwInstance, pError);
4849 + if ((NSSArena *) NULL == arena) {
4850 + if (CKR_OK == *pError) {
4851 + *pError = CKR_GENERAL_ERROR;
4855 + mdSlot = nss_ZNEW(arena, NSSCKMDSlot);
4856 + if ((NSSCKMDSlot *) NULL == mdSlot) {
4857 + *pError = CKR_HOST_MEMORY;
4858 + return (NSSCKMDSlot *) NULL;
4861 + mdSlot->etc = pem_NewToken(fwInstance, pError);
4863 + mdSlot->GetSlotDescription = pem_mdSlot_GetSlotDescription;
4864 + mdSlot->GetManufacturerID = pem_mdSlot_GetManufacturerID;
4865 + mdSlot->GetHardwareVersion = pem_mdSlot_GetHardwareVersion;
4866 + mdSlot->GetFirmwareVersion = pem_mdSlot_GetFirmwareVersion;
4867 + mdSlot->GetRemovableDevice = pem_mdSlot_GetRemovableDevice;
4868 + mdSlot->GetToken = pem_mdSlot_GetToken;
4870 + return mdSlot;
4873 +NSS_IMPLEMENT_DATA const NSSCKMDSlot
4874 +pem_mdSlot = {
4875 + (void *) NULL, /* etc */
4876 + NULL, /* Initialize */
4877 + NULL, /* Destroy */
4878 + pem_mdSlot_GetSlotDescription,
4879 + pem_mdSlot_GetManufacturerID,
4880 + NULL, /* GetTokenPresent -- defaults to true */
4881 + pem_mdSlot_GetRemovableDevice,
4882 + NULL, /* GetHardwareSlot -- defaults to false */
4883 + pem_mdSlot_GetHardwareVersion,
4884 + pem_mdSlot_GetFirmwareVersion,
4885 + pem_mdSlot_GetToken,
4886 + (void *) NULL /* null terminator */
4888 diff --git a/a/nss/lib/ckfw/pem/ptoken.c b/b/nss/lib/ckfw/pem/ptoken.c
4889 new file mode 100644
4890 index 0000000..6c35b21
4891 --- /dev/null
4892 +++ b/b/nss/lib/ckfw/pem/ptoken.c
4893 @@ -0,0 +1,334 @@
4894 +/* ***** BEGIN LICENSE BLOCK *****
4895 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4897 + * The contents of this file are subject to the Mozilla Public License Version
4898 + * 1.1 (the "License"); you may not use this file except in compliance with
4899 + * the License. You may obtain a copy of the License at
4900 + * http://www.mozilla.org/MPL/
4902 + * Software distributed under the License is distributed on an "AS IS" basis,
4903 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
4904 + * for the specific language governing rights and limitations under the
4905 + * License.
4907 + * The Original Code is the Netscape security libraries.
4909 + * The Initial Developer of the Original Code is
4910 + * Netscape Communications Corporation.
4911 + * Portions created by the Initial Developer are Copyright (C) 1994-2000
4912 + * the Initial Developer. All Rights Reserved.
4914 + * Contributor(s):
4915 + * Rob Crittenden (rcritten@redhat.com)
4917 + * Alternatively, the contents of this file may be used under the terms of
4918 + * either the GNU General Public License Version 2 or later (the "GPL"), or
4919 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
4920 + * in which case the provisions of the GPL or the LGPL are applicable instead
4921 + * of those above. If you wish to allow use of your version of this file only
4922 + * under the terms of either the GPL or the LGPL, and not to allow others to
4923 + * use your version of this file under the terms of the MPL, indicate your
4924 + * decision by deleting the provisions above and replace them with the notice
4925 + * and other provisions required by the GPL or the LGPL. If you do not delete
4926 + * the provisions above, a recipient may use your version of this file under
4927 + * the terms of any one of the MPL, the GPL or the LGPL.
4929 + * ***** END LICENSE BLOCK ***** */
4931 +#include "ckpem.h"
4932 +#include "prprf.h"
4935 + * ptoken.c
4937 + * This file implements the NSSCKMDToken object for the
4938 + * "PEM objects" cryptoki module.
4939 + */
4941 +NSS_EXTERN_DATA int token_needsLogin[NUM_SLOTS];
4943 +static NSSUTF8 *
4944 +pem_mdToken_GetLabel
4946 + NSSCKMDToken * mdToken,
4947 + NSSCKFWToken * fwToken,
4948 + NSSCKMDInstance * mdInstance,
4949 + NSSCKFWInstance * fwInstance,
4950 + CK_RV * pError
4953 + NSSCKFWSlot *fwSlot;
4954 + CK_SLOT_ID slotID;
4955 + NSSArena *arena;
4956 + char *tokenid;
4958 + arena = NSSCKFWInstance_GetArena(fwInstance, pError);
4959 + fwSlot = NSSCKFWToken_GetFWSlot(fwToken);
4960 + slotID = nssCKFWSlot_GetSlotID(fwSlot);
4962 + tokenid = (char *) nss_ZAlloc(arena, 256);
4963 + PR_snprintf(tokenid, 256, "PEM Token #%ld", slotID);
4965 + return (NSSUTF8 *) tokenid;
4968 +static NSSUTF8 *
4969 +pem_mdToken_GetManufacturerID
4971 + NSSCKMDToken * mdToken,
4972 + NSSCKFWToken * fwToken,
4973 + NSSCKMDInstance * mdInstance,
4974 + NSSCKFWInstance * fwInstance,
4975 + CK_RV * pError
4978 + return (NSSUTF8 *) pem_ManufacturerID;
4981 +static NSSUTF8 *
4982 +pem_mdToken_GetModel
4984 + NSSCKMDToken * mdToken,
4985 + NSSCKFWToken * fwToken,
4986 + NSSCKMDInstance * mdInstance,
4987 + NSSCKFWInstance * fwInstance,
4988 + CK_RV * pError
4991 + return (NSSUTF8 *) pem_TokenModel;
4994 +static NSSUTF8 *
4995 +pem_mdToken_GetSerialNumber
4997 + NSSCKMDToken * mdToken,
4998 + NSSCKFWToken * fwToken,
4999 + NSSCKMDInstance * mdInstance,
5000 + NSSCKFWInstance * fwInstance,
5001 + CK_RV * pError
5004 + return (NSSUTF8 *) pem_TokenSerialNumber;
5007 +static CK_BBOOL
5008 +pem_mdToken_GetIsWriteProtected
5010 + NSSCKMDToken * mdToken,
5011 + NSSCKFWToken * fwToken,
5012 + NSSCKMDInstance * mdInstance,
5013 + NSSCKFWInstance * fwInstance
5016 + return CK_TRUE;
5019 +static CK_VERSION
5020 +pem_mdToken_GetHardwareVersion
5022 + NSSCKMDToken * mdToken,
5023 + NSSCKFWToken * fwToken,
5024 + NSSCKMDInstance * mdInstance,
5025 + NSSCKFWInstance * fwInstance
5028 + return pem_HardwareVersion;
5031 +static CK_VERSION
5032 +pem_mdToken_GetFirmwareVersion
5034 + NSSCKMDToken * mdToken,
5035 + NSSCKFWToken * fwToken,
5036 + NSSCKMDInstance * mdInstance,
5037 + NSSCKFWInstance * fwInstance
5040 + return pem_FirmwareVersion;
5043 +static NSSCKMDSession *pem_mdToken_OpenSession
5045 + NSSCKMDToken * mdToken,
5046 + NSSCKFWToken * fwToken,
5047 + NSSCKMDInstance * mdInstance,
5048 + NSSCKFWInstance * fwInstance,
5049 + NSSCKFWSession * fwSession,
5050 + CK_BBOOL rw,
5051 + CK_RV * pError
5054 + plog("pem_mdToken_OpenSession\n");
5055 + return pem_CreateSession(fwSession, pError);
5058 +static CK_ULONG
5059 +pem_mdToken_GetMechanismCount
5061 + NSSCKMDToken * mdToken,
5062 + NSSCKFWToken * fwToken,
5063 + NSSCKMDInstance * mdInstance,
5064 + NSSCKFWInstance * fwInstance
5067 + return (CK_ULONG) 1;
5070 +static CK_RV
5071 +pem_mdToken_GetMechanismTypes
5073 + NSSCKMDToken * mdToken,
5074 + NSSCKFWToken * fwToken,
5075 + NSSCKMDInstance * mdInstance,
5076 + NSSCKFWInstance * fwInstance,
5077 + CK_MECHANISM_TYPE types[]
5080 + types[0] = CKM_RSA_PKCS;
5081 + return CKR_OK;
5084 +static NSSCKMDMechanism *
5085 +pem_mdToken_GetMechanism
5087 + NSSCKMDToken * mdToken,
5088 + NSSCKFWToken * fwToken,
5089 + NSSCKMDInstance * mdInstance,
5090 + NSSCKFWInstance * fwInstance,
5091 + CK_MECHANISM_TYPE which,
5092 + CK_RV * pError
5095 + if (which != CKM_RSA_PKCS) {
5096 + *pError = CKR_MECHANISM_INVALID;
5097 + return (NSSCKMDMechanism *) NULL;
5099 + return (NSSCKMDMechanism *) & pem_mdMechanismRSA;
5102 +static CK_BBOOL
5103 +pem_mdToken_GetUserPinInitialized
5105 + NSSCKMDToken * mdToken,
5106 + NSSCKFWToken * fwToken,
5107 + NSSCKMDInstance * mdInstance,
5108 + NSSCKFWInstance * fwInstance
5111 + plog("pem_mdToken_GetUserPinInitialized: always TRUE\n");
5112 + return CK_TRUE;
5115 +static CK_BBOOL
5116 +pem_mdToken_GetLoginRequired
5118 + NSSCKMDToken * mdToken,
5119 + NSSCKFWToken * fwToken,
5120 + NSSCKMDInstance * mdInstance,
5121 + NSSCKFWInstance * fwInstance
5124 + char *label;
5125 + CK_RV pError;
5126 + NSSCKFWSlot *fwSlot;
5127 + CK_SLOT_ID slotID;
5129 + fwSlot = NSSCKFWToken_GetFWSlot(fwToken);
5130 + slotID = nssCKFWSlot_GetSlotID(fwSlot);
5132 + label = pem_mdToken_GetLabel(mdToken, fwToken, mdInstance, fwInstance,
5133 + &pError);
5135 + plog("pem_mdToken_GetLoginRequired %s: %d\n", label,
5136 + token_needsLogin[slotID - 1]);
5138 + if (token_needsLogin[slotID - 1] == PR_TRUE)
5139 + return CK_TRUE;
5140 + else
5141 + return CK_FALSE;
5144 +NSSCKMDToken *
5145 +pem_NewToken
5147 + NSSCKFWInstance * fwInstance,
5148 + CK_RV * pError
5151 + NSSArena *arena;
5152 + NSSCKMDToken *mdToken;
5153 + pemToken *token;
5155 + arena = NSSCKFWInstance_GetArena(fwInstance, pError);
5156 + if ((NSSArena *) NULL == arena) {
5157 + if (CKR_OK == *pError) {
5158 + *pError = CKR_GENERAL_ERROR;
5162 + mdToken = nss_ZNEW(arena, NSSCKMDToken);
5163 + if ((NSSCKMDToken *) NULL == mdToken) {
5164 + *pError = CKR_HOST_MEMORY;
5165 + return (NSSCKMDToken *) NULL;
5168 + token = nss_ZNEW(arena, struct pemTokenStr);
5169 + if ((struct pemTokenStr *) NULL == token) {
5170 + *pError = CKR_HOST_MEMORY;
5171 + return (NSSCKMDToken *) NULL;
5174 + mdToken->etc = (void *) token;
5175 + mdToken->GetLabel = pem_mdToken_GetLabel;
5176 + mdToken->GetManufacturerID = pem_mdToken_GetManufacturerID;
5177 + mdToken->GetModel = pem_mdToken_GetModel;
5178 + mdToken->GetSerialNumber = pem_mdToken_GetSerialNumber;
5179 + mdToken->GetIsWriteProtected = pem_mdToken_GetIsWriteProtected;
5180 + mdToken->GetLoginRequired = pem_mdToken_GetLoginRequired;
5181 + mdToken->GetUserPinInitialized = pem_mdToken_GetUserPinInitialized;
5182 + mdToken->GetHardwareVersion = pem_mdToken_GetHardwareVersion;
5183 + mdToken->GetFirmwareVersion = pem_mdToken_GetFirmwareVersion;
5184 + mdToken->OpenSession = pem_mdToken_OpenSession;
5185 + mdToken->GetMechanismCount = pem_mdToken_GetMechanismCount;
5186 + mdToken->GetMechanismTypes = pem_mdToken_GetMechanismTypes;
5187 + mdToken->GetMechanism = pem_mdToken_GetMechanism;
5189 + return mdToken;
5192 +#if 0
5193 +NSS_IMPLEMENT_DATA const NSSCKMDToken pem_mdToken = {
5194 + (void *) NULL, /* etc */
5195 + NULL, /* Setup */
5196 + NULL, /* Invalidate */
5197 + NULL, /* InitToken -- default errs */
5198 + pem_mdToken_GetLabel,
5199 + pem_mdToken_GetManufacturerID,
5200 + pem_mdToken_GetModel,
5201 + pem_mdToken_GetSerialNumber,
5202 + NULL, /* GetHasRNG -- default is false */
5203 + pem_mdToken_GetIsWriteProtected,
5204 + pem_mdToken_GetLoginRequired,
5205 + pem_mdToken_GetUserPinInitialized,
5206 + NULL, /* GetRestoreKeyNotNeeded -- irrelevant */
5207 + NULL, /* GetHasClockOnToken -- default is false */
5208 + NULL, /* GetHasProtectedAuthenticationPath -- default is false */
5209 + NULL, /* GetSupportsDualCryptoOperations -- default is false */
5210 + NULL, /* GetMaxSessionCount -- default is CK_UNAVAILABLE_INFORMATION */
5211 + NULL, /* GetMaxRwSessionCount -- default is CK_UNAVAILABLE_INFORMATION */
5212 + NULL, /* GetMaxPinLen -- irrelevant */
5213 + NULL, /* GetMinPinLen -- irrelevant */
5214 + NULL, /* GetTotalPublicMemory -- default is CK_UNAVAILABLE_INFORMATION */
5215 + NULL, /* GetFreePublicMemory -- default is CK_UNAVAILABLE_INFORMATION */
5216 + NULL, /* GetTotalPrivateMemory -- default is CK_UNAVAILABLE_INFORMATION */
5217 + NULL, /* GetFreePrivateMemory -- default is CK_UNAVAILABLE_INFORMATION */
5218 + pem_mdToken_GetHardwareVersion,
5219 + pem_mdToken_GetFirmwareVersion,
5220 + NULL, /* GetUTCTime -- no clock */
5221 + pem_mdToken_OpenSession,
5222 + pem_mdToken_GetMechanismCount,
5223 + pem_mdToken_GetMechanismTypes,
5224 + pem_mdToken_GetMechanism,
5225 + (void *) NULL /* null terminator */
5227 +#endif
5228 diff --git a/a/nss/lib/ckfw/pem/rsawrapr.c b/b/nss/lib/ckfw/pem/rsawrapr.c
5229 new file mode 100644
5230 index 0000000..1179f2a
5231 --- /dev/null
5232 +++ b/b/nss/lib/ckfw/pem/rsawrapr.c
5233 @@ -0,0 +1,823 @@
5235 + * PKCS#1 encoding and decoding functions.
5236 + * This file is believed to contain no code licensed from other parties.
5238 + * ***** BEGIN LICENSE BLOCK *****
5239 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5241 + * The contents of this file are subject to the Mozilla Public License Version
5242 + * 1.1 (the "License"); you may not use this file except in compliance with
5243 + * the License. You may obtain a copy of the License at
5244 + * http://www.mozilla.org/MPL/
5246 + * Software distributed under the License is distributed on an "AS IS" basis,
5247 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
5248 + * for the specific language governing rights and limitations under the
5249 + * License.
5251 + * The Original Code is the Netscape security libraries.
5253 + * The Initial Developer of the Original Code is
5254 + * Netscape Communications Corporation.
5255 + * Portions created by the Initial Developer are Copyright (C) 1994-2000
5256 + * the Initial Developer. All Rights Reserved.
5258 + * Contributor(s):
5259 + * Rob Crittenden (rcritten@redhat.com)
5261 + * Alternatively, the contents of this file may be used under the terms of
5262 + * either the GNU General Public License Version 2 or later (the "GPL"), or
5263 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
5264 + * in which case the provisions of the GPL or the LGPL are applicable instead
5265 + * of those above. If you wish to allow use of your version of this file only
5266 + * under the terms of either the GPL or the LGPL, and not to allow others to
5267 + * use your version of this file under the terms of the MPL, indicate your
5268 + * decision by deleting the provisions above and replace them with the notice
5269 + * and other provisions required by the GPL or the LGPL. If you do not delete
5270 + * the provisions above, a recipient may use your version of this file under
5271 + * the terms of any one of the MPL, the GPL or the LGPL.
5273 + * ***** END LICENSE BLOCK ***** */
5274 +/* $Id: $ */
5276 +#include "ckpem.h"
5277 +#include "blapi.h"
5278 +#include "softoken.h"
5279 +#include "sechash.h"
5280 +#include "base.h"
5282 +#include "secerr.h"
5284 +#define RSA_BLOCK_MIN_PAD_LEN 8
5285 +#define RSA_BLOCK_FIRST_OCTET 0x00
5286 +#define RSA_BLOCK_PRIVATE0_PAD_OCTET 0x00
5287 +#define RSA_BLOCK_PRIVATE_PAD_OCTET 0xff
5288 +#define RSA_BLOCK_AFTER_PAD_OCTET 0x00
5290 +#define OAEP_SALT_LEN 8
5291 +#define OAEP_PAD_LEN 8
5292 +#define OAEP_PAD_OCTET 0x00
5294 +#define FLAT_BUFSIZE 512 /* bytes to hold flattened SHA1Context. */
5296 +unsigned
5297 +pem_PublicModulusLen(NSSLOWKEYPublicKey *pubk)
5299 + unsigned char b0;
5301 + /* interpret modulus length as key strength... in
5302 + * fortezza that's the public key length */
5304 + switch (pubk->keyType) {
5305 + case pemLOWKEYRSAKey:
5306 + b0 = pubk->u.rsa.modulus.data[0];
5307 + return b0 ? pubk->u.rsa.modulus.len : pubk->u.rsa.modulus.len - 1;
5308 + default:
5309 + break;
5311 + return 0;
5314 +static SHA1Context *SHA1_CloneContext(SHA1Context * original)
5316 + SHA1Context *clone = NULL;
5317 + unsigned char *pBuf;
5318 + int sha1ContextSize = SHA1_FlattenSize(original);
5319 + SECStatus frv;
5320 + unsigned char buf[FLAT_BUFSIZE];
5322 + PORT_Assert(sizeof buf >= sha1ContextSize);
5323 + if (sizeof buf >= sha1ContextSize) {
5324 + pBuf = buf;
5325 + } else {
5326 + pBuf = nss_ZAlloc(NULL, sha1ContextSize);
5327 + if (!pBuf)
5328 + goto done;
5331 + frv = SHA1_Flatten(original, pBuf);
5332 + if (frv == SECSuccess) {
5333 + clone = SHA1_Resurrect(pBuf, NULL);
5334 + memset(pBuf, 0, sha1ContextSize);
5336 + done:
5337 + if (pBuf != buf)
5338 + nss_ZFreeIf(pBuf);
5339 + return clone;
5343 + * Modify data by XORing it with a special hash of salt.
5344 + */
5345 +static SECStatus
5346 +oaep_xor_with_h1(unsigned char *data, unsigned int datalen,
5347 + unsigned char *salt, unsigned int saltlen)
5349 + SHA1Context *sha1cx;
5350 + unsigned char *dp, *dataend;
5351 + unsigned char end_octet;
5353 + sha1cx = SHA1_NewContext();
5354 + if (sha1cx == NULL) {
5355 + return SECFailure;
5358 + /*
5359 + * Get a hash of salt started; we will use it several times,
5360 + * adding in a different end octet (x00, x01, x02, ...).
5361 + */
5362 + SHA1_Begin(sha1cx);
5363 + SHA1_Update(sha1cx, salt, saltlen);
5364 + end_octet = 0;
5366 + dp = data;
5367 + dataend = data + datalen;
5369 + while (dp < dataend) {
5370 + SHA1Context *sha1cx_h1;
5371 + unsigned int sha1len, sha1off;
5372 + unsigned char sha1[SHA1_LENGTH];
5374 + /*
5375 + * Create hash of (salt || end_octet)
5376 + */
5377 + sha1cx_h1 = SHA1_CloneContext(sha1cx);
5378 + SHA1_Update(sha1cx_h1, &end_octet, 1);
5379 + SHA1_End(sha1cx_h1, sha1, &sha1len, sizeof(sha1));
5380 + SHA1_DestroyContext(sha1cx_h1, PR_TRUE);
5381 + PORT_Assert(sha1len == SHA1_LENGTH);
5383 + /*
5384 + * XOR that hash with the data.
5385 + * When we have fewer than SHA1_LENGTH octets of data
5386 + * left to xor, use just the low-order ones of the hash.
5387 + */
5388 + sha1off = 0;
5389 + if ((dataend - dp) < SHA1_LENGTH)
5390 + sha1off = SHA1_LENGTH - (dataend - dp);
5391 + while (sha1off < SHA1_LENGTH)
5392 + *dp++ ^= sha1[sha1off++];
5394 + /*
5395 + * Bump for next hash chunk.
5396 + */
5397 + end_octet++;
5400 + SHA1_DestroyContext(sha1cx, PR_TRUE);
5401 + return SECSuccess;
5405 + * Modify salt by XORing it with a special hash of data.
5406 + */
5407 +static SECStatus
5408 +oaep_xor_with_h2(unsigned char *salt, unsigned int saltlen,
5409 + unsigned char *data, unsigned int datalen)
5411 + unsigned char sha1[SHA1_LENGTH];
5412 + unsigned char *psalt, *psha1, *saltend;
5413 + SECStatus rv;
5415 + /*
5416 + * Create a hash of data.
5417 + */
5418 + rv = SHA1_HashBuf(sha1, data, datalen);
5419 + if (rv != SECSuccess) {
5420 + return rv;
5423 + /*
5424 + * XOR the low-order octets of that hash with salt.
5425 + */
5426 + PORT_Assert(saltlen <= SHA1_LENGTH);
5427 + saltend = salt + saltlen;
5428 + psalt = salt;
5429 + psha1 = sha1 + SHA1_LENGTH - saltlen;
5430 + while (psalt < saltend) {
5431 + *psalt++ ^= *psha1++;
5434 + return SECSuccess;
5438 + * RSA block types
5440 + * The actual values are important -- they are fixed, *not* arbitrary.
5441 + * The explicit value assignments are not needed (because C would give
5442 + * us those same values anyway) but are included as a reminder...
5443 + */
5444 +typedef enum {
5445 + RSA_BlockPrivate0 = 0, /* unused, really */
5446 + RSA_BlockPrivate = 1, /* pad for a private-key operation */
5447 + RSA_BlockPublic = 2, /* pad for a public-key operation */
5448 + RSA_BlockRaw = 4, /* simply justify the block appropriately */
5449 + RSA_BlockTotal
5450 +} RSA_BlockType;
5453 + * Format one block of data for public/private key encryption using
5454 + * the rules defined in PKCS #1.
5455 + */
5456 +static unsigned char *rsa_FormatOneBlock(unsigned modulusLen,
5457 + RSA_BlockType blockType,
5458 + SECItem * data)
5460 + unsigned char *block;
5461 + unsigned char *bp;
5462 + int padLen;
5463 + int i;
5464 + SECStatus rv;
5466 + block = (unsigned char *) nss_ZAlloc(NULL, modulusLen);
5467 + if (block == NULL)
5468 + return NULL;
5470 + bp = block;
5472 + /*
5473 + * All RSA blocks start with two octets:
5474 + * 0x00 || BlockType
5475 + */
5476 + *bp++ = RSA_BLOCK_FIRST_OCTET;
5477 + *bp++ = (unsigned char) blockType;
5479 + switch (blockType) {
5481 + /*
5482 + * Blocks intended for private-key operation.
5483 + */
5484 + case RSA_BlockPrivate: /* preferred method */
5485 + /*
5486 + * 0x00 || BT || Pad || 0x00 || ActualData
5487 + * 1 1 padLen 1 data->len
5488 + * Pad is either all 0x00 or all 0xff bytes, depending on blockType.
5489 + */
5490 + padLen = modulusLen - data->len - 3;
5491 + PORT_Assert(padLen >= RSA_BLOCK_MIN_PAD_LEN);
5492 + if (padLen < RSA_BLOCK_MIN_PAD_LEN) {
5493 + nss_ZFreeIf(block);
5494 + return NULL;
5496 + nsslibc_memset(bp, RSA_BLOCK_PRIVATE_PAD_OCTET, padLen);
5497 + bp += padLen;
5498 + *bp++ = RSA_BLOCK_AFTER_PAD_OCTET;
5499 + nsslibc_memcpy(bp, data->data, data->len);
5500 + break;
5502 + /*
5503 + * Blocks intended for public-key operation.
5504 + */
5505 + case RSA_BlockPublic:
5507 + /*
5508 + * 0x00 || BT || Pad || 0x00 || ActualData
5509 + * 1 1 padLen 1 data->len
5510 + * Pad is all non-zero random bytes.
5511 + */
5512 + padLen = modulusLen - data->len - 3;
5513 + PORT_Assert(padLen >= RSA_BLOCK_MIN_PAD_LEN);
5514 + if (padLen < RSA_BLOCK_MIN_PAD_LEN) {
5515 + nss_ZFreeIf(block);
5516 + return NULL;
5518 + for (i = 0; i < padLen; i++) {
5519 + /* Pad with non-zero random data. */
5520 + do {
5521 + rv = RNG_GenerateGlobalRandomBytes(bp + i, 1);
5522 + } while (rv == SECSuccess
5523 + && bp[i] == RSA_BLOCK_AFTER_PAD_OCTET);
5524 + if (rv != SECSuccess) {
5525 + nss_ZFreeIf(block);
5526 + return NULL;
5529 + bp += padLen;
5530 + *bp++ = RSA_BLOCK_AFTER_PAD_OCTET;
5531 + nsslibc_memcpy(bp, data->data, data->len);
5533 + break;
5535 + default:
5536 + PORT_Assert(0);
5537 + nss_ZFreeIf(block);
5538 + return NULL;
5541 + return block;
5544 +static SECStatus
5545 +rsa_FormatBlock(SECItem * result, unsigned modulusLen,
5546 + RSA_BlockType blockType, SECItem * data)
5548 + /*
5549 + * XXX For now assume that the data length fits in a single
5550 + * XXX encryption block; the ASSERTs below force this.
5551 + * XXX To fix it, each case will have to loop over chunks whose
5552 + * XXX lengths satisfy the assertions, until all data is handled.
5553 + * XXX (Unless RSA has more to say about how to handle data
5554 + * XXX which does not fit in a single encryption block?)
5555 + * XXX And I do not know what the result is supposed to be,
5556 + * XXX so the interface to this function may need to change
5557 + * XXX to allow for returning multiple blocks, if they are
5558 + * XXX not wanted simply concatenated one after the other.
5559 + */
5561 + switch (blockType) {
5562 + case RSA_BlockPrivate:
5563 + case RSA_BlockPublic:
5564 + /*
5565 + * 0x00 || BT || Pad || 0x00 || ActualData
5567 + * The "3" below is the first octet + the second octet + the 0x00
5568 + * octet that always comes just before the ActualData.
5569 + */
5570 + PORT_Assert(data->len <=
5571 + (modulusLen - (3 + RSA_BLOCK_MIN_PAD_LEN)));
5573 + result->data = rsa_FormatOneBlock(modulusLen, blockType, data);
5574 + if (result->data == NULL) {
5575 + result->len = 0;
5576 + return SECFailure;
5578 + result->len = modulusLen;
5580 + break;
5582 + case RSA_BlockRaw:
5583 + /*
5584 + * Pad || ActualData
5585 + * Pad is zeros. The application is responsible for recovering
5586 + * the actual data.
5587 + */
5588 + if (data->len > modulusLen) {
5589 + return SECFailure;
5591 + result->data = (unsigned char *) nss_ZAlloc(NULL, modulusLen);
5592 + result->len = modulusLen;
5593 + nsslibc_memcpy(result->data + (modulusLen - data->len), data->data,
5594 + data->len);
5595 + break;
5597 + default:
5598 + PORT_Assert(0);
5599 + result->data = NULL;
5600 + result->len = 0;
5601 + return SECFailure;
5604 + return SECSuccess;
5607 +/* XXX Doesn't set error code */
5608 +SECStatus
5609 +pem_RSA_Sign(pemLOWKEYPrivateKey * key,
5610 + unsigned char *output,
5611 + unsigned int *output_len,
5612 + unsigned int maxOutputLen,
5613 + unsigned char *input, unsigned int input_len)
5615 + SECStatus rv = SECSuccess;
5616 + unsigned int modulus_len = pem_PrivateModulusLen(key);
5617 + SECItem formatted;
5618 + SECItem unformatted;
5620 + if (maxOutputLen < modulus_len)
5621 + return SECFailure;
5622 + PORT_Assert(key->keyType == pemLOWKEYRSAKey);
5623 + if (key->keyType != pemLOWKEYRSAKey)
5624 + return SECFailure;
5626 + unformatted.len = input_len;
5627 + unformatted.data = input;
5628 + formatted.data = NULL;
5629 + rv = rsa_FormatBlock(&formatted, modulus_len, RSA_BlockPrivate,
5630 + &unformatted);
5631 + if (rv != SECSuccess)
5632 + goto done;
5634 + rv = RSA_PrivateKeyOpDoubleChecked(&key->u.rsa, output,
5635 + formatted.data);
5636 + *output_len = modulus_len;
5638 + goto done;
5640 + done:
5641 + if (formatted.data != NULL)
5642 + nss_ZFreeIf(formatted.data);
5643 + return rv;
5646 +#if 0
5647 +/* XXX Doesn't set error code */
5648 +SECStatus
5649 +RSA_CheckSign(NSSLOWKEYPublicKey * key,
5650 + unsigned char *sign,
5651 + unsigned int sign_len,
5652 + unsigned char *hash, unsigned int hash_len)
5654 + SECStatus rv;
5655 + unsigned int modulus_len = pem_PublicModulusLen(key);
5656 + unsigned int i;
5657 + unsigned char *buffer;
5659 + modulus_len = pem_PublicModulusLen(key);
5660 + if (sign_len != modulus_len)
5661 + goto failure;
5662 + /*
5663 + * 0x00 || BT || Pad || 0x00 || ActualData
5665 + * The "3" below is the first octet + the second octet + the 0x00
5666 + * octet that always comes just before the ActualData.
5667 + */
5668 + if (hash_len > modulus_len - (3 + RSA_BLOCK_MIN_PAD_LEN))
5669 + goto failure;
5670 + PORT_Assert(key->keyType == pemLOWKEYRSAKey);
5671 + if (key->keyType != pemLOWKEYRSAKey)
5672 + goto failure;
5674 + buffer = (unsigned char *) nss_ZAlloc(NULL, modulus_len + 1);
5675 + if (!buffer)
5676 + goto failure;
5678 + rv = RSA_PublicKeyOp(&key->u.rsa, buffer, sign);
5679 + if (rv != SECSuccess)
5680 + goto loser;
5682 + /*
5683 + * check the padding that was used
5684 + */
5685 + if (buffer[0] != 0 || buffer[1] != 1)
5686 + goto loser;
5687 + for (i = 2; i < modulus_len - hash_len - 1; i++) {
5688 + if (buffer[i] != 0xff)
5689 + goto loser;
5691 + if (buffer[i] != 0)
5692 + goto loser;
5694 + /*
5695 + * make sure we get the same results
5696 + */
5697 + if (memcmp(buffer + modulus_len - hash_len, hash, hash_len) != 0)
5698 + goto loser;
5700 + nss_ZFreeIf(buffer);
5701 + return SECSuccess;
5703 + loser:
5704 + nss_ZFreeIf(buffer);
5705 + failure:
5706 + return SECFailure;
5709 +/* XXX Doesn't set error code */
5710 +SECStatus
5711 +RSA_CheckSignRecover(NSSLOWKEYPublicKey * key,
5712 + unsigned char *data,
5713 + unsigned int *data_len,
5714 + unsigned int max_output_len,
5715 + unsigned char *sign, unsigned int sign_len)
5717 + SECStatus rv;
5718 + unsigned int modulus_len = pem_PublicModulusLen(key);
5719 + unsigned int i;
5720 + unsigned char *buffer;
5722 + if (sign_len != modulus_len)
5723 + goto failure;
5724 + PORT_Assert(key->keyType == pemLOWKEYRSAKey);
5725 + if (key->keyType != pemLOWKEYRSAKey)
5726 + goto failure;
5728 + buffer = (unsigned char *) nss_ZAlloc(NULL, modulus_len + 1);
5729 + if (!buffer)
5730 + goto failure;
5732 + rv = RSA_PublicKeyOp(&key->u.rsa, buffer, sign);
5733 + if (rv != SECSuccess)
5734 + goto loser;
5735 + *data_len = 0;
5737 + /*
5738 + * check the padding that was used
5739 + */
5740 + if (buffer[0] != 0 || buffer[1] != 1)
5741 + goto loser;
5742 + for (i = 2; i < modulus_len; i++) {
5743 + if (buffer[i] == 0) {
5744 + *data_len = modulus_len - i - 1;
5745 + break;
5747 + if (buffer[i] != 0xff)
5748 + goto loser;
5750 + if (*data_len == 0)
5751 + goto loser;
5752 + if (*data_len > max_output_len)
5753 + goto loser;
5755 + /*
5756 + * make sure we get the same results
5757 + */
5758 + nsslibc_memcpy(data, buffer + modulus_len - *data_len, *data_len);
5760 + nss_ZFreeIf(buffer);
5761 + return SECSuccess;
5763 + loser:
5764 + nss_ZFreeIf(buffer);
5765 + failure:
5766 + return SECFailure;
5769 +/* XXX Doesn't set error code */
5770 +SECStatus
5771 +RSA_EncryptBlock(NSSLOWKEYPublicKey * key,
5772 + unsigned char *output,
5773 + unsigned int *output_len,
5774 + unsigned int max_output_len,
5775 + unsigned char *input, unsigned int input_len)
5777 + SECStatus rv;
5778 + unsigned int modulus_len = pem_PublicModulusLen(key);
5779 + SECItem formatted;
5780 + SECItem unformatted;
5782 + formatted.data = NULL;
5783 + if (max_output_len < modulus_len)
5784 + goto failure;
5785 + PORT_Assert(key->keyType == pemLOWKEYRSAKey);
5786 + if (key->keyType != pemLOWKEYRSAKey)
5787 + goto failure;
5789 + unformatted.len = input_len;
5790 + unformatted.data = input;
5791 + formatted.data = NULL;
5792 + rv = rsa_FormatBlock(&formatted, modulus_len, RSA_BlockPublic,
5793 + &unformatted);
5794 + if (rv != SECSuccess)
5795 + goto failure;
5797 + rv = RSA_PublicKeyOp(&key->u.rsa, output, formatted.data);
5798 + if (rv != SECSuccess)
5799 + goto failure;
5801 + nss_ZFreeIf(formatted.data);
5802 + *output_len = modulus_len;
5803 + return SECSuccess;
5805 + failure:
5806 + if (formatted.data != NULL)
5807 + nss_ZFreeIf(formatted.data);
5808 + return SECFailure;
5810 +#endif
5812 +/* XXX Doesn't set error code */
5813 +SECStatus
5814 +pem_RSA_DecryptBlock(pemLOWKEYPrivateKey * key,
5815 + unsigned char *output,
5816 + unsigned int *output_len,
5817 + unsigned int max_output_len,
5818 + unsigned char *input, unsigned int input_len)
5820 + SECStatus rv;
5821 + unsigned int modulus_len = pem_PrivateModulusLen(key);
5822 + unsigned int i;
5823 + unsigned char *buffer;
5825 + PORT_Assert(key->keyType == pemLOWKEYRSAKey);
5826 + if (key->keyType != pemLOWKEYRSAKey)
5827 + goto failure;
5828 + if (input_len != modulus_len)
5829 + goto failure;
5831 + buffer = (unsigned char *) nss_ZAlloc(NULL, modulus_len + 1);
5832 + if (!buffer)
5833 + goto failure;
5835 + rv = RSA_PrivateKeyOp(&key->u.rsa, buffer, input);
5836 + if (rv != SECSuccess) {
5837 + goto loser;
5840 + if (buffer[0] != 0 || buffer[1] != 2)
5841 + goto loser;
5842 + *output_len = 0;
5843 + for (i = 2; i < modulus_len; i++) {
5844 + if (buffer[i] == 0) {
5845 + *output_len = modulus_len - i - 1;
5846 + break;
5849 + if (*output_len == 0)
5850 + goto loser;
5851 + if (*output_len > max_output_len)
5852 + goto loser;
5854 + nsslibc_memcpy(output, buffer + modulus_len - *output_len, *output_len);
5856 + nss_ZFreeIf(buffer);
5857 + return SECSuccess;
5859 + loser:
5860 + nss_ZFreeIf(buffer);
5861 + failure:
5862 + return SECFailure;
5865 +#if 0
5866 +/* XXX Doesn't set error code */
5868 + * added to make pkcs #11 happy
5869 + * RAW is RSA_X_509
5870 + */
5871 +SECStatus
5872 +pem_RSA_SignRaw(pemLOWKEYPrivateKey * key,
5873 + unsigned char *output,
5874 + unsigned int *output_len,
5875 + unsigned int maxOutputLen,
5876 + unsigned char *input, unsigned int input_len)
5878 + SECStatus rv = SECSuccess;
5879 + unsigned int modulus_len = pem_PrivateModulusLen(key);
5880 + SECItem formatted;
5881 + SECItem unformatted;
5883 + if (maxOutputLen < modulus_len)
5884 + return SECFailure;
5885 + PORT_Assert(key->keyType == pemLOWKEYRSAKey);
5886 + if (key->keyType != pemLOWKEYRSAKey)
5887 + return SECFailure;
5889 + unformatted.len = input_len;
5890 + unformatted.data = input;
5891 + formatted.data = NULL;
5892 + rv = rsa_FormatBlock(&formatted, modulus_len, RSA_BlockRaw,
5893 + &unformatted);
5894 + if (rv != SECSuccess)
5895 + goto done;
5897 + rv = RSA_PrivateKeyOpDoubleChecked(&key->u.rsa, output,
5898 + formatted.data);
5899 + *output_len = modulus_len;
5901 + done:
5902 + if (formatted.data != NULL)
5903 + nss_ZFreeIf(formatted.data);
5904 + return rv;
5907 +/* XXX Doesn't set error code */
5908 +SECStatus
5909 +RSA_CheckSignRaw(NSSLOWKEYPublicKey * key,
5910 + unsigned char *sign,
5911 + unsigned int sign_len,
5912 + unsigned char *hash, unsigned int hash_len)
5914 + SECStatus rv;
5915 + unsigned int modulus_len = pem_PublicModulusLen(key);
5916 + unsigned char *buffer;
5918 + if (sign_len != modulus_len)
5919 + goto failure;
5920 + if (hash_len > modulus_len)
5921 + goto failure;
5922 + PORT_Assert(key->keyType == pemLOWKEYRSAKey);
5923 + if (key->keyType != pemLOWKEYRSAKey)
5924 + goto failure;
5926 + buffer = (unsigned char *) nss_ZAlloc(NULL, modulus_len + 1);
5927 + if (!buffer)
5928 + goto failure;
5930 + rv = RSA_PublicKeyOp(&key->u.rsa, buffer, sign);
5931 + if (rv != SECSuccess)
5932 + goto loser;
5934 + /*
5935 + * make sure we get the same results
5936 + */
5937 + /* NOTE: should we verify the leading zeros? */
5938 + if (memcmp(buffer + (modulus_len - hash_len), hash, hash_len) !=
5939 + 0)
5940 + goto loser;
5942 + nss_ZFreeIf(buffer);
5943 + return SECSuccess;
5945 + loser:
5946 + nss_ZFreeIf(buffer);
5947 + failure:
5948 + return SECFailure;
5951 +/* XXX Doesn't set error code */
5952 +SECStatus
5953 +RSA_CheckSignRecoverRaw(NSSLOWKEYPublicKey * key,
5954 + unsigned char *data,
5955 + unsigned int *data_len,
5956 + unsigned int max_output_len,
5957 + unsigned char *sign, unsigned int sign_len)
5959 + SECStatus rv;
5960 + unsigned int modulus_len = pem_PublicModulusLen(key);
5962 + if (sign_len != modulus_len)
5963 + goto failure;
5964 + if (max_output_len < modulus_len)
5965 + goto failure;
5966 + PORT_Assert(key->keyType == pemLOWKEYRSAKey);
5967 + if (key->keyType != pemLOWKEYRSAKey)
5968 + goto failure;
5970 + rv = RSA_PublicKeyOp(&key->u.rsa, data, sign);
5971 + if (rv != SECSuccess)
5972 + goto failure;
5974 + *data_len = modulus_len;
5975 + return SECSuccess;
5977 + failure:
5978 + return SECFailure;
5982 +/* XXX Doesn't set error code */
5983 +SECStatus
5984 +RSA_EncryptRaw(NSSLOWKEYPublicKey * key,
5985 + unsigned char *output,
5986 + unsigned int *output_len,
5987 + unsigned int max_output_len,
5988 + unsigned char *input, unsigned int input_len)
5990 + SECStatus rv;
5991 + unsigned int modulus_len = pem_PublicModulusLen(key);
5992 + SECItem formatted;
5993 + SECItem unformatted;
5995 + formatted.data = NULL;
5996 + if (max_output_len < modulus_len)
5997 + goto failure;
5998 + PORT_Assert(key->keyType == pemLOWKEYRSAKey);
5999 + if (key->keyType != pemLOWKEYRSAKey)
6000 + goto failure;
6002 + unformatted.len = input_len;
6003 + unformatted.data = input;
6004 + formatted.data = NULL;
6005 + rv = rsa_FormatBlock(&formatted, modulus_len, RSA_BlockRaw,
6006 + &unformatted);
6007 + if (rv != SECSuccess)
6008 + goto failure;
6010 + rv = RSA_PublicKeyOp(&key->u.rsa, output, formatted.data);
6011 + if (rv != SECSuccess)
6012 + goto failure;
6014 + nss_ZFreeIf(formatted.data);
6015 + *output_len = modulus_len;
6016 + return SECSuccess;
6018 + failure:
6019 + if (formatted.data != NULL)
6020 + nss_ZFreeIf(formatted.data);
6021 + return SECFailure;
6024 +/* XXX Doesn't set error code */
6025 +SECStatus
6026 +pem_RSA_DecryptRaw(pemLOWKEYPrivateKey * key,
6027 + unsigned char *output,
6028 + unsigned int *output_len,
6029 + unsigned int max_output_len,
6030 + unsigned char *input, unsigned int input_len)
6032 + SECStatus rv;
6033 + unsigned int modulus_len = pem_PrivateModulusLen(key);
6035 + if (modulus_len <= 0)
6036 + goto failure;
6037 + if (modulus_len > max_output_len)
6038 + goto failure;
6039 + PORT_Assert(key->keyType == pemLOWKEYRSAKey);
6040 + if (key->keyType != pemLOWKEYRSAKey)
6041 + goto failure;
6042 + if (input_len != modulus_len)
6043 + goto failure;
6045 + rv = RSA_PrivateKeyOp(&key->u.rsa, output, input);
6046 + if (rv != SECSuccess) {
6047 + goto failure;
6050 + *output_len = modulus_len;
6051 + return SECSuccess;
6053 + failure:
6054 + return SECFailure;
6056 +#endif
6057 diff --git a/a/nss/lib/ckfw/pem/util.c b/b/nss/lib/ckfw/pem/util.c
6058 new file mode 100644
6059 index 0000000..e5fb4da
6060 --- /dev/null
6061 +++ b/b/nss/lib/ckfw/pem/util.c
6062 @@ -0,0 +1,314 @@
6063 +/* ***** BEGIN LICENSE BLOCK *****
6064 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6066 + * The contents of this file are subject to the Mozilla Public License Version
6067 + * 1.1 (the "License"); you may not use this file except in compliance with
6068 + * the License. You may obtain a copy of the License at
6069 + * http://www.mozilla.org/MPL/
6071 + * Software distributed under the License is distributed on an "AS IS" basis,
6072 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
6073 + * for the specific language governing rights and limitations under the
6074 + * License.
6076 + * The Original Code is the Netscape security libraries.
6078 + * The Initial Developer of the Original Code is
6079 + * Netscape Communications Corporation.
6080 + * Portions created by the Initial Developer are Copyright (C) 1994-2000
6081 + * the Initial Developer. All Rights Reserved.
6083 + * Contributor(s):
6084 + * Rob Crittenden (rcritten@redhat.com)
6086 + * Alternatively, the contents of this file may be used under the terms of
6087 + * either the GNU General Public License Version 2 or later (the "GPL"), or
6088 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
6089 + * in which case the provisions of the GPL or the LGPL are applicable instead
6090 + * of those above. If you wish to allow use of your version of this file only
6091 + * under the terms of either the GPL or the LGPL, and not to allow others to
6092 + * use your version of this file under the terms of the MPL, indicate your
6093 + * decision by deleting the provisions above and replace them with the notice
6094 + * and other provisions required by the GPL or the LGPL. If you do not delete
6095 + * the provisions above, a recipient may use your version of this file under
6096 + * the terms of any one of the MPL, the GPL or the LGPL.
6098 + * ***** END LICENSE BLOCK ***** */
6100 +/* cribbed from secutil.c */
6102 +#include "prtypes.h"
6103 +#include "prtime.h"
6104 +#include "prlong.h"
6105 +#include "prerror.h"
6106 +#include "prlog.h"
6107 +#include "prprf.h"
6108 +#include "plgetopt.h"
6109 +#include "plstr.h"
6110 +#include "prenv.h"
6111 +#include "prnetdb.h"
6112 +#include "base.h"
6113 +#include "base64.h"
6115 +#include "cryptohi.h"
6116 +#include "secpkcs7.h"
6117 +#include "secerr.h"
6119 +#include "ckpem.h"
6121 +#include <stdarg.h>
6123 +#define CHUNK_SIZE 512
6124 +#define PUT_Object(obj,err) \
6125 + { \
6126 + if (count >= size) { \
6127 + *derlist = *derlist ? \
6128 + nss_ZREALLOCARRAY(*derlist, SECItem *, \
6129 + (size+CHUNK_SIZE) ) : \
6130 + nss_ZNEWARRAY(NULL, SECItem *, \
6131 + (size+CHUNK_SIZE) ) ; \
6132 + if ((SECItem **)NULL == *derlist) { \
6133 + err = CKR_HOST_MEMORY; \
6134 + goto loser; \
6135 + } \
6136 + size += CHUNK_SIZE; \
6137 + } \
6138 + (*derlist)[ count ] = (obj); \
6139 + count++; \
6142 +/* Read certificates from a flat file */
6144 +static SECItem *AllocItem(SECItem * item, unsigned int len)
6146 + SECItem *result = NULL;
6148 + if (item == NULL) {
6149 + result = nss_ZAlloc(NULL, sizeof(SECItem));
6150 + if (result == NULL) {
6151 + goto loser;
6153 + } else {
6154 + PORT_Assert(item->data == NULL);
6155 + result = item;
6158 + result->len = len;
6159 + if (len) {
6160 + result->data = nss_ZAlloc(NULL, len);
6163 + return (result);
6165 + loser:
6166 + return (NULL);
6169 +static SECStatus FileToItem(SECItem * dst, PRFileDesc * src)
6171 + PRFileInfo info;
6172 + PRInt32 numBytes;
6173 + PRStatus prStatus;
6175 + prStatus = PR_GetOpenFileInfo(src, &info);
6177 + if (prStatus != PR_SUCCESS || info.type == PR_FILE_DIRECTORY) {
6178 + return SECFailure;
6181 + /* XXX workaround for 3.1, not all utils zero dst before sending */
6182 + dst->data = 0;
6183 + if (!AllocItem(dst, info.size+1))
6184 + goto loser;
6186 + numBytes = PR_Read(src, dst->data, info.size);
6187 + if (numBytes != info.size) {
6188 + goto loser;
6191 + return SECSuccess;
6192 + loser:
6193 + nss_ZFreeIf(dst->data);
6194 + return SECFailure;
6197 +int
6198 +ReadDERFromFile(SECItem *** derlist, char *filename, PRBool ascii,
6199 + int *cipher, char **ivstring, PRBool certsonly)
6201 + SECStatus rv;
6202 + PRFileDesc *inFile;
6203 + int count = 0, size = 0;
6204 + SECItem *der = NULL;
6205 + int error;
6206 + SECItem filedata;
6207 + char *c, *iv;
6209 + inFile = PR_Open(filename, PR_RDONLY, 0);
6210 + if (!inFile)
6211 + return -1;
6213 + if (ascii) {
6214 + /* First convert ascii to binary */
6215 + char *asc, *body;
6217 + /* Read in ascii data */
6218 + rv = FileToItem(&filedata, inFile);
6219 + if (rv != SECSuccess) {
6220 + PR_Close(inFile);
6221 + return -1;
6223 + asc = (char *) filedata.data;
6224 + if (!asc) {
6225 + PR_Close(inFile);
6226 + return -1;
6229 + /* check for headers and trailers and remove them */
6230 + if (strstr(asc, "-----BEGIN") != NULL) {
6231 + int key = 0;
6232 + while ((asc) && ((body = strstr(asc, "-----BEGIN")) != NULL)) {
6233 + char *trailer;
6234 + key = 0;
6235 + if ((strncmp(body, "-----BEGIN RSA PRIVATE KEY", 25) == 0) ||
6236 + (strncmp(body, "-----BEGIN PRIVATE KEY", 21) == 0)) {
6237 + key = 1;
6238 + c = body;
6239 + body = strchr(body, '\n');
6240 + if (NULL == body)
6241 + goto loser;
6242 + body++;
6243 + if (strncmp(body, "Proc-Type: 4,ENCRYPTED", 22) == 0) {
6244 + body = strchr(body, '\n');
6245 + if (NULL == body)
6246 + goto loser;
6247 + body++;
6248 + if (strncmp(body, "DEK-Info: ", 10) == 0) {
6249 + body += 10;
6250 + c = body;
6251 + body = strchr(body, ',');
6252 + if (body == NULL)
6253 + goto loser;
6254 + *body = '\0';
6255 + if (!PL_strcasecmp(c, "DES-EDE3-CBC"))
6256 + *cipher = NSS_DES_EDE3_CBC;
6257 + else if (!PL_strcasecmp(c, "DES-CBC"))
6258 + *cipher = NSS_DES_CBC;
6259 + else {
6260 + *cipher = -1;
6261 + goto loser;
6263 + body++;
6264 + iv = body;
6265 + body = strchr(body, '\n');
6266 + if (body == NULL)
6267 + goto loser;
6268 + *body = '\0';
6269 + body++;
6270 + *ivstring = strdup(iv);
6272 + } else { /* Else the private key is not encrypted */
6273 + *cipher = 0;
6274 + body = c;
6277 + der = (SECItem *) malloc(sizeof(SECItem));
6278 + if (der == NULL)
6279 + goto loser;
6281 + trailer = NULL;
6282 + asc = body;
6283 + body = strchr(body, '\n');
6284 + if (!body)
6285 + body = strchr(asc, '\r'); /* maybe this is a MAC file */
6286 + if (body) {
6287 + trailer = strstr(++body, "-----END");
6289 + if (trailer != NULL) {
6290 + asc = trailer + 1;
6291 + *trailer = '\0';
6292 + } else {
6293 + free(der);
6294 + goto loser;
6297 + /* Convert to binary */
6298 + rv = ATOB_ConvertAsciiToItem(der, body);
6299 + if (rv) {
6300 + free(der);
6301 + goto loser;
6303 + if ((certsonly && !key) || (!certsonly && key)) {
6304 + PUT_Object(der, error);
6305 + } else {
6306 + free(der->data);
6307 + free(der);
6309 + } /* while */
6310 + } else { /* No headers and footers, translate the blob */
6311 + der = (SECItem *) malloc(sizeof(SECItem));
6312 + if (der == NULL)
6313 + goto loser;
6315 + rv = ATOB_ConvertAsciiToItem(der, asc);
6316 + if (rv) {
6317 + free(der);
6318 + goto loser;
6321 + /* NOTE: This code path has never been tested. */
6322 + PUT_Object(der, error);
6325 + nss_ZFreeIf(filedata.data);
6326 + filedata.data = 0;
6327 + filedata.len = 0;
6328 + } else {
6329 + /* Read in binary der */
6330 + rv = FileToItem(der, inFile);
6331 + if (rv != SECSuccess) {
6332 + PR_Close(inFile);
6333 + return -1;
6336 + PR_Close(inFile);
6337 + return count;
6339 + loser:
6340 + if (filedata.len > 0)
6341 + nss_ZFreeIf(filedata.data);
6342 + PR_Close(inFile);
6343 + return -1;
6346 +#ifdef DEBUG
6347 +#define LOGGING_BUFFER_SIZE 400
6348 +#define PEM_DEFAULT_LOG_FILE "/tmp/pkcs11.log"
6349 +static const char *pemLogModuleName = "PEM";
6350 +static PRLogModuleInfo* pemLogModule;
6351 +#endif
6353 +void open_log()
6355 +#ifdef DEBUG
6356 + const char *nsprLogFile = PR_GetEnv("NSPR_LOG_FILE");
6358 + pemLogModule = PR_NewLogModule(pemLogModuleName);
6360 + (void) PR_SetLogFile(nsprLogFile ? nsprLogFile : PEM_DEFAULT_LOG_FILE);
6361 + /* If false, the log file will remain what it was before */
6362 +#endif
6365 +void plog(const char *fmt, ...)
6367 +#ifdef DEBUG
6368 + char buf[LOGGING_BUFFER_SIZE];
6369 + va_list ap;
6371 + va_start(ap, fmt);
6372 + PR_vsnprintf(buf, sizeof(buf), fmt, ap);
6373 + va_end(ap);
6374 + PR_LOG(pemLogModule, PR_LOG_DEBUG, ("%s", buf));
6375 +#endif