• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1diff -pu a/nss/lib/ssl/ssl3con.c b/nss/lib/ssl/ssl3con.c
2--- a/nss/lib/ssl/ssl3con.c	2014-01-17 17:52:00.295082288 -0800
3+++ b/nss/lib/ssl/ssl3con.c	2014-01-17 17:52:19.745405758 -0800
4@@ -2471,6 +2471,9 @@ ssl3_ClientAuthTokenPresent(sslSessionID
5     PRBool isPresent = PR_TRUE;
6
7     /* we only care if we are doing client auth */
8+    /* If NSS_PLATFORM_CLIENT_AUTH is defined and a platformClientKey is being
9+     * used, u.ssl3.clAuthValid will be false and this function will always
10+     * return PR_TRUE. */
11     if (!sid || !sid->u.ssl3.clAuthValid) {
12 	return PR_TRUE;
13     }
14@@ -6103,25 +6106,36 @@ ssl3_SendCertificateVerify(sslSocket *ss
15
16     isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
17     isTLS12 = (PRBool)(ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
18-    keyType = ss->ssl3.clientPrivateKey->keyType;
19-    rv = ssl3_SignHashes(&hashes, ss->ssl3.clientPrivateKey, &buf, isTLS);
20-    if (rv == SECSuccess) {
21-	PK11SlotInfo * slot;
22-	sslSessionID * sid   = ss->sec.ci.sid;
23+    if (ss->ssl3.platformClientKey) {
24+#ifdef NSS_PLATFORM_CLIENT_AUTH
25+	keyType = CERT_GetCertKeyType(
26+	    &ss->ssl3.clientCertificate->subjectPublicKeyInfo);
27+	rv = ssl3_PlatformSignHashes(
28+	    &hashes, ss->ssl3.platformClientKey, &buf, isTLS, keyType);
29+	ssl_FreePlatformKey(ss->ssl3.platformClientKey);
30+	ss->ssl3.platformClientKey = (PlatformKey)NULL;
31+#endif /* NSS_PLATFORM_CLIENT_AUTH */
32+    } else {
33+	keyType = ss->ssl3.clientPrivateKey->keyType;
34+	rv = ssl3_SignHashes(&hashes, ss->ssl3.clientPrivateKey, &buf, isTLS);
35+	if (rv == SECSuccess) {
36+	    PK11SlotInfo * slot;
37+	    sslSessionID * sid   = ss->sec.ci.sid;
38
39-    	/* Remember the info about the slot that did the signing.
40-	** Later, when doing an SSL restart handshake, verify this.
41-	** These calls are mere accessors, and can't fail.
42-	*/
43-	slot = PK11_GetSlotFromPrivateKey(ss->ssl3.clientPrivateKey);
44-	sid->u.ssl3.clAuthSeries     = PK11_GetSlotSeries(slot);
45-	sid->u.ssl3.clAuthSlotID     = PK11_GetSlotID(slot);
46-	sid->u.ssl3.clAuthModuleID   = PK11_GetModuleID(slot);
47-	sid->u.ssl3.clAuthValid      = PR_TRUE;
48-	PK11_FreeSlot(slot);
49+	    /* Remember the info about the slot that did the signing.
50+	    ** Later, when doing an SSL restart handshake, verify this.
51+	    ** These calls are mere accessors, and can't fail.
52+	    */
53+	    slot = PK11_GetSlotFromPrivateKey(ss->ssl3.clientPrivateKey);
54+	    sid->u.ssl3.clAuthSeries     = PK11_GetSlotSeries(slot);
55+	    sid->u.ssl3.clAuthSlotID     = PK11_GetSlotID(slot);
56+	    sid->u.ssl3.clAuthModuleID   = PK11_GetModuleID(slot);
57+	    sid->u.ssl3.clAuthValid      = PR_TRUE;
58+	    PK11_FreeSlot(slot);
59+	}
60+	SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
61+	ss->ssl3.clientPrivateKey = NULL;
62     }
63-    SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
64-    ss->ssl3.clientPrivateKey = NULL;
65     if (rv != SECSuccess) {
66 	goto done;	/* err code was set by ssl3_SignHashes */
67     }
68@@ -6200,6 +6214,12 @@ ssl3_HandleServerHello(sslSocket *ss, SS
69        SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
70        ss->ssl3.clientPrivateKey = NULL;
71     }
72+#ifdef NSS_PLATFORM_CLIENT_AUTH
73+    if (ss->ssl3.platformClientKey) {
74+       ssl_FreePlatformKey(ss->ssl3.platformClientKey);
75+       ss->ssl3.platformClientKey = (PlatformKey)NULL;
76+    }
77+#endif  /* NSS_PLATFORM_CLIENT_AUTH */
78
79     temp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
80     if (temp < 0) {
81@@ -6827,6 +6847,18 @@ ssl3_ExtractClientKeyInfo(sslSocket *ss,
82 	goto done;
83     }
84
85+#if defined(NSS_PLATFORM_CLIENT_AUTH) && defined(_WIN32)
86+    /* If the key is in CAPI, assume conservatively that the CAPI service
87+     * provider may be unable to sign SHA-256 hashes.
88+     */
89+    if (ss->ssl3.platformClientKey->dwKeySpec != CERT_NCRYPT_KEY_SPEC) {
90+	/* CAPI only supports RSA and DSA signatures, so we don't need to
91+	 * check the key type. */
92+	*preferSha1 = PR_TRUE;
93+	goto done;
94+    }
95+#endif  /* NSS_PLATFORM_CLIENT_AUTH && _WIN32 */
96+
97     /* If the key is a 1024-bit RSA or DSA key, assume conservatively that
98      * it may be unable to sign SHA-256 hashes. This is the case for older
99      * Estonian ID cards that have 1024-bit RSA keys. In FIPS 186-2 and
100@@ -6925,6 +6957,10 @@ ssl3_HandleCertificateRequest(sslSocket
101     SECItem              cert_types  = {siBuffer, NULL, 0};
102     SECItem              algorithms  = {siBuffer, NULL, 0};
103     CERTDistNames        ca_list;
104+#ifdef NSS_PLATFORM_CLIENT_AUTH
105+    CERTCertList *       platform_cert_list = NULL;
106+    CERTCertListNode *   certNode = NULL;
107+#endif  /* NSS_PLATFORM_CLIENT_AUTH */
108
109     SSL_TRC(3, ("%d: SSL3[%d]: handle certificate_request handshake",
110 		SSL_GETPID(), ss->fd));
111@@ -6941,6 +6977,7 @@ ssl3_HandleCertificateRequest(sslSocket
112     PORT_Assert(ss->ssl3.clientCertChain == NULL);
113     PORT_Assert(ss->ssl3.clientCertificate == NULL);
114     PORT_Assert(ss->ssl3.clientPrivateKey == NULL);
115+    PORT_Assert(ss->ssl3.platformClientKey == (PlatformKey)NULL);
116
117     isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);
118     isTLS12 = (PRBool)(ss->ssl3.prSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
119@@ -7020,6 +7057,18 @@ ssl3_HandleCertificateRequest(sslSocket
120     desc = no_certificate;
121     ss->ssl3.hs.ws = wait_hello_done;
122
123+#ifdef NSS_PLATFORM_CLIENT_AUTH
124+    if (ss->getPlatformClientAuthData != NULL) {
125+	/* XXX Should pass cert_types and algorithms in this call!! */
126+        rv = (SECStatus)(*ss->getPlatformClientAuthData)(
127+                                        ss->getPlatformClientAuthDataArg,
128+                                        ss->fd, &ca_list,
129+                                        &platform_cert_list,
130+                                        (void**)&ss->ssl3.platformClientKey,
131+                                        &ss->ssl3.clientCertificate,
132+                                        &ss->ssl3.clientPrivateKey);
133+    } else
134+#endif
135     if (ss->getClientAuthData != NULL) {
136 	/* XXX Should pass cert_types and algorithms in this call!! */
137 	rv = (SECStatus)(*ss->getClientAuthData)(ss->getClientAuthDataArg,
138@@ -7029,12 +7078,55 @@ ssl3_HandleCertificateRequest(sslSocket
139     } else {
140 	rv = SECFailure; /* force it to send a no_certificate alert */
141     }
142+
143     switch (rv) {
144     case SECWouldBlock:	/* getClientAuthData has put up a dialog box. */
145 	ssl3_SetAlwaysBlock(ss);
146 	break;	/* not an error */
147
148     case SECSuccess:
149+#ifdef NSS_PLATFORM_CLIENT_AUTH
150+        if (!platform_cert_list || CERT_LIST_EMPTY(platform_cert_list) ||
151+            !ss->ssl3.platformClientKey) {
152+            if (platform_cert_list) {
153+                CERT_DestroyCertList(platform_cert_list);
154+                platform_cert_list = NULL;
155+            }
156+            if (ss->ssl3.platformClientKey) {
157+                ssl_FreePlatformKey(ss->ssl3.platformClientKey);
158+                ss->ssl3.platformClientKey = (PlatformKey)NULL;
159+            }
160+	    /* Fall through to NSS client auth check */
161+        } else {
162+	    certNode = CERT_LIST_HEAD(platform_cert_list);
163+	    ss->ssl3.clientCertificate = CERT_DupCertificate(certNode->cert);
164+
165+	    /* Setting ssl3.clientCertChain non-NULL will cause
166+	     * ssl3_HandleServerHelloDone to call SendCertificate.
167+	     * Note: clientCertChain should include the EE cert as
168+	     * clientCertificate is ignored during the actual sending
169+	     */
170+	    ss->ssl3.clientCertChain =
171+		    hack_NewCertificateListFromCertList(platform_cert_list);
172+	    CERT_DestroyCertList(platform_cert_list);
173+	    platform_cert_list = NULL;
174+	    if (ss->ssl3.clientCertChain == NULL) {
175+		if (ss->ssl3.clientCertificate != NULL) {
176+		    CERT_DestroyCertificate(ss->ssl3.clientCertificate);
177+		    ss->ssl3.clientCertificate = NULL;
178+		}
179+		if (ss->ssl3.platformClientKey) {
180+		    ssl_FreePlatformKey(ss->ssl3.platformClientKey);
181+		    ss->ssl3.platformClientKey = (PlatformKey)NULL;
182+		}
183+		goto send_no_certificate;
184+	    }
185+	    if (ss->ssl3.hs.hashType == handshake_hash_single) {
186+		ssl3_DestroyBackupHandshakeHashIfNotNeeded(ss, &algorithms);
187+	    }
188+	    break;  /* not an error */
189+	}
190+#endif   /* NSS_PLATFORM_CLIENT_AUTH */
191         /* check what the callback function returned */
192         if ((!ss->ssl3.clientCertificate) || (!ss->ssl3.clientPrivateKey)) {
193             /* we are missing either the key or cert */
194@@ -7096,6 +7188,10 @@ loser:
195 done:
196     if (arena != NULL)
197     	PORT_FreeArena(arena, PR_FALSE);
198+#ifdef NSS_PLATFORM_CLIENT_AUTH
199+    if (platform_cert_list)
200+        CERT_DestroyCertList(platform_cert_list);
201+#endif
202     return rv;
203 }
204
205@@ -7213,7 +7309,8 @@ ssl3_SendClientSecondRound(sslSocket *ss
206
207     sendClientCert = !ss->ssl3.sendEmptyCert &&
208 		     ss->ssl3.clientCertChain  != NULL &&
209-		     ss->ssl3.clientPrivateKey != NULL;
210+		     (ss->ssl3.platformClientKey ||
211+		     ss->ssl3.clientPrivateKey != NULL);
212
213     if (!sendClientCert &&
214 	ss->ssl3.hs.hashType == handshake_hash_single &&
215@@ -12052,6 +12149,10 @@ ssl3_DestroySSL3Info(sslSocket *ss)
216
217     if (ss->ssl3.clientPrivateKey != NULL)
218 	SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
219+#ifdef NSS_PLATFORM_CLIENT_AUTH
220+    if (ss->ssl3.platformClientKey)
221+	ssl_FreePlatformKey(ss->ssl3.platformClientKey);
222+#endif /* NSS_PLATFORM_CLIENT_AUTH */
223
224     if (ss->ssl3.peerCertArena != NULL)
225 	ssl3_CleanupPeerCerts(ss);
226diff -pu a/nss/lib/ssl/ssl3ext.c b/nss/lib/ssl/ssl3ext.c
227--- a/nss/lib/ssl/ssl3ext.c	2014-01-17 17:49:26.072517368 -0800
228+++ b/nss/lib/ssl/ssl3ext.c	2014-01-17 17:52:19.745405758 -0800
229@@ -10,8 +10,8 @@
230 #include "nssrenam.h"
231 #include "nss.h"
232 #include "ssl.h"
233-#include "sslproto.h"
234 #include "sslimpl.h"
235+#include "sslproto.h"
236 #include "pk11pub.h"
237 #ifdef NO_PKCS11_BYPASS
238 #include "blapit.h"
239diff -pu a/nss/lib/ssl/sslauth.c b/nss/lib/ssl/sslauth.c
240--- a/nss/lib/ssl/sslauth.c	2014-01-17 17:49:26.072517368 -0800
241+++ b/nss/lib/ssl/sslauth.c	2014-01-17 17:52:19.755405924 -0800
242@@ -216,6 +216,28 @@ SSL_GetClientAuthDataHook(PRFileDesc *s,
243     return SECSuccess;
244 }
245
246+#ifdef NSS_PLATFORM_CLIENT_AUTH
247+/* NEED LOCKS IN HERE.  */
248+SECStatus
249+SSL_GetPlatformClientAuthDataHook(PRFileDesc *s,
250+                                  SSLGetPlatformClientAuthData func,
251+                                  void *arg)
252+{
253+    sslSocket *ss;
254+
255+    ss = ssl_FindSocket(s);
256+    if (!ss) {
257+	SSL_DBG(("%d: SSL[%d]: bad socket in GetPlatformClientAuthDataHook",
258+		 SSL_GETPID(), s));
259+	return SECFailure;
260+    }
261+
262+    ss->getPlatformClientAuthData = func;
263+    ss->getPlatformClientAuthDataArg = arg;
264+    return SECSuccess;
265+}
266+#endif   /* NSS_PLATFORM_CLIENT_AUTH */
267+
268 /* NEED LOCKS IN HERE.  */
269 SECStatus
270 SSL_SetPKCS11PinArg(PRFileDesc *s, void *arg)
271diff -pu a/nss/lib/ssl/ssl.h b/nss/lib/ssl/ssl.h
272--- a/nss/lib/ssl/ssl.h	2014-01-17 17:49:26.062517203 -0800
273+++ b/nss/lib/ssl/ssl.h	2014-01-17 17:52:19.755405924 -0800
274@@ -533,6 +533,48 @@ typedef SECStatus (PR_CALLBACK *SSLGetCl
275 SSL_IMPORT SECStatus SSL_GetClientAuthDataHook(PRFileDesc *fd,
276 			                       SSLGetClientAuthData f, void *a);
277
278+/*
279+ * Prototype for SSL callback to get client auth data from the application,
280+ * optionally using the underlying platform's cryptographic primitives.
281+ * To use the platform cryptographic primitives, caNames and pRetCerts
282+ * should be set.  To use NSS, pRetNSSCert and pRetNSSKey should be set.
283+ * Returning SECFailure will cause the socket to send no client certificate.
284+ *	arg - application passed argument
285+ *	caNames - pointer to distinguished names of CAs that the server likes
286+ *	pRetCerts - pointer to pointer to list of certs, with the first being
287+ *		    the client cert, and any following being used for chain
288+ *		    building
289+ *	pRetKey - pointer to native key pointer, for return of key
290+ *          - Windows: A pointer to a PCERT_KEY_CONTEXT that was allocated
291+ *                     via PORT_Alloc(). Ownership of the PCERT_KEY_CONTEXT
292+ *                     is transferred to NSS, which will free via
293+ *                     PORT_Free().
294+ *          - Mac OS X: A pointer to a SecKeyRef. Ownership is
295+ *                      transferred to NSS, which will free via CFRelease().
296+ *	pRetNSSCert - pointer to pointer to NSS cert, for return of cert.
297+ *	pRetNSSKey - pointer to NSS key pointer, for return of key.
298+ */
299+typedef SECStatus (PR_CALLBACK *SSLGetPlatformClientAuthData)(void *arg,
300+                                PRFileDesc *fd,
301+                                CERTDistNames *caNames,
302+                                CERTCertList **pRetCerts,/*return */
303+                                void **pRetKey,/* return */
304+                                CERTCertificate **pRetNSSCert,/*return */
305+                                SECKEYPrivateKey **pRetNSSKey);/* return */
306+
307+/*
308+ * Set the client side callback for SSL to retrieve user's private key
309+ * and certificate.
310+ * Note: If a platform client auth callback is set, the callback configured by
311+ * SSL_GetClientAuthDataHook, if any, will not be called.
312+ *
313+ *	fd - the file descriptor for the connection in question
314+ *	f - the application's callback that delivers the key and cert
315+ *	a - application specific data
316+ */
317+SSL_IMPORT SECStatus
318+SSL_GetPlatformClientAuthDataHook(PRFileDesc *fd,
319+                                  SSLGetPlatformClientAuthData f, void *a);
320
321 /*
322 ** SNI extension processing callback function.
323diff -pu a/nss/lib/ssl/sslimpl.h b/nss/lib/ssl/sslimpl.h
324--- a/nss/lib/ssl/sslimpl.h	2014-01-17 17:52:00.295082288 -0800
325+++ b/nss/lib/ssl/sslimpl.h	2014-01-17 17:52:19.755405924 -0800
326@@ -20,6 +20,7 @@
327 #include "sslerr.h"
328 #include "ssl3prot.h"
329 #include "hasht.h"
330+#include "keythi.h"
331 #include "nssilock.h"
332 #include "pkcs11t.h"
333 #if defined(XP_UNIX) || defined(XP_BEOS)
334@@ -31,6 +32,15 @@
335
336 #include "sslt.h" /* for some formerly private types, now public */
337
338+#ifdef NSS_PLATFORM_CLIENT_AUTH
339+#if defined(XP_WIN32)
340+#include <windows.h>
341+#include <wincrypt.h>
342+#elif defined(XP_MACOSX)
343+#include <Security/Security.h>
344+#endif
345+#endif
346+
347 /* to make some of these old enums public without namespace pollution,
348 ** it was necessary to prepend ssl_ to the names.
349 ** These #defines preserve compatibility with the old code here in libssl.
350@@ -441,6 +451,14 @@ struct sslGatherStr {
351 #define GS_DATA		3
352 #define GS_PAD		4
353
354+#if defined(NSS_PLATFORM_CLIENT_AUTH) && defined(XP_WIN32)
355+typedef PCERT_KEY_CONTEXT PlatformKey;
356+#elif defined(NSS_PLATFORM_CLIENT_AUTH) && defined(XP_MACOSX)
357+typedef SecKeyRef PlatformKey;
358+#else
359+typedef void *PlatformKey;
360+#endif
361+
362
363
364 /*
365@@ -953,6 +971,10 @@ struct ssl3StateStr {
366
367     CERTCertificate *    clientCertificate;  /* used by client */
368     SECKEYPrivateKey *   clientPrivateKey;   /* used by client */
369+    /* platformClientKey is present even when NSS_PLATFORM_CLIENT_AUTH is not
370+     * defined in order to allow cleaner conditional code.
371+     * At most one of clientPrivateKey and platformClientKey may be set. */
372+    PlatformKey          platformClientKey;  /* used by client */
373     CERTCertificateList *clientCertChain;    /* used by client */
374     PRBool               sendEmptyCert;      /* used by client */
375
376@@ -1214,6 +1236,10 @@ const unsigned char *  preferredCipher;
377     void                     *authCertificateArg;
378     SSLGetClientAuthData      getClientAuthData;
379     void                     *getClientAuthDataArg;
380+#ifdef NSS_PLATFORM_CLIENT_AUTH
381+    SSLGetPlatformClientAuthData getPlatformClientAuthData;
382+    void                        *getPlatformClientAuthDataArg;
383+#endif  /* NSS_PLATFORM_CLIENT_AUTH */
384     SSLSNISocketConfig        sniSocketConfig;
385     void                     *sniSocketConfigArg;
386     SSLBadCertHandler         handleBadCert;
387@@ -1852,6 +1878,26 @@ extern SECStatus ssl_InitSessionCacheLoc
388
389 extern SECStatus ssl_FreeSessionCacheLocks(void);
390
391+/***************** platform client auth ****************/
392+
393+#ifdef NSS_PLATFORM_CLIENT_AUTH
394+// Releases the platform key.
395+extern void ssl_FreePlatformKey(PlatformKey key);
396+
397+// Implement the client CertificateVerify message for SSL3/TLS1.0
398+extern SECStatus ssl3_PlatformSignHashes(SSL3Hashes *hash,
399+                                         PlatformKey key, SECItem *buf,
400+                                         PRBool isTLS, KeyType keyType);
401+
402+// Converts a CERTCertList* (A collection of CERTCertificates) into a
403+// CERTCertificateList* (A collection of SECItems), or returns NULL if
404+// it cannot be converted.
405+// This is to allow the platform-supplied chain to be created with purely
406+// public API functions, using the preferred CERTCertList mutators, rather
407+// pushing this hack to clients.
408+extern CERTCertificateList* hack_NewCertificateListFromCertList(
409+        CERTCertList* list);
410+#endif  /* NSS_PLATFORM_CLIENT_AUTH */
411
412 /**************** DTLS-specific functions **************/
413 extern void dtls_FreeQueuedMessage(DTLSQueuedMessage *msg);
414diff -pu a/nss/lib/ssl/sslsock.c b/nss/lib/ssl/sslsock.c
415--- a/nss/lib/ssl/sslsock.c	2014-01-17 17:49:40.942764689 -0800
416+++ b/nss/lib/ssl/sslsock.c	2014-01-17 17:52:19.755405924 -0800
417@@ -263,6 +263,10 @@ ssl_DupSocket(sslSocket *os)
418 	    ss->authCertificateArg    = os->authCertificateArg;
419 	    ss->getClientAuthData     = os->getClientAuthData;
420 	    ss->getClientAuthDataArg  = os->getClientAuthDataArg;
421+#ifdef NSS_PLATFORM_CLIENT_AUTH
422+	    ss->getPlatformClientAuthData    = os->getPlatformClientAuthData;
423+	    ss->getPlatformClientAuthDataArg = os->getPlatformClientAuthDataArg;
424+#endif
425             ss->sniSocketConfig       = os->sniSocketConfig;
426             ss->sniSocketConfigArg    = os->sniSocketConfigArg;
427 	    ss->handleBadCert         = os->handleBadCert;
428@@ -1667,6 +1671,12 @@ SSL_ReconfigFD(PRFileDesc *model, PRFile
429         ss->getClientAuthData     = sm->getClientAuthData;
430     if (sm->getClientAuthDataArg)
431         ss->getClientAuthDataArg  = sm->getClientAuthDataArg;
432+#ifdef NSS_PLATFORM_CLIENT_AUTH
433+    if (sm->getPlatformClientAuthData)
434+        ss->getPlatformClientAuthData    = sm->getPlatformClientAuthData;
435+    if (sm->getPlatformClientAuthDataArg)
436+        ss->getPlatformClientAuthDataArg = sm->getPlatformClientAuthDataArg;
437+#endif
438     if (sm->sniSocketConfig)
439         ss->sniSocketConfig       = sm->sniSocketConfig;
440     if (sm->sniSocketConfigArg)
441@@ -2921,6 +2931,10 @@ ssl_NewSocket(PRBool makeLocks, SSLProto
442         ss->sniSocketConfig    = NULL;
443         ss->sniSocketConfigArg = NULL;
444 	ss->getClientAuthData  = NULL;
445+#ifdef NSS_PLATFORM_CLIENT_AUTH
446+	ss->getPlatformClientAuthData = NULL;
447+	ss->getPlatformClientAuthDataArg = NULL;
448+#endif   /* NSS_PLATFORM_CLIENT_AUTH */
449 	ss->handleBadCert      = NULL;
450 	ss->badCertArg         = NULL;
451 	ss->pkcs11PinArg       = NULL;
452