- add sources.
[platform/framework/web/crosswalk.git] / src / net / third_party / nss / patches / clientauth.patch
1 diff -pu a/nss/lib/ssl/ssl3con.c b/nss/lib/ssl/ssl3con.c
2 --- a/nss/lib/ssl/ssl3con.c     2013-07-31 12:31:45.326118409 -0700
3 +++ b/nss/lib/ssl/ssl3con.c     2013-07-31 12:35:27.189373289 -0700
4 @@ -2284,6 +2284,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 @@ -5768,25 +5771,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 @@ -5870,6 +5884,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 @@ -6496,6 +6516,10 @@ ssl3_HandleCertificateRequest(sslSocket
82      SECItem              cert_types  = {siBuffer, NULL, 0};
83      SECItem              algorithms  = {siBuffer, NULL, 0};
84      CERTDistNames        ca_list;
85 +#ifdef NSS_PLATFORM_CLIENT_AUTH
86 +    CERTCertList *       platform_cert_list = NULL;
87 +    CERTCertListNode *   certNode = NULL;
88 +#endif  /* NSS_PLATFORM_CLIENT_AUTH */
89  
90      SSL_TRC(3, ("%d: SSL3[%d]: handle certificate_request handshake",
91                 SSL_GETPID(), ss->fd));
92 @@ -6512,6 +6536,7 @@ ssl3_HandleCertificateRequest(sslSocket
93      PORT_Assert(ss->ssl3.clientCertChain == NULL);
94      PORT_Assert(ss->ssl3.clientCertificate == NULL);
95      PORT_Assert(ss->ssl3.clientPrivateKey == NULL);
96 +    PORT_Assert(ss->ssl3.platformClientKey == (PlatformKey)NULL);
97  
98      isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);
99      isTLS12 = (PRBool)(ss->ssl3.prSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
100 @@ -6591,6 +6616,18 @@ ssl3_HandleCertificateRequest(sslSocket
101      desc = no_certificate;
102      ss->ssl3.hs.ws = wait_hello_done;
103  
104 +#ifdef NSS_PLATFORM_CLIENT_AUTH
105 +    if (ss->getPlatformClientAuthData != NULL) {
106 +       /* XXX Should pass cert_types and algorithms in this call!! */
107 +        rv = (SECStatus)(*ss->getPlatformClientAuthData)(
108 +                                        ss->getPlatformClientAuthDataArg,
109 +                                        ss->fd, &ca_list,
110 +                                        &platform_cert_list,
111 +                                        (void**)&ss->ssl3.platformClientKey,
112 +                                        &ss->ssl3.clientCertificate,
113 +                                        &ss->ssl3.clientPrivateKey);
114 +    } else
115 +#endif
116      if (ss->getClientAuthData != NULL) {
117         /* XXX Should pass cert_types and algorithms in this call!! */
118         rv = (SECStatus)(*ss->getClientAuthData)(ss->getClientAuthDataArg,
119 @@ -6600,12 +6637,52 @@ ssl3_HandleCertificateRequest(sslSocket
120      } else {
121         rv = SECFailure; /* force it to send a no_certificate alert */
122      }
123 +
124      switch (rv) {
125      case SECWouldBlock:        /* getClientAuthData has put up a dialog box. */
126         ssl3_SetAlwaysBlock(ss);
127         break;  /* not an error */
128  
129      case SECSuccess:
130 +#ifdef NSS_PLATFORM_CLIENT_AUTH
131 +        if (!platform_cert_list || CERT_LIST_EMPTY(platform_cert_list) ||
132 +            !ss->ssl3.platformClientKey) {
133 +            if (platform_cert_list) {
134 +                CERT_DestroyCertList(platform_cert_list);
135 +                platform_cert_list = NULL;
136 +            }
137 +            if (ss->ssl3.platformClientKey) {
138 +                ssl_FreePlatformKey(ss->ssl3.platformClientKey);
139 +                ss->ssl3.platformClientKey = (PlatformKey)NULL;
140 +            }
141 +           /* Fall through to NSS client auth check */
142 +        } else {
143 +           certNode = CERT_LIST_HEAD(platform_cert_list);
144 +           ss->ssl3.clientCertificate = CERT_DupCertificate(certNode->cert);
145 +
146 +           /* Setting ssl3.clientCertChain non-NULL will cause
147 +            * ssl3_HandleServerHelloDone to call SendCertificate.
148 +            * Note: clientCertChain should include the EE cert as
149 +            * clientCertificate is ignored during the actual sending
150 +            */
151 +           ss->ssl3.clientCertChain =
152 +                   hack_NewCertificateListFromCertList(platform_cert_list);
153 +           CERT_DestroyCertList(platform_cert_list);
154 +           platform_cert_list = NULL;
155 +           if (ss->ssl3.clientCertChain == NULL) {
156 +               if (ss->ssl3.clientCertificate != NULL) {
157 +                   CERT_DestroyCertificate(ss->ssl3.clientCertificate);
158 +                   ss->ssl3.clientCertificate = NULL;
159 +               }
160 +               if (ss->ssl3.platformClientKey) {
161 +                   ssl_FreePlatformKey(ss->ssl3.platformClientKey);
162 +                   ss->ssl3.platformClientKey = (PlatformKey)NULL;
163 +               }
164 +               goto send_no_certificate;
165 +           }
166 +           break;  /* not an error */
167 +       }
168 +#endif   /* NSS_PLATFORM_CLIENT_AUTH */
169          /* check what the callback function returned */
170          if ((!ss->ssl3.clientCertificate) || (!ss->ssl3.clientPrivateKey)) {
171              /* we are missing either the key or cert */
172 @@ -6668,6 +6745,10 @@ loser:
173  done:
174      if (arena != NULL)
175         PORT_FreeArena(arena, PR_FALSE);
176 +#ifdef NSS_PLATFORM_CLIENT_AUTH
177 +    if (platform_cert_list)
178 +        CERT_DestroyCertList(platform_cert_list);
179 +#endif
180      return rv;
181  }
182  
183 @@ -6749,7 +6830,8 @@ ssl3_SendClientSecondRound(sslSocket *ss
184  
185      sendClientCert = !ss->ssl3.sendEmptyCert &&
186                      ss->ssl3.clientCertChain  != NULL &&
187 -                    ss->ssl3.clientPrivateKey != NULL;
188 +                    (ss->ssl3.platformClientKey ||
189 +                    ss->ssl3.clientPrivateKey != NULL);
190  
191      /* We must wait for the server's certificate to be authenticated before
192       * sending the client certificate in order to disclosing the client
193 @@ -11465,6 +11547,10 @@ ssl3_DestroySSL3Info(sslSocket *ss)
194  
195      if (ss->ssl3.clientPrivateKey != NULL)
196         SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
197 +#ifdef NSS_PLATFORM_CLIENT_AUTH
198 +    if (ss->ssl3.platformClientKey)
199 +       ssl_FreePlatformKey(ss->ssl3.platformClientKey);
200 +#endif /* NSS_PLATFORM_CLIENT_AUTH */
201  
202      if (ss->ssl3.peerCertArena != NULL)
203         ssl3_CleanupPeerCerts(ss);
204 diff -pu a/nss/lib/ssl/ssl3ext.c b/nss/lib/ssl/ssl3ext.c
205 --- a/nss/lib/ssl/ssl3ext.c     2013-07-31 12:07:10.964699464 -0700
206 +++ b/nss/lib/ssl/ssl3ext.c     2013-07-31 12:35:27.189373289 -0700
207 @@ -10,8 +10,8 @@
208  #include "nssrenam.h"
209  #include "nss.h"
210  #include "ssl.h"
211 -#include "sslproto.h"
212  #include "sslimpl.h"
213 +#include "sslproto.h"
214  #include "pk11pub.h"
215  #ifdef NO_PKCS11_BYPASS
216  #include "blapit.h"
217 diff -pu a/nss/lib/ssl/sslauth.c b/nss/lib/ssl/sslauth.c
218 --- a/nss/lib/ssl/sslauth.c     2013-07-31 12:32:29.076760372 -0700
219 +++ b/nss/lib/ssl/sslauth.c     2013-07-31 12:35:27.189373289 -0700
220 @@ -219,6 +219,28 @@ SSL_GetClientAuthDataHook(PRFileDesc *s,
221      return SECSuccess;
222  }
223  
224 +#ifdef NSS_PLATFORM_CLIENT_AUTH
225 +/* NEED LOCKS IN HERE.  */
226 +SECStatus 
227 +SSL_GetPlatformClientAuthDataHook(PRFileDesc *s,
228 +                                  SSLGetPlatformClientAuthData func,
229 +                                  void *arg)
230 +{
231 +    sslSocket *ss;
232 +
233 +    ss = ssl_FindSocket(s);
234 +    if (!ss) {
235 +       SSL_DBG(("%d: SSL[%d]: bad socket in GetPlatformClientAuthDataHook",
236 +                SSL_GETPID(), s));
237 +       return SECFailure;
238 +    }
239 +
240 +    ss->getPlatformClientAuthData = func;
241 +    ss->getPlatformClientAuthDataArg = arg;
242 +    return SECSuccess;
243 +}
244 +#endif   /* NSS_PLATFORM_CLIENT_AUTH */
245 +
246  /* NEED LOCKS IN HERE.  */
247  SECStatus 
248  SSL_SetPKCS11PinArg(PRFileDesc *s, void *arg)
249 diff -pu a/nss/lib/ssl/ssl.h b/nss/lib/ssl/ssl.h
250 --- a/nss/lib/ssl/ssl.h 2013-07-31 12:32:29.076760372 -0700
251 +++ b/nss/lib/ssl/ssl.h 2013-07-31 12:35:27.199373436 -0700
252 @@ -503,6 +503,48 @@ typedef SECStatus (PR_CALLBACK *SSLGetCl
253  SSL_IMPORT SECStatus SSL_GetClientAuthDataHook(PRFileDesc *fd, 
254                                                SSLGetClientAuthData f, void *a);
255  
256 +/*
257 + * Prototype for SSL callback to get client auth data from the application,
258 + * optionally using the underlying platform's cryptographic primitives.
259 + * To use the platform cryptographic primitives, caNames and pRetCerts
260 + * should be set.  To use NSS, pRetNSSCert and pRetNSSKey should be set.
261 + * Returning SECFailure will cause the socket to send no client certificate.
262 + *     arg - application passed argument
263 + *     caNames - pointer to distinguished names of CAs that the server likes
264 + *     pRetCerts - pointer to pointer to list of certs, with the first being
265 + *                 the client cert, and any following being used for chain
266 + *                 building
267 + *     pRetKey - pointer to native key pointer, for return of key
268 + *          - Windows: A pointer to a PCERT_KEY_CONTEXT that was allocated
269 + *                     via PORT_Alloc(). Ownership of the PCERT_KEY_CONTEXT
270 + *                     is transferred to NSS, which will free via
271 + *                     PORT_Free().
272 + *          - Mac OS X: A pointer to a SecKeyRef. Ownership is
273 + *                      transferred to NSS, which will free via CFRelease().
274 + *     pRetNSSCert - pointer to pointer to NSS cert, for return of cert.
275 + *     pRetNSSKey - pointer to NSS key pointer, for return of key.
276 + */
277 +typedef SECStatus (PR_CALLBACK *SSLGetPlatformClientAuthData)(void *arg,
278 +                                PRFileDesc *fd,
279 +                                CERTDistNames *caNames,
280 +                                CERTCertList **pRetCerts,/*return */
281 +                                void **pRetKey,/* return */
282 +                                CERTCertificate **pRetNSSCert,/*return */
283 +                                SECKEYPrivateKey **pRetNSSKey);/* return */
284 +
285 +/*
286 + * Set the client side callback for SSL to retrieve user's private key
287 + * and certificate.
288 + * Note: If a platform client auth callback is set, the callback configured by
289 + * SSL_GetClientAuthDataHook, if any, will not be called.
290 + *
291 + *     fd - the file descriptor for the connection in question
292 + *     f - the application's callback that delivers the key and cert
293 + *     a - application specific data
294 + */
295 +SSL_IMPORT SECStatus
296 +SSL_GetPlatformClientAuthDataHook(PRFileDesc *fd,
297 +                                  SSLGetPlatformClientAuthData f, void *a);
298  
299  /*
300  ** SNI extension processing callback function.
301 diff -pu a/nss/lib/ssl/sslimpl.h b/nss/lib/ssl/sslimpl.h
302 --- a/nss/lib/ssl/sslimpl.h     2013-07-31 12:31:45.326118409 -0700
303 +++ b/nss/lib/ssl/sslimpl.h     2013-07-31 12:35:27.199373436 -0700
304 @@ -20,6 +20,7 @@
305  #include "sslerr.h"
306  #include "ssl3prot.h"
307  #include "hasht.h"
308 +#include "keythi.h"
309  #include "nssilock.h"
310  #include "pkcs11t.h"
311  #if defined(XP_UNIX) || defined(XP_BEOS)
312 @@ -31,6 +32,15 @@
313  
314  #include "sslt.h" /* for some formerly private types, now public */
315  
316 +#ifdef NSS_PLATFORM_CLIENT_AUTH
317 +#if defined(XP_WIN32)
318 +#include <windows.h>
319 +#include <wincrypt.h>
320 +#elif defined(XP_MACOSX)
321 +#include <Security/Security.h>
322 +#endif
323 +#endif
324 +
325  /* to make some of these old enums public without namespace pollution,
326  ** it was necessary to prepend ssl_ to the names.
327  ** These #defines preserve compatibility with the old code here in libssl.
328 @@ -444,6 +454,14 @@ typedef SECStatus (*SSLCompressor)(void
329                                     int                  inlen);
330  typedef SECStatus (*SSLDestroy)(void *context, PRBool freeit);
331  
332 +#if defined(NSS_PLATFORM_CLIENT_AUTH) && defined(XP_WIN32)
333 +typedef PCERT_KEY_CONTEXT PlatformKey;
334 +#elif defined(NSS_PLATFORM_CLIENT_AUTH) && defined(XP_MACOSX)
335 +typedef SecKeyRef PlatformKey;
336 +#else
337 +typedef void *PlatformKey;
338 +#endif
339 +
340  
341  
342  /*
343 @@ -896,6 +914,10 @@ struct ssl3StateStr {
344  
345      CERTCertificate *    clientCertificate;  /* used by client */
346      SECKEYPrivateKey *   clientPrivateKey;   /* used by client */
347 +    /* platformClientKey is present even when NSS_PLATFORM_CLIENT_AUTH is not
348 +     * defined in order to allow cleaner conditional code.
349 +     * At most one of clientPrivateKey and platformClientKey may be set. */
350 +    PlatformKey          platformClientKey;  /* used by client */
351      CERTCertificateList *clientCertChain;    /* used by client */
352      PRBool               sendEmptyCert;      /* used by client */
353  
354 @@ -1153,6 +1175,10 @@ const unsigned char *  preferredCipher;
355      void                     *authCertificateArg;
356      SSLGetClientAuthData      getClientAuthData;
357      void                     *getClientAuthDataArg;
358 +#ifdef NSS_PLATFORM_CLIENT_AUTH
359 +    SSLGetPlatformClientAuthData getPlatformClientAuthData;
360 +    void                        *getPlatformClientAuthDataArg;
361 +#endif  /* NSS_PLATFORM_CLIENT_AUTH */
362      SSLSNISocketConfig        sniSocketConfig;
363      void                     *sniSocketConfigArg;
364      SSLBadCertHandler         handleBadCert;
365 @@ -1737,7 +1763,6 @@ extern void ssl_FreePRSocket(PRFileDesc
366   * various ciphers */
367  extern int ssl3_config_match_init(sslSocket *);
368  
369 -
370  /* Create a new ref counted key pair object from two keys. */
371  extern ssl3KeyPair * ssl3_NewKeyPair( SECKEYPrivateKey * privKey, 
372                                        SECKEYPublicKey * pubKey);
373 @@ -1777,6 +1802,26 @@ extern SECStatus ssl_InitSessionCacheLoc
374  
375  extern SECStatus ssl_FreeSessionCacheLocks(void);
376  
377 +/***************** platform client auth ****************/
378 +
379 +#ifdef NSS_PLATFORM_CLIENT_AUTH
380 +// Releases the platform key.
381 +extern void ssl_FreePlatformKey(PlatformKey key);
382 +
383 +// Implement the client CertificateVerify message for SSL3/TLS1.0
384 +extern SECStatus ssl3_PlatformSignHashes(SSL3Hashes *hash,
385 +                                         PlatformKey key, SECItem *buf,
386 +                                         PRBool isTLS, KeyType keyType);
387 +
388 +// Converts a CERTCertList* (A collection of CERTCertificates) into a
389 +// CERTCertificateList* (A collection of SECItems), or returns NULL if
390 +// it cannot be converted.
391 +// This is to allow the platform-supplied chain to be created with purely
392 +// public API functions, using the preferred CERTCertList mutators, rather
393 +// pushing this hack to clients.
394 +extern CERTCertificateList* hack_NewCertificateListFromCertList(
395 +        CERTCertList* list);
396 +#endif  /* NSS_PLATFORM_CLIENT_AUTH */
397  
398  /**************** DTLS-specific functions **************/
399  extern void dtls_FreeQueuedMessage(DTLSQueuedMessage *msg);
400 diff -pu a/nss/lib/ssl/sslsock.c b/nss/lib/ssl/sslsock.c
401 --- a/nss/lib/ssl/sslsock.c     2013-07-31 12:28:39.283413269 -0700
402 +++ b/nss/lib/ssl/sslsock.c     2013-07-31 12:35:27.199373436 -0700
403 @@ -343,6 +343,10 @@ ssl_DupSocket(sslSocket *os)
404             ss->authCertificateArg    = os->authCertificateArg;
405             ss->getClientAuthData     = os->getClientAuthData;
406             ss->getClientAuthDataArg  = os->getClientAuthDataArg;
407 +#ifdef NSS_PLATFORM_CLIENT_AUTH
408 +           ss->getPlatformClientAuthData    = os->getPlatformClientAuthData;
409 +           ss->getPlatformClientAuthDataArg = os->getPlatformClientAuthDataArg;
410 +#endif
411              ss->sniSocketConfig       = os->sniSocketConfig;
412              ss->sniSocketConfigArg    = os->sniSocketConfigArg;
413             ss->handleBadCert         = os->handleBadCert;
414 @@ -1730,6 +1734,12 @@ SSL_ReconfigFD(PRFileDesc *model, PRFile
415          ss->getClientAuthData     = sm->getClientAuthData;
416      if (sm->getClientAuthDataArg)
417          ss->getClientAuthDataArg  = sm->getClientAuthDataArg;
418 +#ifdef NSS_PLATFORM_CLIENT_AUTH
419 +    if (sm->getPlatformClientAuthData)
420 +        ss->getPlatformClientAuthData    = sm->getPlatformClientAuthData;
421 +    if (sm->getPlatformClientAuthDataArg)
422 +        ss->getPlatformClientAuthDataArg = sm->getPlatformClientAuthDataArg;
423 +#endif
424      if (sm->sniSocketConfig)
425          ss->sniSocketConfig       = sm->sniSocketConfig;
426      if (sm->sniSocketConfigArg)
427 @@ -2980,6 +2990,10 @@ ssl_NewSocket(PRBool makeLocks, SSLProto
428          ss->sniSocketConfig    = NULL;
429          ss->sniSocketConfigArg = NULL;
430         ss->getClientAuthData  = NULL;
431 +#ifdef NSS_PLATFORM_CLIENT_AUTH
432 +       ss->getPlatformClientAuthData = NULL;
433 +       ss->getPlatformClientAuthDataArg = NULL;
434 +#endif   /* NSS_PLATFORM_CLIENT_AUTH */
435         ss->handleBadCert      = NULL;
436         ss->badCertArg         = NULL;
437         ss->pkcs11PinArg       = NULL;