1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 2001
19 * the Initial Developer. All Rights Reserved.
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
37 * The following handles the loading, unloading and management of
38 * various PCKS #11 modules
43 * this header file contains routines for parsing PKCS #11 module spec
44 * strings. It contains 'C' code and should only be included in one module.
45 * Currently it is included in both softoken and the wrapper.
54 #define SECMOD_ARG_LIBRARY_PARAMETER "library="
55 #define SECMOD_ARG_NAME_PARAMETER "name="
56 #define SECMOD_ARG_MODULE_PARAMETER "parameters="
57 #define SECMOD_ARG_NSS_PARAMETER "NSS="
58 #define SECMOD_ARG_FORTEZZA_FLAG "FORTEZZA"
59 #define SECMOD_ARG_ESCAPE '\\'
61 struct secmodargSlotFlagTable
{
67 #define SECMOD_DEFAULT_CIPHER_ORDER 0
68 #define SECMOD_DEFAULT_TRUST_ORDER 50
71 #define SECMOD_ARG_ENTRY(arg,flag) \
72 { #arg , sizeof(#arg)-1, flag }
73 static struct secmodargSlotFlagTable secmod_argSlotFlagTable
[] = {
74 SECMOD_ARG_ENTRY(RSA
,SECMOD_RSA_FLAG
),
75 SECMOD_ARG_ENTRY(DSA
,SECMOD_RSA_FLAG
),
76 SECMOD_ARG_ENTRY(RC2
,SECMOD_RC4_FLAG
),
77 SECMOD_ARG_ENTRY(RC4
,SECMOD_RC2_FLAG
),
78 SECMOD_ARG_ENTRY(DES
,SECMOD_DES_FLAG
),
79 SECMOD_ARG_ENTRY(DH
,SECMOD_DH_FLAG
),
80 SECMOD_ARG_ENTRY(FORTEZZA
,SECMOD_FORTEZZA_FLAG
),
81 SECMOD_ARG_ENTRY(RC5
,SECMOD_RC5_FLAG
),
82 SECMOD_ARG_ENTRY(SHA1
,SECMOD_SHA1_FLAG
),
83 SECMOD_ARG_ENTRY(MD5
,SECMOD_MD5_FLAG
),
84 SECMOD_ARG_ENTRY(MD2
,SECMOD_MD2_FLAG
),
85 SECMOD_ARG_ENTRY(SSL
,SECMOD_SSL_FLAG
),
86 SECMOD_ARG_ENTRY(TLS
,SECMOD_TLS_FLAG
),
87 SECMOD_ARG_ENTRY(AES
,SECMOD_AES_FLAG
),
88 SECMOD_ARG_ENTRY(Camellia
,SECMOD_CAMELLIA_FLAG
),
89 SECMOD_ARG_ENTRY(PublicCerts
,SECMOD_FRIENDLY_FLAG
),
90 SECMOD_ARG_ENTRY(RANDOM
,SECMOD_RANDOM_FLAG
),
93 #define SECMOD_HANDLE_STRING_ARG(param,target,value,command) \
94 if (PORT_Strncasecmp(param,value,sizeof(value)-1) == 0) { \
95 param += sizeof(value)-1; \
96 if (target) PORT_Free(target); \
97 target = secmod_argFetchValue(param,&next); \
102 #define SECMOD_HANDLE_FINAL_ARG(param) \
103 { param = secmod_argSkipParameter(param); } param = secmod_argStrip(param);
106 static int secmod_argSlotFlagTableSize
=
107 sizeof(secmod_argSlotFlagTable
)/sizeof(secmod_argSlotFlagTable
[0]);
110 static PRBool
secmod_argGetPair(char c
) {
114 case '<': return '>';
115 case '{': return '}';
116 case '[': return ']';
117 case '(': return ')';
123 static PRBool
secmod_argIsBlank(char c
) {
127 static PRBool
secmod_argIsEscape(char c
) {
131 static PRBool
secmod_argIsQuote(char c
) {
136 case '{': /* } end curly to keep vi bracket matching working */
138 case '[': /* ] */ return PR_TRUE
;
144 static PRBool
secmod_argHasChar(char *v
, char c
)
147 if (*v
== c
) return PR_TRUE
;
152 static PRBool
secmod_argHasBlanks(char *v
)
155 if (secmod_argIsBlank(*v
)) return PR_TRUE
;
160 static char *secmod_argStrip(char *c
) {
161 while (*c
&& secmod_argIsBlank(*c
)) c
++;
166 secmod_argFindEnd(char *string
) {
168 PRBool lastEscape
= PR_FALSE
;
170 if (secmod_argIsQuote(*string
)) {
171 endChar
= secmod_argGetPair(*string
);
175 for (;*string
; string
++) {
177 lastEscape
= PR_FALSE
;
180 if (secmod_argIsEscape(*string
) && !lastEscape
) {
181 lastEscape
= PR_TRUE
;
184 if ((endChar
== ' ') && secmod_argIsBlank(*string
)) break;
185 if (*string
== endChar
) {
194 secmod_argFetchValue(char *string
, int *pcount
)
196 char *end
= secmod_argFindEnd(string
);
197 char *retString
, *copyString
;
198 PRBool lastEscape
= PR_FALSE
;
207 copyString
= retString
= (char *)PORT_Alloc(len
+1);
211 if (retString
== NULL
) return NULL
;
214 if (secmod_argIsQuote(*string
)) string
++;
215 for (; string
< end
; string
++) {
216 if (secmod_argIsEscape(*string
) && !lastEscape
) {
217 lastEscape
= PR_TRUE
;
220 lastEscape
= PR_FALSE
;
221 *copyString
++ = *string
;
228 secmod_argSkipParameter(char *string
)
231 /* look for the end of the <name>= */
232 for (;*string
; string
++) {
233 if (*string
== '=') { string
++; break; }
234 if (secmod_argIsBlank(*string
)) return(string
);
237 end
= secmod_argFindEnd(string
);
244 secmod_argParseModuleSpec(char *modulespec
, char **lib
, char **mod
,
245 char **parameters
, char **nss
)
248 modulespec
= secmod_argStrip(modulespec
);
250 *lib
= *mod
= *parameters
= *nss
= 0;
252 while (*modulespec
) {
253 SECMOD_HANDLE_STRING_ARG(modulespec
,*lib
,SECMOD_ARG_LIBRARY_PARAMETER
,;)
254 SECMOD_HANDLE_STRING_ARG(modulespec
,*mod
,SECMOD_ARG_NAME_PARAMETER
,;)
255 SECMOD_HANDLE_STRING_ARG(modulespec
,*parameters
,
256 SECMOD_ARG_MODULE_PARAMETER
,;)
257 SECMOD_HANDLE_STRING_ARG(modulespec
,*nss
,SECMOD_ARG_NSS_PARAMETER
,;)
258 SECMOD_HANDLE_FINAL_ARG(modulespec
)
265 secmod_argGetParamValue(char *paramName
,char *parameters
)
267 char searchValue
[256];
268 int paramLen
= strlen(paramName
);
269 char *returnValue
= NULL
;
272 if ((parameters
== NULL
) || (*parameters
== 0)) return NULL
;
274 PORT_Assert(paramLen
+2 < sizeof(searchValue
));
276 PORT_Strcpy(searchValue
,paramName
);
277 PORT_Strcat(searchValue
,"=");
278 while (*parameters
) {
279 if (PORT_Strncasecmp(parameters
,searchValue
,paramLen
+1) == 0) {
280 parameters
+= paramLen
+1;
281 returnValue
= secmod_argFetchValue(parameters
,&next
);
284 parameters
= secmod_argSkipParameter(parameters
);
286 parameters
= secmod_argStrip(parameters
);
293 secmod_argNextFlag(char *flags
)
295 for (; *flags
; flags
++) {
305 secmod_argHasFlag(char *label
, char *flag
, char *parameters
)
308 int len
= strlen(flag
);
309 PRBool found
= PR_FALSE
;
311 flags
= secmod_argGetParamValue(label
,parameters
);
312 if (flags
== NULL
) return PR_FALSE
;
314 for (index
=flags
; *index
; index
=secmod_argNextFlag(index
)) {
315 if (PORT_Strncasecmp(index
,flag
,len
) == 0) {
325 secmod_argSetNewCipherFlags(unsigned long *newCiphers
,char *cipherList
)
327 newCiphers
[0] = newCiphers
[1] = 0;
328 if ((cipherList
== NULL
) || (*cipherList
== 0)) return;
330 for (;*cipherList
; cipherList
=secmod_argNextFlag(cipherList
)) {
331 if (PORT_Strncasecmp(cipherList
,SECMOD_ARG_FORTEZZA_FLAG
,
332 sizeof(SECMOD_ARG_FORTEZZA_FLAG
)-1) == 0) {
333 newCiphers
[0] |= SECMOD_FORTEZZA_FLAG
;
336 /* add additional flags here as necessary */
337 /* direct bit mapping escape */
338 if (*cipherList
== 0) {
339 if (cipherList
[1] == 'l') {
340 newCiphers
[1] |= atoi(&cipherList
[2]);
342 newCiphers
[0] |= atoi(&cipherList
[2]);
350 * decode a number. handle octal (leading '0'), hex (leading '0x') or decimal
353 secmod_argDecodeNumber(char *num
)
356 unsigned long value
= 0;
361 if (num
== NULL
) return retValue
;
363 num
= secmod_argStrip(num
);
373 if ((*num
== 'x') || (*num
== 'X')) {
380 for ( ;*num
; num
++ ) {
383 } else if ((*num
>= 'a') && (*num
<= 'f')) {
384 digit
= *num
- 'a' + 10;
385 } else if ((*num
>= 'A') && (*num
<= 'F')) {
386 digit
= *num
- 'A' + 10;
390 if (digit
>= radix
) break;
391 value
= value
*radix
+ digit
;
394 retValue
= ((int) value
) * sign
;
399 secmod_argReadLong(char *label
,char *params
, long defValue
, PRBool
*isdefault
)
403 if (isdefault
) *isdefault
= PR_FALSE
;
405 value
= secmod_argGetParamValue(label
,params
);
407 if (isdefault
) *isdefault
= PR_TRUE
;
410 retValue
= secmod_argDecodeNumber(value
);
411 if (value
) PORT_Free(value
);
418 secmod_argSlotFlags(char *label
,char *params
)
421 unsigned long retValue
= 0;
423 PRBool all
= PR_FALSE
;
425 flags
= secmod_argGetParamValue(label
,params
);
426 if (flags
== NULL
) return 0;
428 if (PORT_Strcasecmp(flags
,"all") == 0) all
= PR_TRUE
;
430 for (index
=flags
; *index
; index
=secmod_argNextFlag(index
)) {
431 for (i
=0; i
< secmod_argSlotFlagTableSize
; i
++) {
432 if (all
|| (PORT_Strncasecmp(index
, secmod_argSlotFlagTable
[i
].name
,
433 secmod_argSlotFlagTable
[i
].len
) == 0)) {
434 retValue
|= secmod_argSlotFlagTable
[i
].value
;
444 secmod_argDecodeSingleSlotInfo(char *name
, char *params
,
445 PK11PreSlotInfo
*slotInfo
)
449 slotInfo
->slotID
=secmod_argDecodeNumber(name
);
450 slotInfo
->defaultFlags
=secmod_argSlotFlags("slotFlags",params
);
451 slotInfo
->timeout
=secmod_argReadLong("timeout",params
, 0, NULL
);
453 askpw
= secmod_argGetParamValue("askpw",params
);
457 if (PORT_Strcasecmp(askpw
,"every") == 0) {
458 slotInfo
->askpw
= -1;
459 } else if (PORT_Strcasecmp(askpw
,"timeout") == 0) {
463 slotInfo
->defaultFlags
|= PK11_OWN_PW_DEFAULTS
;
465 slotInfo
->hasRootCerts
= secmod_argHasFlag("rootFlags", "hasRootCerts",
467 slotInfo
->hasRootTrust
= secmod_argHasFlag("rootFlags", "hasRootTrust",
472 secmod_argGetName(char *inString
, int *next
)
478 /* look for the end of the <name>= */
479 for (string
= inString
;*string
; string
++) {
480 if (*string
== '=') { break; }
481 if (secmod_argIsBlank(*string
)) break;
484 len
= string
- inString
;
487 if (*string
== '=') (*next
) += 1;
489 name
= PORT_Alloc(len
+1);
490 PORT_Strncpy(name
,inString
,len
);
496 static PK11PreSlotInfo
*
497 secmod_argParseSlotInfo(PRArenaPool
*arena
, char *slotParams
, int *retCount
)
500 PK11PreSlotInfo
*slotInfo
= NULL
;
501 int i
=0,count
= 0,next
;
504 if ((slotParams
== NULL
) || (*slotParams
== 0)) return NULL
;
506 /* first count the number of slots */
507 for (slotIndex
= secmod_argStrip(slotParams
); *slotIndex
;
508 slotIndex
= secmod_argStrip(secmod_argSkipParameter(slotIndex
))) {
512 /* get the data structures */
514 slotInfo
= (PK11PreSlotInfo
*)
515 PORT_ArenaAlloc(arena
,count
*sizeof(PK11PreSlotInfo
));
516 PORT_Memset(slotInfo
,0,count
*sizeof(PK11PreSlotInfo
));
518 slotInfo
= (PK11PreSlotInfo
*)
519 PORT_ZAlloc(count
*sizeof(PK11PreSlotInfo
));
521 if (slotInfo
== NULL
) return NULL
;
523 for (slotIndex
= secmod_argStrip(slotParams
), i
= 0;
524 *slotIndex
&& i
< count
; ) {
526 name
= secmod_argGetName(slotIndex
,&next
);
529 if (!secmod_argIsBlank(*slotIndex
)) {
530 char *args
= secmod_argFetchValue(slotIndex
,&next
);
533 secmod_argDecodeSingleSlotInfo(name
,args
,&slotInfo
[i
]);
538 if (name
) PORT_Free(name
);
539 slotIndex
= secmod_argStrip(slotIndex
);
545 static char *secmod_nullString
= "";
548 secmod_formatValue(PRArenaPool
*arena
, char *value
, char quote
)
550 char *vp
,*vp2
,*retval
;
551 int size
= 0, escapes
= 0;
553 for (vp
=value
; *vp
;vp
++) {
554 if ((*vp
== quote
) || (*vp
== SECMOD_ARG_ESCAPE
)) escapes
++;
558 retval
= PORT_ArenaZAlloc(arena
,size
+escapes
+1);
560 retval
= PORT_ZAlloc(size
+escapes
+1);
562 if (retval
== NULL
) return NULL
;
564 for (vp
=value
; *vp
; vp
++) {
565 if ((*vp
== quote
) || (*vp
== SECMOD_ARG_ESCAPE
))
566 *vp2
++ = SECMOD_ARG_ESCAPE
;
572 static char *secmod_formatPair(char *name
,char *value
, char quote
)
574 char openQuote
= quote
;
575 char closeQuote
= secmod_argGetPair(quote
);
576 char *newValue
= NULL
;
578 PRBool need_quote
= PR_FALSE
;
580 if (!value
|| (*value
== 0)) return secmod_nullString
;
582 if (secmod_argHasBlanks(value
) || secmod_argIsQuote(value
[0]))
585 if ((need_quote
&& secmod_argHasChar(value
,closeQuote
))
586 || secmod_argHasChar(value
,SECMOD_ARG_ESCAPE
)) {
587 value
= newValue
= secmod_formatValue(NULL
, value
,quote
);
588 if (newValue
== NULL
) return secmod_nullString
;
591 returnValue
= PR_smprintf("%s=%c%s%c",name
,openQuote
,value
,closeQuote
);
593 returnValue
= PR_smprintf("%s=%s",name
,value
);
595 if (returnValue
== NULL
) returnValue
= secmod_nullString
;
597 if (newValue
) PORT_Free(newValue
);
602 static char *secmod_formatIntPair(char *name
, unsigned long value
,
607 if (value
== def
) return secmod_nullString
;
609 returnValue
= PR_smprintf("%s=%d",name
,value
);
615 secmod_freePair(char *pair
)
617 if (pair
&& pair
!= secmod_nullString
) {
618 PR_smprintf_free(pair
);
622 #define MAX_FLAG_SIZE sizeof("internal")+sizeof("FIPS")+sizeof("moduleDB")+\
623 sizeof("moduleDBOnly")+sizeof("critical")
625 secmod_mkNSSFlags(PRBool internal
, PRBool isFIPS
,
626 PRBool isModuleDB
, PRBool isModuleDBOnly
, PRBool isCritical
)
628 char *flags
= (char *)PORT_ZAlloc(MAX_FLAG_SIZE
);
629 PRBool first
= PR_TRUE
;
631 PORT_Memset(flags
,0,MAX_FLAG_SIZE
);
633 PORT_Strcat(flags
,"internal");
637 if (!first
) PORT_Strcat(flags
,",");
638 PORT_Strcat(flags
,"FIPS");
642 if (!first
) PORT_Strcat(flags
,",");
643 PORT_Strcat(flags
,"moduleDB");
646 if (isModuleDBOnly
) {
647 if (!first
) PORT_Strcat(flags
,",");
648 PORT_Strcat(flags
,"moduleDBOnly");
652 if (!first
) PORT_Strcat(flags
,",");
653 PORT_Strcat(flags
,"critical");
660 secmod_mkCipherFlags(unsigned long ssl0
, unsigned long ssl1
)
665 for (i
=0; i
< sizeof(ssl0
)*8; i
++) {
668 if ((1<<i
) == SECMOD_FORTEZZA_FLAG
) {
669 string
= PR_smprintf("%s","FORTEZZA");
671 string
= PR_smprintf("0h0x%08x",1<<i
);
675 tmp
= PR_smprintf("%s,%s",cipher
,string
);
676 PR_smprintf_free(cipher
);
677 PR_smprintf_free(string
);
684 for (i
=0; i
< sizeof(ssl0
)*8; i
++) {
688 tmp
= PR_smprintf("%s,0l0x%08x",cipher
,1<<i
);
689 PR_smprintf_free(cipher
);
692 cipher
= PR_smprintf("0l0x%08x",1<<i
);
701 secmod_mkSlotFlags(unsigned long defaultFlags
)
706 for (i
=0; i
< sizeof(defaultFlags
)*8; i
++) {
707 if (defaultFlags
& (1<<i
)) {
710 for (j
=0; j
< secmod_argSlotFlagTableSize
; j
++) {
711 if (secmod_argSlotFlagTable
[j
].value
== ( 1UL << i
)) {
712 string
= secmod_argSlotFlagTable
[j
].name
;
719 tmp
= PR_smprintf("%s,%s",flags
,string
);
720 PR_smprintf_free(flags
);
723 flags
= PR_smprintf("%s",string
);
732 #define SECMOD_MAX_ROOT_FLAG_SIZE sizeof("hasRootCerts")+sizeof("hasRootTrust")
735 secmod_mkRootFlags(PRBool hasRootCerts
, PRBool hasRootTrust
)
737 char *flags
= (char *)PORT_ZAlloc(SECMOD_MAX_ROOT_FLAG_SIZE
);
738 PRBool first
= PR_TRUE
;
740 PORT_Memset(flags
,0,SECMOD_MAX_ROOT_FLAG_SIZE
);
742 PORT_Strcat(flags
,"hasRootCerts");
746 if (!first
) PORT_Strcat(flags
,",");
747 PORT_Strcat(flags
,"hasRootTrust");
754 secmod_mkSlotString(unsigned long slotID
, unsigned long defaultFlags
,
755 unsigned long timeout
, unsigned char askpw_in
,
756 PRBool hasRootCerts
, PRBool hasRootTrust
) {
757 char *askpw
,*flags
,*rootFlags
,*slotString
;
758 char *flagPair
,*rootFlagsPair
;
771 flags
= secmod_mkSlotFlags(defaultFlags
);
772 rootFlags
= secmod_mkRootFlags(hasRootCerts
,hasRootTrust
);
773 flagPair
=secmod_formatPair("slotFlags",flags
,'\'');
774 rootFlagsPair
=secmod_formatPair("rootFlags",rootFlags
,'\'');
775 if (flags
) PR_smprintf_free(flags
);
776 if (rootFlags
) PORT_Free(rootFlags
);
777 if (defaultFlags
& PK11_OWN_PW_DEFAULTS
) {
778 slotString
= PR_smprintf("0x%08lx=[%s askpw=%s timeout=%d %s]",
779 (PRUint32
)slotID
,flagPair
,askpw
,timeout
,
782 slotString
= PR_smprintf("0x%08lx=[%s %s]",
783 (PRUint32
)slotID
,flagPair
,rootFlagsPair
);
785 secmod_freePair(flagPair
);
786 secmod_freePair(rootFlagsPair
);
791 secmod_mkNSS(char **slotStrings
, int slotCount
, PRBool internal
, PRBool isFIPS
,
792 PRBool isModuleDB
, PRBool isModuleDBOnly
, PRBool isCritical
,
793 unsigned long trustOrder
, unsigned long cipherOrder
,
794 unsigned long ssl0
, unsigned long ssl1
) {
796 char *slotParams
, *ciphers
, *nss
, *nssFlags
, *tmp
;
797 char *trustOrderPair
,*cipherOrderPair
,*slotPair
,*cipherPair
,*flagPair
;
800 /* now let's build up the string
801 * first the slot infos
804 for (i
=0; i
< (int)slotCount
; i
++) {
805 slotLen
+= PORT_Strlen(slotStrings
[i
])+1;
807 slotLen
+= 1; /* space for the final NULL */
809 slotParams
= (char *)PORT_ZAlloc(slotLen
);
810 PORT_Memset(slotParams
,0,slotLen
);
811 for (i
=0; i
< (int)slotCount
; i
++) {
812 PORT_Strcat(slotParams
,slotStrings
[i
]);
813 PORT_Strcat(slotParams
," ");
814 PR_smprintf_free(slotStrings
[i
]);
819 * now the NSS structure
821 nssFlags
= secmod_mkNSSFlags(internal
,isFIPS
,isModuleDB
,isModuleDBOnly
,
823 /* for now only the internal module is critical */
824 ciphers
= secmod_mkCipherFlags(ssl0
, ssl1
);
826 trustOrderPair
=secmod_formatIntPair("trustOrder",trustOrder
,
827 SECMOD_DEFAULT_TRUST_ORDER
);
828 cipherOrderPair
=secmod_formatIntPair("cipherOrder",cipherOrder
,
829 SECMOD_DEFAULT_CIPHER_ORDER
);
830 slotPair
=secmod_formatPair("slotParams",slotParams
,'{'); /* } */
831 if (slotParams
) PORT_Free(slotParams
);
832 cipherPair
=secmod_formatPair("ciphers",ciphers
,'\'');
833 if (ciphers
) PR_smprintf_free(ciphers
);
834 flagPair
=secmod_formatPair("Flags",nssFlags
,'\'');
835 if (nssFlags
) PORT_Free(nssFlags
);
836 nss
= PR_smprintf("%s %s %s %s %s",trustOrderPair
,
837 cipherOrderPair
,slotPair
,cipherPair
,flagPair
);
838 secmod_freePair(trustOrderPair
);
839 secmod_freePair(cipherOrderPair
);
840 secmod_freePair(slotPair
);
841 secmod_freePair(cipherPair
);
842 secmod_freePair(flagPair
);
843 tmp
= secmod_argStrip(nss
);
845 PR_smprintf_free(nss
);
852 secmod_mkNewModuleSpec(char *dllName
, char *commonName
, char *parameters
,
855 char *lib
,*name
,*param
,*nss
;
860 lib
= secmod_formatPair("library",dllName
,'\"');
861 name
= secmod_formatPair("name",commonName
,'\"');
862 param
= secmod_formatPair("parameters",parameters
,'\"');
863 nss
= secmod_formatPair("NSS",NSS
,'\"');
864 moduleSpec
= PR_smprintf("%s %s %s %s", lib
,name
,param
,nss
);
865 secmod_freePair(lib
);
866 secmod_freePair(name
);
867 secmod_freePair(param
);
868 secmod_freePair(nss
);