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