nss: make the fallback to SSLv3 work again
[platform/upstream/curl.git] / lib / vtls / nss.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
10  * This software is licensed as described in the file COPYING, which
11  * you should have received as part of this distribution. The terms
12  * are also available at http://curl.haxx.se/docs/copyright.html.
13  *
14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15  * copies of the Software, and permit persons to whom the Software is
16  * furnished to do so, under the terms of the COPYING file.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  ***************************************************************************/
22
23 /*
24  * Source file for all NSS-specific code for the TLS/SSL layer. No code
25  * but vtls.c should ever call or use these functions.
26  */
27
28 #include "curl_setup.h"
29
30 #ifdef USE_NSS
31
32 #include "urldata.h"
33 #include "sendf.h"
34 #include "formdata.h" /* for the boundary function */
35 #include "url.h" /* for the ssl config check function */
36 #include "connect.h"
37 #include "strequal.h"
38 #include "select.h"
39 #include "vtls.h"
40 #include "llist.h"
41
42 #define _MPRINTF_REPLACE /* use the internal *printf() functions */
43 #include <curl/mprintf.h>
44
45 #include "nssg.h"
46 #include <nspr.h>
47 #include <nss.h>
48 #include <ssl.h>
49 #include <sslerr.h>
50 #include <secerr.h>
51 #include <secmod.h>
52 #include <sslproto.h>
53 #include <prtypes.h>
54 #include <pk11pub.h>
55 #include <prio.h>
56 #include <secitem.h>
57 #include <secport.h>
58 #include <certdb.h>
59 #include <base64.h>
60 #include <cert.h>
61 #include <prerror.h>
62
63 #include "curl_memory.h"
64 #include "rawstr.h"
65 #include "warnless.h"
66 #include "x509asn1.h"
67
68 /* The last #include file should be: */
69 #include "memdebug.h"
70
71 #define SSL_DIR "/etc/pki/nssdb"
72
73 /* enough to fit the string "PEM Token #[0|1]" */
74 #define SLOTSIZE 13
75
76 PRFileDesc *PR_ImportTCPSocket(PRInt32 osfd);
77
78 PRLock * nss_initlock = NULL;
79 PRLock * nss_crllock = NULL;
80 NSSInitContext * nss_context = NULL;
81
82 volatile int initialized = 0;
83
84 typedef struct {
85   const char *name;
86   int num;
87 } cipher_s;
88
89 #define PK11_SETATTRS(_attr, _idx, _type, _val, _len) do {  \
90   CK_ATTRIBUTE *ptr = (_attr) + ((_idx)++);                 \
91   ptr->type = (_type);                                      \
92   ptr->pValue = (_val);                                     \
93   ptr->ulValueLen = (_len);                                 \
94 } WHILE_FALSE
95
96 #define CERT_NewTempCertificate __CERT_NewTempCertificate
97
98 #define NUM_OF_CIPHERS sizeof(cipherlist)/sizeof(cipherlist[0])
99 static const cipher_s cipherlist[] = {
100   /* SSL2 cipher suites */
101   {"rc4",                        SSL_EN_RC4_128_WITH_MD5},
102   {"rc4-md5",                    SSL_EN_RC4_128_WITH_MD5},
103   {"rc4export",                  SSL_EN_RC4_128_EXPORT40_WITH_MD5},
104   {"rc2",                        SSL_EN_RC2_128_CBC_WITH_MD5},
105   {"rc2export",                  SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5},
106   {"des",                        SSL_EN_DES_64_CBC_WITH_MD5},
107   {"desede3",                    SSL_EN_DES_192_EDE3_CBC_WITH_MD5},
108   /* SSL3/TLS cipher suites */
109   {"rsa_rc4_128_md5",            SSL_RSA_WITH_RC4_128_MD5},
110   {"rsa_rc4_128_sha",            SSL_RSA_WITH_RC4_128_SHA},
111   {"rsa_3des_sha",               SSL_RSA_WITH_3DES_EDE_CBC_SHA},
112   {"rsa_des_sha",                SSL_RSA_WITH_DES_CBC_SHA},
113   {"rsa_rc4_40_md5",             SSL_RSA_EXPORT_WITH_RC4_40_MD5},
114   {"rsa_rc2_40_md5",             SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5},
115   {"rsa_null_md5",               SSL_RSA_WITH_NULL_MD5},
116   {"rsa_null_sha",               SSL_RSA_WITH_NULL_SHA},
117   {"fips_3des_sha",              SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA},
118   {"fips_des_sha",               SSL_RSA_FIPS_WITH_DES_CBC_SHA},
119   {"fortezza",                   SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA},
120   {"fortezza_rc4_128_sha",       SSL_FORTEZZA_DMS_WITH_RC4_128_SHA},
121   {"fortezza_null",              SSL_FORTEZZA_DMS_WITH_NULL_SHA},
122   /* TLS 1.0: Exportable 56-bit Cipher Suites. */
123   {"rsa_des_56_sha",             TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA},
124   {"rsa_rc4_56_sha",             TLS_RSA_EXPORT1024_WITH_RC4_56_SHA},
125   /* AES ciphers. */
126   {"dhe_dss_aes_128_cbc_sha",    TLS_DHE_DSS_WITH_AES_128_CBC_SHA},
127   {"dhe_dss_aes_256_cbc_sha",    TLS_DHE_DSS_WITH_AES_256_CBC_SHA},
128   {"dhe_rsa_aes_128_cbc_sha",    TLS_DHE_RSA_WITH_AES_128_CBC_SHA},
129   {"dhe_rsa_aes_256_cbc_sha",    TLS_DHE_RSA_WITH_AES_256_CBC_SHA},
130   {"rsa_aes_128_sha",            TLS_RSA_WITH_AES_128_CBC_SHA},
131   {"rsa_aes_256_sha",            TLS_RSA_WITH_AES_256_CBC_SHA},
132   /* ECC ciphers. */
133   {"ecdh_ecdsa_null_sha",        TLS_ECDH_ECDSA_WITH_NULL_SHA},
134   {"ecdh_ecdsa_rc4_128_sha",     TLS_ECDH_ECDSA_WITH_RC4_128_SHA},
135   {"ecdh_ecdsa_3des_sha",        TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA},
136   {"ecdh_ecdsa_aes_128_sha",     TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA},
137   {"ecdh_ecdsa_aes_256_sha",     TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA},
138   {"ecdhe_ecdsa_null_sha",       TLS_ECDHE_ECDSA_WITH_NULL_SHA},
139   {"ecdhe_ecdsa_rc4_128_sha",    TLS_ECDHE_ECDSA_WITH_RC4_128_SHA},
140   {"ecdhe_ecdsa_3des_sha",       TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA},
141   {"ecdhe_ecdsa_aes_128_sha",    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA},
142   {"ecdhe_ecdsa_aes_256_sha",    TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
143   {"ecdh_rsa_null_sha",          TLS_ECDH_RSA_WITH_NULL_SHA},
144   {"ecdh_rsa_128_sha",           TLS_ECDH_RSA_WITH_RC4_128_SHA},
145   {"ecdh_rsa_3des_sha",          TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA},
146   {"ecdh_rsa_aes_128_sha",       TLS_ECDH_RSA_WITH_AES_128_CBC_SHA},
147   {"ecdh_rsa_aes_256_sha",       TLS_ECDH_RSA_WITH_AES_256_CBC_SHA},
148   {"echde_rsa_null",             TLS_ECDHE_RSA_WITH_NULL_SHA},
149   {"ecdhe_rsa_rc4_128_sha",      TLS_ECDHE_RSA_WITH_RC4_128_SHA},
150   {"ecdhe_rsa_3des_sha",         TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA},
151   {"ecdhe_rsa_aes_128_sha",      TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
152   {"ecdhe_rsa_aes_256_sha",      TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
153   {"ecdh_anon_null_sha",         TLS_ECDH_anon_WITH_NULL_SHA},
154   {"ecdh_anon_rc4_128sha",       TLS_ECDH_anon_WITH_RC4_128_SHA},
155   {"ecdh_anon_3des_sha",         TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA},
156   {"ecdh_anon_aes_128_sha",      TLS_ECDH_anon_WITH_AES_128_CBC_SHA},
157   {"ecdh_anon_aes_256_sha",      TLS_ECDH_anon_WITH_AES_256_CBC_SHA},
158 #ifdef TLS_RSA_WITH_NULL_SHA256
159   /* new HMAC-SHA256 cipher suites specified in RFC */
160   {"rsa_null_sha_256",                TLS_RSA_WITH_NULL_SHA256},
161   {"rsa_aes_128_cbc_sha_256",         TLS_RSA_WITH_AES_128_CBC_SHA256},
162   {"rsa_aes_256_cbc_sha_256",         TLS_RSA_WITH_AES_256_CBC_SHA256},
163   {"dhe_rsa_aes_128_cbc_sha_256",     TLS_DHE_RSA_WITH_AES_128_CBC_SHA256},
164   {"dhe_rsa_aes_256_cbc_sha_256",     TLS_DHE_RSA_WITH_AES_256_CBC_SHA256},
165   {"ecdhe_ecdsa_aes_128_cbc_sha_256", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256},
166   {"ecdhe_rsa_aes_128_cbc_sha_256",   TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},
167 #endif
168 #ifdef TLS_RSA_WITH_AES_128_GCM_SHA256
169   /* AES GCM cipher suites in RFC 5288 and RFC 5289 */
170   {"rsa_aes_128_gcm_sha_256",         TLS_RSA_WITH_AES_128_GCM_SHA256},
171   {"dhe_rsa_aes_128_gcm_sha_256",     TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
172   {"dhe_dss_aes_128_gcm_sha_256",     TLS_DHE_DSS_WITH_AES_128_GCM_SHA256},
173   {"ecdhe_ecdsa_aes_128_gcm_sha_256", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
174   {"ecdh_ecdsa_aes_128_gcm_sha_256",  TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256},
175   {"ecdhe_rsa_aes_128_gcm_sha_256",   TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
176   {"ecdh_rsa_aes_128_gcm_sha_256",    TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256},
177 #endif
178 };
179
180 static const char* pem_library = "libnsspem.so";
181 SECMODModule* mod = NULL;
182
183 /* NSPR I/O layer we use to detect blocking direction during SSL handshake */
184 static PRDescIdentity nspr_io_identity = PR_INVALID_IO_LAYER;
185 static PRIOMethods nspr_io_methods;
186
187 static const char* nss_error_to_name(PRErrorCode code)
188 {
189   const char *name = PR_ErrorToName(code);
190   if(name)
191     return name;
192
193   return "unknown error";
194 }
195
196 static void nss_print_error_message(struct SessionHandle *data, PRUint32 err)
197 {
198   failf(data, "%s", PR_ErrorToString(err, PR_LANGUAGE_I_DEFAULT));
199 }
200
201 static SECStatus set_ciphers(struct SessionHandle *data, PRFileDesc * model,
202                              char *cipher_list)
203 {
204   unsigned int i;
205   PRBool cipher_state[NUM_OF_CIPHERS];
206   PRBool found;
207   char *cipher;
208
209   /* First disable all ciphers. This uses a different max value in case
210    * NSS adds more ciphers later we don't want them available by
211    * accident
212    */
213   for(i=0; i<SSL_NumImplementedCiphers; i++) {
214     SSL_CipherPrefSet(model, SSL_ImplementedCiphers[i], PR_FALSE);
215   }
216
217   /* Set every entry in our list to false */
218   for(i=0; i<NUM_OF_CIPHERS; i++) {
219     cipher_state[i] = PR_FALSE;
220   }
221
222   cipher = cipher_list;
223
224   while(cipher_list && (cipher_list[0])) {
225     while((*cipher) && (ISSPACE(*cipher)))
226       ++cipher;
227
228     if((cipher_list = strchr(cipher, ','))) {
229       *cipher_list++ = '\0';
230     }
231
232     found = PR_FALSE;
233
234     for(i=0; i<NUM_OF_CIPHERS; i++) {
235       if(Curl_raw_equal(cipher, cipherlist[i].name)) {
236         cipher_state[i] = PR_TRUE;
237         found = PR_TRUE;
238         break;
239       }
240     }
241
242     if(found == PR_FALSE) {
243       failf(data, "Unknown cipher in list: %s", cipher);
244       return SECFailure;
245     }
246
247     if(cipher_list) {
248       cipher = cipher_list;
249     }
250   }
251
252   /* Finally actually enable the selected ciphers */
253   for(i=0; i<NUM_OF_CIPHERS; i++) {
254     if(!cipher_state[i])
255       continue;
256
257     if(SSL_CipherPrefSet(model, cipherlist[i].num, PR_TRUE) != SECSuccess) {
258       failf(data, "cipher-suite not supported by NSS: %s", cipherlist[i].name);
259       return SECFailure;
260     }
261   }
262
263   return SECSuccess;
264 }
265
266 /*
267  * Get the number of ciphers that are enabled. We use this to determine
268  * if we need to call NSS_SetDomesticPolicy() to enable the default ciphers.
269  */
270 static int num_enabled_ciphers(void)
271 {
272   PRInt32 policy = 0;
273   int count = 0;
274   unsigned int i;
275
276   for(i=0; i<NUM_OF_CIPHERS; i++) {
277     SSL_CipherPolicyGet(cipherlist[i].num, &policy);
278     if(policy)
279       count++;
280   }
281   return count;
282 }
283
284 /*
285  * Determine whether the nickname passed in is a filename that needs to
286  * be loaded as a PEM or a regular NSS nickname.
287  *
288  * returns 1 for a file
289  * returns 0 for not a file (NSS nickname)
290  */
291 static int is_file(const char *filename)
292 {
293   struct_stat st;
294
295   if(filename == NULL)
296     return 0;
297
298   if(stat(filename, &st) == 0)
299     if(S_ISREG(st.st_mode))
300       return 1;
301
302   return 0;
303 }
304
305 /* Check if the given string is filename or nickname of a certificate.  If the
306  * given string is recognized as filename, return NULL.  If the given string is
307  * recognized as nickname, return a duplicated string.  The returned string
308  * should be later deallocated using free().  If the OOM failure occurs, we
309  * return NULL, too.
310  */
311 static char* dup_nickname(struct SessionHandle *data, enum dupstring cert_kind)
312 {
313   const char *str = data->set.str[cert_kind];
314   const char *n;
315
316   if(!is_file(str))
317     /* no such file exists, use the string as nickname */
318     return strdup(str);
319
320   /* search the last slash; we require at least one slash in a file name */
321   n = strrchr(str, '/');
322   if(!n) {
323     infof(data, "warning: certificate file name \"%s\" handled as nickname; "
324           "please use \"./%s\" to force file name\n", str, str);
325     return strdup(str);
326   }
327
328   /* we'll use the PEM reader to read the certificate from file */
329   return NULL;
330 }
331
332 /* Call PK11_CreateGenericObject() with the given obj_class and filename.  If
333  * the call succeeds, append the object handle to the list of objects so that
334  * the object can be destroyed in Curl_nss_close(). */
335 static CURLcode nss_create_object(struct ssl_connect_data *ssl,
336                                   CK_OBJECT_CLASS obj_class,
337                                   const char *filename, bool cacert)
338 {
339   PK11SlotInfo *slot;
340   PK11GenericObject *obj;
341   CK_BBOOL cktrue = CK_TRUE;
342   CK_BBOOL ckfalse = CK_FALSE;
343   CK_ATTRIBUTE attrs[/* max count of attributes */ 4];
344   int attr_cnt = 0;
345   CURLcode err = (cacert)
346     ? CURLE_SSL_CACERT_BADFILE
347     : CURLE_SSL_CERTPROBLEM;
348
349   const int slot_id = (cacert) ? 0 : 1;
350   char *slot_name = aprintf("PEM Token #%d", slot_id);
351   if(!slot_name)
352     return CURLE_OUT_OF_MEMORY;
353
354   slot = PK11_FindSlotByName(slot_name);
355   free(slot_name);
356   if(!slot)
357     return err;
358
359   PK11_SETATTRS(attrs, attr_cnt, CKA_CLASS, &obj_class, sizeof(obj_class));
360   PK11_SETATTRS(attrs, attr_cnt, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL));
361   PK11_SETATTRS(attrs, attr_cnt, CKA_LABEL, (unsigned char *)filename,
362                 strlen(filename) + 1);
363
364   if(CKO_CERTIFICATE == obj_class) {
365     CK_BBOOL *pval = (cacert) ? (&cktrue) : (&ckfalse);
366     PK11_SETATTRS(attrs, attr_cnt, CKA_TRUST, pval, sizeof(*pval));
367   }
368
369   obj = PK11_CreateGenericObject(slot, attrs, attr_cnt, PR_FALSE);
370   PK11_FreeSlot(slot);
371   if(!obj)
372     return err;
373
374   if(!Curl_llist_insert_next(ssl->obj_list, ssl->obj_list->tail, obj)) {
375     PK11_DestroyGenericObject(obj);
376     return CURLE_OUT_OF_MEMORY;
377   }
378
379   if(!cacert && CKO_CERTIFICATE == obj_class)
380     /* store reference to a client certificate */
381     ssl->obj_clicert = obj;
382
383   return CURLE_OK;
384 }
385
386 /* Destroy the NSS object whose handle is given by ptr.  This function is
387  * a callback of Curl_llist_alloc() used by Curl_llist_destroy() to destroy
388  * NSS objects in Curl_nss_close() */
389 static void nss_destroy_object(void *user, void *ptr)
390 {
391   PK11GenericObject *obj = (PK11GenericObject *)ptr;
392   (void) user;
393   PK11_DestroyGenericObject(obj);
394 }
395
396 static CURLcode nss_load_cert(struct ssl_connect_data *ssl,
397                               const char *filename, PRBool cacert)
398 {
399   CURLcode err = (cacert)
400     ? CURLE_SSL_CACERT_BADFILE
401     : CURLE_SSL_CERTPROBLEM;
402
403   /* libnsspem.so leaks memory if the requested file does not exist.  For more
404    * details, go to <https://bugzilla.redhat.com/734760>. */
405   if(is_file(filename))
406     err = nss_create_object(ssl, CKO_CERTIFICATE, filename, cacert);
407
408   if(CURLE_OK == err && !cacert) {
409     /* we have successfully loaded a client certificate */
410     CERTCertificate *cert;
411     char *nickname = NULL;
412     char *n = strrchr(filename, '/');
413     if(n)
414       n++;
415
416     /* The following undocumented magic helps to avoid a SIGSEGV on call
417      * of PK11_ReadRawAttribute() from SelectClientCert() when using an
418      * immature version of libnsspem.so.  For more details, go to
419      * <https://bugzilla.redhat.com/733685>. */
420     nickname = aprintf("PEM Token #1:%s", n);
421     if(nickname) {
422       cert = PK11_FindCertFromNickname(nickname, NULL);
423       if(cert)
424         CERT_DestroyCertificate(cert);
425
426       free(nickname);
427     }
428   }
429
430   return err;
431 }
432
433 /* add given CRL to cache if it is not already there */
434 static SECStatus nss_cache_crl(SECItem *crlDER)
435 {
436   CERTCertDBHandle *db = CERT_GetDefaultCertDB();
437   CERTSignedCrl *crl = SEC_FindCrlByDERCert(db, crlDER, 0);
438   if(crl) {
439     /* CRL already cached */
440     SEC_DestroyCrl(crl);
441     SECITEM_FreeItem(crlDER, PR_FALSE);
442     return SECSuccess;
443   }
444
445   /* acquire lock before call of CERT_CacheCRL() */
446   PR_Lock(nss_crllock);
447   if(SECSuccess != CERT_CacheCRL(db, crlDER)) {
448     /* unable to cache CRL */
449     PR_Unlock(nss_crllock);
450     SECITEM_FreeItem(crlDER, PR_FALSE);
451     return SECFailure;
452   }
453
454   /* we need to clear session cache, so that the CRL could take effect */
455   SSL_ClearSessionCache();
456   PR_Unlock(nss_crllock);
457   return SECSuccess;
458 }
459
460 static SECStatus nss_load_crl(const char* crlfilename)
461 {
462   PRFileDesc *infile;
463   PRFileInfo  info;
464   SECItem filedata = { 0, NULL, 0 };
465   SECItem crlDER = { 0, NULL, 0 };
466   char *body;
467
468   infile = PR_Open(crlfilename, PR_RDONLY, 0);
469   if(!infile)
470     return SECFailure;
471
472   if(PR_SUCCESS != PR_GetOpenFileInfo(infile, &info))
473     goto fail;
474
475   if(!SECITEM_AllocItem(NULL, &filedata, info.size + /* zero ended */ 1))
476     goto fail;
477
478   if(info.size != PR_Read(infile, filedata.data, info.size))
479     goto fail;
480
481   /* place a trailing zero right after the visible data */
482   body = (char*)filedata.data;
483   body[--filedata.len] = '\0';
484
485   body = strstr(body, "-----BEGIN");
486   if(body) {
487     /* assume ASCII */
488     char *trailer;
489     char *begin = PORT_Strchr(body, '\n');
490     if(!begin)
491       begin = PORT_Strchr(body, '\r');
492     if(!begin)
493       goto fail;
494
495     trailer = strstr(++begin, "-----END");
496     if(!trailer)
497       goto fail;
498
499     /* retrieve DER from ASCII */
500     *trailer = '\0';
501     if(ATOB_ConvertAsciiToItem(&crlDER, begin))
502       goto fail;
503
504     SECITEM_FreeItem(&filedata, PR_FALSE);
505   }
506   else
507     /* assume DER */
508     crlDER = filedata;
509
510   PR_Close(infile);
511   return nss_cache_crl(&crlDER);
512
513 fail:
514   PR_Close(infile);
515   SECITEM_FreeItem(&filedata, PR_FALSE);
516   return SECFailure;
517 }
518
519 static CURLcode nss_load_key(struct connectdata *conn, int sockindex,
520                              char *key_file)
521 {
522   PK11SlotInfo *slot;
523   SECStatus status;
524   CURLcode rv;
525   struct ssl_connect_data *ssl = conn->ssl;
526   (void)sockindex; /* unused */
527
528   rv = nss_create_object(ssl, CKO_PRIVATE_KEY, key_file, FALSE);
529   if(CURLE_OK != rv) {
530     PR_SetError(SEC_ERROR_BAD_KEY, 0);
531     return rv;
532   }
533
534   slot = PK11_FindSlotByName("PEM Token #1");
535   if(!slot)
536     return CURLE_SSL_CERTPROBLEM;
537
538   /* This will force the token to be seen as re-inserted */
539   SECMOD_WaitForAnyTokenEvent(mod, 0, 0);
540   PK11_IsPresent(slot);
541
542   status = PK11_Authenticate(slot, PR_TRUE,
543                              conn->data->set.str[STRING_KEY_PASSWD]);
544   PK11_FreeSlot(slot);
545   return (SECSuccess == status)
546     ? CURLE_OK
547     : CURLE_SSL_CERTPROBLEM;
548 }
549
550 static int display_error(struct connectdata *conn, PRInt32 err,
551                          const char *filename)
552 {
553   switch(err) {
554   case SEC_ERROR_BAD_PASSWORD:
555     failf(conn->data, "Unable to load client key: Incorrect password");
556     return 1;
557   case SEC_ERROR_UNKNOWN_CERT:
558     failf(conn->data, "Unable to load certificate %s", filename);
559     return 1;
560   default:
561     break;
562   }
563   return 0; /* The caller will print a generic error */
564 }
565
566 static CURLcode cert_stuff(struct connectdata *conn, int sockindex,
567                            char *cert_file, char *key_file)
568 {
569   struct SessionHandle *data = conn->data;
570   CURLcode rv;
571
572   if(cert_file) {
573     rv = nss_load_cert(&conn->ssl[sockindex], cert_file, PR_FALSE);
574     if(CURLE_OK != rv) {
575       const PRErrorCode err = PR_GetError();
576       if(!display_error(conn, err, cert_file)) {
577         const char *err_name = nss_error_to_name(err);
578         failf(data, "unable to load client cert: %d (%s)", err, err_name);
579       }
580
581       return rv;
582     }
583   }
584
585   if(key_file || (is_file(cert_file))) {
586     if(key_file)
587       rv = nss_load_key(conn, sockindex, key_file);
588     else
589       /* In case the cert file also has the key */
590       rv = nss_load_key(conn, sockindex, cert_file);
591     if(CURLE_OK != rv) {
592       const PRErrorCode err = PR_GetError();
593       if(!display_error(conn, err, key_file)) {
594         const char *err_name = nss_error_to_name(err);
595         failf(data, "unable to load client key: %d (%s)", err, err_name);
596       }
597
598       return rv;
599     }
600   }
601
602   return CURLE_OK;
603 }
604
605 static char * nss_get_password(PK11SlotInfo * slot, PRBool retry, void *arg)
606 {
607   (void)slot; /* unused */
608   if(retry || NULL == arg)
609     return NULL;
610   else
611     return (char *)PORT_Strdup((char *)arg);
612 }
613
614 /* bypass the default SSL_AuthCertificate() hook in case we do not want to
615  * verify peer */
616 static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig,
617                                     PRBool isServer)
618 {
619   struct connectdata *conn = (struct connectdata *)arg;
620   if(!conn->data->set.ssl.verifypeer) {
621     infof(conn->data, "skipping SSL peer certificate verification\n");
622     return SECSuccess;
623   }
624
625   return SSL_AuthCertificate(CERT_GetDefaultCertDB(), fd, checksig, isServer);
626 }
627
628 /**
629  * Inform the application that the handshake is complete.
630  */
631 static void HandshakeCallback(PRFileDesc *sock, void *arg)
632 {
633 #ifdef USE_NGHTTP2
634   struct connectdata *conn = (struct connectdata*) arg;
635   unsigned int buflenmax = 50;
636   unsigned char buf[50];
637   unsigned int buflen;
638   SSLNextProtoState state;
639
640   if(!conn->data->set.ssl_enable_npn && !conn->data->set.ssl_enable_alpn) {
641     return;
642   }
643
644   if(SSL_GetNextProto(sock, &state, buf, &buflen, buflenmax) == SECSuccess) {
645
646     switch(state) {
647       case SSL_NEXT_PROTO_NO_SUPPORT:
648       case SSL_NEXT_PROTO_NO_OVERLAP:
649         infof(conn->data, "TLS, neither ALPN nor NPN succeeded\n");
650         return;
651 #ifdef SSL_ENABLE_ALPN
652       case SSL_NEXT_PROTO_SELECTED:
653         infof(conn->data, "ALPN, server accepted to use %.*s\n", buflen, buf);
654         break;
655 #endif
656       case SSL_NEXT_PROTO_NEGOTIATED:
657         infof(conn->data, "NPN, server accepted to use %.*s\n", buflen, buf);
658         break;
659     }
660
661     if(buflen == NGHTTP2_PROTO_VERSION_ID_LEN &&
662        memcmp(NGHTTP2_PROTO_VERSION_ID, buf, NGHTTP2_PROTO_VERSION_ID_LEN)
663        == 0) {
664       conn->negnpn = NPN_HTTP2;
665     }
666     else if(buflen == ALPN_HTTP_1_1_LENGTH && memcmp(ALPN_HTTP_1_1, buf,
667                                                      ALPN_HTTP_1_1_LENGTH)) {
668       conn->negnpn = NPN_HTTP1_1;
669     }
670   }
671 #else
672   (void)sock;
673   (void)arg;
674 #endif
675 }
676
677 static void display_cert_info(struct SessionHandle *data,
678                               CERTCertificate *cert)
679 {
680   char *subject, *issuer, *common_name;
681   PRExplodedTime printableTime;
682   char timeString[256];
683   PRTime notBefore, notAfter;
684
685   subject = CERT_NameToAscii(&cert->subject);
686   issuer = CERT_NameToAscii(&cert->issuer);
687   common_name = CERT_GetCommonName(&cert->subject);
688   infof(data, "\tsubject: %s\n", subject);
689
690   CERT_GetCertTimes(cert, &notBefore, &notAfter);
691   PR_ExplodeTime(notBefore, PR_GMTParameters, &printableTime);
692   PR_FormatTime(timeString, 256, "%b %d %H:%M:%S %Y GMT", &printableTime);
693   infof(data, "\tstart date: %s\n", timeString);
694   PR_ExplodeTime(notAfter, PR_GMTParameters, &printableTime);
695   PR_FormatTime(timeString, 256, "%b %d %H:%M:%S %Y GMT", &printableTime);
696   infof(data, "\texpire date: %s\n", timeString);
697   infof(data, "\tcommon name: %s\n", common_name);
698   infof(data, "\tissuer: %s\n", issuer);
699
700   PR_Free(subject);
701   PR_Free(issuer);
702   PR_Free(common_name);
703 }
704
705 static void display_conn_info(struct connectdata *conn, PRFileDesc *sock)
706 {
707   SSLChannelInfo channel;
708   SSLCipherSuiteInfo suite;
709   CERTCertificate *cert;
710   CERTCertificate *cert2;
711   CERTCertificate *cert3;
712   PRTime now;
713   int i;
714
715   if(SSL_GetChannelInfo(sock, &channel, sizeof channel) ==
716      SECSuccess && channel.length == sizeof channel &&
717      channel.cipherSuite) {
718     if(SSL_GetCipherSuiteInfo(channel.cipherSuite,
719                               &suite, sizeof suite) == SECSuccess) {
720       infof(conn->data, "SSL connection using %s\n", suite.cipherSuiteName);
721     }
722   }
723
724   cert = SSL_PeerCertificate(sock);
725
726   if(cert) {
727     infof(conn->data, "Server certificate:\n");
728
729     if(!conn->data->set.ssl.certinfo) {
730       display_cert_info(conn->data, cert);
731       CERT_DestroyCertificate(cert);
732     }
733     else {
734       /* Count certificates in chain. */
735       now = PR_Now();
736       i = 1;
737       if(!cert->isRoot) {
738         cert2 = CERT_FindCertIssuer(cert, now, certUsageSSLCA);
739         while(cert2) {
740           i++;
741           if(cert2->isRoot) {
742             CERT_DestroyCertificate(cert2);
743             break;
744           }
745           cert3 = CERT_FindCertIssuer(cert2, now, certUsageSSLCA);
746           CERT_DestroyCertificate(cert2);
747           cert2 = cert3;
748         }
749       }
750       Curl_ssl_init_certinfo(conn->data, i);
751       for(i = 0; cert; cert = cert2) {
752         Curl_extract_certinfo(conn, i++, (char *)cert->derCert.data,
753                               (char *)cert->derCert.data + cert->derCert.len);
754         if(cert->isRoot) {
755           CERT_DestroyCertificate(cert);
756           break;
757         }
758         cert2 = CERT_FindCertIssuer(cert, now, certUsageSSLCA);
759         CERT_DestroyCertificate(cert);
760       }
761     }
762   }
763
764   return;
765 }
766
767 static SECStatus BadCertHandler(void *arg, PRFileDesc *sock)
768 {
769   struct connectdata *conn = (struct connectdata *)arg;
770   struct SessionHandle *data = conn->data;
771   PRErrorCode err = PR_GetError();
772   CERTCertificate *cert;
773
774   /* remember the cert verification result */
775   data->set.ssl.certverifyresult = err;
776
777   if(err == SSL_ERROR_BAD_CERT_DOMAIN && !data->set.ssl.verifyhost)
778     /* we are asked not to verify the host name */
779     return SECSuccess;
780
781   /* print only info about the cert, the error is printed off the callback */
782   cert = SSL_PeerCertificate(sock);
783   if(cert) {
784     infof(data, "Server certificate:\n");
785     display_cert_info(data, cert);
786     CERT_DestroyCertificate(cert);
787   }
788
789   return SECFailure;
790 }
791
792 /**
793  *
794  * Check that the Peer certificate's issuer certificate matches the one found
795  * by issuer_nickname.  This is not exactly the way OpenSSL and GNU TLS do the
796  * issuer check, so we provide comments that mimic the OpenSSL
797  * X509_check_issued function (in x509v3/v3_purp.c)
798  */
799 static SECStatus check_issuer_cert(PRFileDesc *sock,
800                                    char *issuer_nickname)
801 {
802   CERTCertificate *cert,*cert_issuer,*issuer;
803   SECStatus res=SECSuccess;
804   void *proto_win = NULL;
805
806   /*
807     PRArenaPool   *tmpArena = NULL;
808     CERTAuthKeyID *authorityKeyID = NULL;
809     SECITEM       *caname = NULL;
810   */
811
812   cert = SSL_PeerCertificate(sock);
813   cert_issuer = CERT_FindCertIssuer(cert,PR_Now(),certUsageObjectSigner);
814
815   proto_win = SSL_RevealPinArg(sock);
816   issuer = PK11_FindCertFromNickname(issuer_nickname, proto_win);
817
818   if((!cert_issuer) || (!issuer))
819     res = SECFailure;
820   else if(SECITEM_CompareItem(&cert_issuer->derCert,
821                               &issuer->derCert)!=SECEqual)
822     res = SECFailure;
823
824   CERT_DestroyCertificate(cert);
825   CERT_DestroyCertificate(issuer);
826   CERT_DestroyCertificate(cert_issuer);
827   return res;
828 }
829
830 /**
831  *
832  * Callback to pick the SSL client certificate.
833  */
834 static SECStatus SelectClientCert(void *arg, PRFileDesc *sock,
835                                   struct CERTDistNamesStr *caNames,
836                                   struct CERTCertificateStr **pRetCert,
837                                   struct SECKEYPrivateKeyStr **pRetKey)
838 {
839   struct ssl_connect_data *connssl = (struct ssl_connect_data *)arg;
840   struct SessionHandle *data = connssl->data;
841   const char *nickname = connssl->client_nickname;
842
843   if(connssl->obj_clicert) {
844     /* use the cert/key provided by PEM reader */
845     static const char pem_slotname[] = "PEM Token #1";
846     SECItem cert_der = { 0, NULL, 0 };
847     void *proto_win = SSL_RevealPinArg(sock);
848     struct CERTCertificateStr *cert;
849     struct SECKEYPrivateKeyStr *key;
850
851     PK11SlotInfo *slot = PK11_FindSlotByName(pem_slotname);
852     if(NULL == slot) {
853       failf(data, "NSS: PK11 slot not found: %s", pem_slotname);
854       return SECFailure;
855     }
856
857     if(PK11_ReadRawAttribute(PK11_TypeGeneric, connssl->obj_clicert, CKA_VALUE,
858                              &cert_der) != SECSuccess) {
859       failf(data, "NSS: CKA_VALUE not found in PK11 generic object");
860       PK11_FreeSlot(slot);
861       return SECFailure;
862     }
863
864     cert = PK11_FindCertFromDERCertItem(slot, &cert_der, proto_win);
865     SECITEM_FreeItem(&cert_der, PR_FALSE);
866     if(NULL == cert) {
867       failf(data, "NSS: client certificate from file not found");
868       PK11_FreeSlot(slot);
869       return SECFailure;
870     }
871
872     key = PK11_FindPrivateKeyFromCert(slot, cert, NULL);
873     PK11_FreeSlot(slot);
874     if(NULL == key) {
875       failf(data, "NSS: private key from file not found");
876       CERT_DestroyCertificate(cert);
877       return SECFailure;
878     }
879
880     infof(data, "NSS: client certificate from file\n");
881     display_cert_info(data, cert);
882
883     *pRetCert = cert;
884     *pRetKey = key;
885     return SECSuccess;
886   }
887
888   /* use the default NSS hook */
889   if(SECSuccess != NSS_GetClientAuthData((void *)nickname, sock, caNames,
890                                           pRetCert, pRetKey)
891       || NULL == *pRetCert) {
892
893     if(NULL == nickname)
894       failf(data, "NSS: client certificate not found (nickname not "
895             "specified)");
896     else
897       failf(data, "NSS: client certificate not found: %s", nickname);
898
899     return SECFailure;
900   }
901
902   /* get certificate nickname if any */
903   nickname = (*pRetCert)->nickname;
904   if(NULL == nickname)
905     nickname = "[unknown]";
906
907   if(NULL == *pRetKey) {
908     failf(data, "NSS: private key not found for certificate: %s", nickname);
909     return SECFailure;
910   }
911
912   infof(data, "NSS: using client certificate: %s\n", nickname);
913   display_cert_info(data, *pRetCert);
914   return SECSuccess;
915 }
916
917 /* This function is supposed to decide, which error codes should be used
918  * to conclude server is TLS intolerant.
919  *
920  * taken from xulrunner - nsNSSIOLayer.cpp
921  */
922 static PRBool
923 isTLSIntoleranceError(PRInt32 err)
924 {
925   switch (err) {
926   case SSL_ERROR_BAD_MAC_ALERT:
927   case SSL_ERROR_BAD_MAC_READ:
928   case SSL_ERROR_HANDSHAKE_FAILURE_ALERT:
929   case SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT:
930   case SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE:
931   case SSL_ERROR_ILLEGAL_PARAMETER_ALERT:
932   case SSL_ERROR_NO_CYPHER_OVERLAP:
933   case SSL_ERROR_BAD_SERVER:
934   case SSL_ERROR_BAD_BLOCK_PADDING:
935   case SSL_ERROR_UNSUPPORTED_VERSION:
936   case SSL_ERROR_PROTOCOL_VERSION_ALERT:
937   case SSL_ERROR_RX_MALFORMED_FINISHED:
938   case SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE:
939   case SSL_ERROR_DECODE_ERROR_ALERT:
940   case SSL_ERROR_RX_UNKNOWN_ALERT:
941     return PR_TRUE;
942   default:
943     return PR_FALSE;
944   }
945 }
946
947 /* update blocking direction in case of PR_WOULD_BLOCK_ERROR */
948 static void nss_update_connecting_state(ssl_connect_state state, void *secret)
949 {
950   struct ssl_connect_data *connssl = (struct ssl_connect_data *)secret;
951   if(PR_GetError() != PR_WOULD_BLOCK_ERROR)
952     /* an unrelated error is passing by */
953     return;
954
955   switch(connssl->connecting_state) {
956   case ssl_connect_2:
957   case ssl_connect_2_reading:
958   case ssl_connect_2_writing:
959     break;
960   default:
961     /* we are not called from an SSL handshake */
962     return;
963   }
964
965   /* update the state accordingly */
966   connssl->connecting_state = state;
967 }
968
969 /* recv() wrapper we use to detect blocking direction during SSL handshake */
970 static PRInt32 nspr_io_recv(PRFileDesc *fd, void *buf, PRInt32 amount,
971                             PRIntn flags, PRIntervalTime timeout)
972 {
973   const PRRecvFN recv_fn = fd->lower->methods->recv;
974   const PRInt32 rv = recv_fn(fd->lower, buf, amount, flags, timeout);
975   if(rv < 0)
976     /* check for PR_WOULD_BLOCK_ERROR and update blocking direction */
977     nss_update_connecting_state(ssl_connect_2_reading, fd->secret);
978   return rv;
979 }
980
981 /* send() wrapper we use to detect blocking direction during SSL handshake */
982 static PRInt32 nspr_io_send(PRFileDesc *fd, const void *buf, PRInt32 amount,
983                             PRIntn flags, PRIntervalTime timeout)
984 {
985   const PRSendFN send_fn = fd->lower->methods->send;
986   const PRInt32 rv = send_fn(fd->lower, buf, amount, flags, timeout);
987   if(rv < 0)
988     /* check for PR_WOULD_BLOCK_ERROR and update blocking direction */
989     nss_update_connecting_state(ssl_connect_2_writing, fd->secret);
990   return rv;
991 }
992
993 /* close() wrapper to avoid assertion failure due to fd->secret != NULL */
994 static PRStatus nspr_io_close(PRFileDesc *fd)
995 {
996   const PRCloseFN close_fn = PR_GetDefaultIOMethods()->close;
997   fd->secret = NULL;
998   return close_fn(fd);
999 }
1000
1001 static CURLcode nss_init_core(struct SessionHandle *data, const char *cert_dir)
1002 {
1003   NSSInitParameters initparams;
1004
1005   if(nss_context != NULL)
1006     return CURLE_OK;
1007
1008   memset((void *) &initparams, '\0', sizeof(initparams));
1009   initparams.length = sizeof(initparams);
1010
1011   if(cert_dir) {
1012     const bool use_sql = NSS_VersionCheck("3.12.0");
1013     char *certpath = aprintf("%s%s", use_sql ? "sql:" : "", cert_dir);
1014     if(!certpath)
1015       return CURLE_OUT_OF_MEMORY;
1016
1017     infof(data, "Initializing NSS with certpath: %s\n", certpath);
1018     nss_context = NSS_InitContext(certpath, "", "", "", &initparams,
1019             NSS_INIT_READONLY | NSS_INIT_PK11RELOAD);
1020     free(certpath);
1021
1022     if(nss_context != NULL)
1023       return CURLE_OK;
1024
1025     infof(data, "Unable to initialize NSS database\n");
1026   }
1027
1028   infof(data, "Initializing NSS with certpath: none\n");
1029   nss_context = NSS_InitContext("", "", "", "", &initparams, NSS_INIT_READONLY
1030          | NSS_INIT_NOCERTDB   | NSS_INIT_NOMODDB       | NSS_INIT_FORCEOPEN
1031          | NSS_INIT_NOROOTINIT | NSS_INIT_OPTIMIZESPACE | NSS_INIT_PK11RELOAD);
1032   if(nss_context != NULL)
1033     return CURLE_OK;
1034
1035   infof(data, "Unable to initialize NSS\n");
1036   return CURLE_SSL_CACERT_BADFILE;
1037 }
1038
1039 static CURLcode nss_init(struct SessionHandle *data)
1040 {
1041   char *cert_dir;
1042   struct_stat st;
1043   CURLcode rv;
1044
1045   if(initialized)
1046     return CURLE_OK;
1047
1048   /* First we check if $SSL_DIR points to a valid dir */
1049   cert_dir = getenv("SSL_DIR");
1050   if(cert_dir) {
1051     if((stat(cert_dir, &st) != 0) ||
1052         (!S_ISDIR(st.st_mode))) {
1053       cert_dir = NULL;
1054     }
1055   }
1056
1057   /* Now we check if the default location is a valid dir */
1058   if(!cert_dir) {
1059     if((stat(SSL_DIR, &st) == 0) &&
1060         (S_ISDIR(st.st_mode))) {
1061       cert_dir = (char *)SSL_DIR;
1062     }
1063   }
1064
1065   if(nspr_io_identity == PR_INVALID_IO_LAYER) {
1066     /* allocate an identity for our own NSPR I/O layer */
1067     nspr_io_identity = PR_GetUniqueIdentity("libcurl");
1068     if(nspr_io_identity == PR_INVALID_IO_LAYER)
1069       return CURLE_OUT_OF_MEMORY;
1070
1071     /* the default methods just call down to the lower I/O layer */
1072     memcpy(&nspr_io_methods, PR_GetDefaultIOMethods(), sizeof nspr_io_methods);
1073
1074     /* override certain methods in the table by our wrappers */
1075     nspr_io_methods.recv  = nspr_io_recv;
1076     nspr_io_methods.send  = nspr_io_send;
1077     nspr_io_methods.close = nspr_io_close;
1078   }
1079
1080   rv = nss_init_core(data, cert_dir);
1081   if(rv)
1082     return rv;
1083
1084   if(num_enabled_ciphers() == 0)
1085     NSS_SetDomesticPolicy();
1086
1087   initialized = 1;
1088   return CURLE_OK;
1089 }
1090
1091 /**
1092  * Global SSL init
1093  *
1094  * @retval 0 error initializing SSL
1095  * @retval 1 SSL initialized successfully
1096  */
1097 int Curl_nss_init(void)
1098 {
1099   /* curl_global_init() is not thread-safe so this test is ok */
1100   if(nss_initlock == NULL) {
1101     PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 256);
1102     nss_initlock = PR_NewLock();
1103     nss_crllock = PR_NewLock();
1104   }
1105
1106   /* We will actually initialize NSS later */
1107
1108   return 1;
1109 }
1110
1111 CURLcode Curl_nss_force_init(struct SessionHandle *data)
1112 {
1113   CURLcode rv;
1114   if(!nss_initlock) {
1115     failf(data,
1116           "unable to initialize NSS, curl_global_init() should have been "
1117           "called with CURL_GLOBAL_SSL or CURL_GLOBAL_ALL");
1118     return CURLE_FAILED_INIT;
1119   }
1120
1121   PR_Lock(nss_initlock);
1122   rv = nss_init(data);
1123   PR_Unlock(nss_initlock);
1124   return rv;
1125 }
1126
1127 /* Global cleanup */
1128 void Curl_nss_cleanup(void)
1129 {
1130   /* This function isn't required to be threadsafe and this is only done
1131    * as a safety feature.
1132    */
1133   PR_Lock(nss_initlock);
1134   if(initialized) {
1135     /* Free references to client certificates held in the SSL session cache.
1136      * Omitting this hampers destruction of the security module owning
1137      * the certificates. */
1138     SSL_ClearSessionCache();
1139
1140     if(mod && SECSuccess == SECMOD_UnloadUserModule(mod)) {
1141       SECMOD_DestroyModule(mod);
1142       mod = NULL;
1143     }
1144     NSS_ShutdownContext(nss_context);
1145     nss_context = NULL;
1146   }
1147   PR_Unlock(nss_initlock);
1148
1149   PR_DestroyLock(nss_initlock);
1150   PR_DestroyLock(nss_crllock);
1151   nss_initlock = NULL;
1152
1153   initialized = 0;
1154 }
1155
1156 /*
1157  * This function uses SSL_peek to determine connection status.
1158  *
1159  * Return codes:
1160  *     1 means the connection is still in place
1161  *     0 means the connection has been closed
1162  *    -1 means the connection status is unknown
1163  */
1164 int
1165 Curl_nss_check_cxn(struct connectdata *conn)
1166 {
1167   int rc;
1168   char buf;
1169
1170   rc =
1171     PR_Recv(conn->ssl[FIRSTSOCKET].handle, (void *)&buf, 1, PR_MSG_PEEK,
1172             PR_SecondsToInterval(1));
1173   if(rc > 0)
1174     return 1; /* connection still in place */
1175
1176   if(rc == 0)
1177     return 0; /* connection has been closed */
1178
1179   return -1;  /* connection status unknown */
1180 }
1181
1182 /*
1183  * This function is called when an SSL connection is closed.
1184  */
1185 void Curl_nss_close(struct connectdata *conn, int sockindex)
1186 {
1187   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1188
1189   if(connssl->handle) {
1190     /* NSS closes the socket we previously handed to it, so we must mark it
1191        as closed to avoid double close */
1192     fake_sclose(conn->sock[sockindex]);
1193     conn->sock[sockindex] = CURL_SOCKET_BAD;
1194
1195     if((connssl->client_nickname != NULL) || (connssl->obj_clicert != NULL))
1196       /* A server might require different authentication based on the
1197        * particular path being requested by the client.  To support this
1198        * scenario, we must ensure that a connection will never reuse the
1199        * authentication data from a previous connection. */
1200       SSL_InvalidateSession(connssl->handle);
1201
1202     if(connssl->client_nickname != NULL) {
1203       free(connssl->client_nickname);
1204       connssl->client_nickname = NULL;
1205     }
1206     /* destroy all NSS objects in order to avoid failure of NSS shutdown */
1207     Curl_llist_destroy(connssl->obj_list, NULL);
1208     connssl->obj_list = NULL;
1209     connssl->obj_clicert = NULL;
1210
1211     PR_Close(connssl->handle);
1212     connssl->handle = NULL;
1213   }
1214 }
1215
1216 /*
1217  * This function is called when the 'data' struct is going away. Close
1218  * down everything and free all resources!
1219  */
1220 int Curl_nss_close_all(struct SessionHandle *data)
1221 {
1222   (void)data;
1223   return 0;
1224 }
1225
1226 /* return true if NSS can provide error code (and possibly msg) for the
1227    error */
1228 static bool is_nss_error(CURLcode err)
1229 {
1230   switch(err) {
1231   case CURLE_PEER_FAILED_VERIFICATION:
1232   case CURLE_SSL_CACERT:
1233   case CURLE_SSL_CERTPROBLEM:
1234   case CURLE_SSL_CONNECT_ERROR:
1235   case CURLE_SSL_ISSUER_ERROR:
1236     return true;
1237
1238   default:
1239     return false;
1240   }
1241 }
1242
1243 /* return true if the given error code is related to a client certificate */
1244 static bool is_cc_error(PRInt32 err)
1245 {
1246   switch(err) {
1247   case SSL_ERROR_BAD_CERT_ALERT:
1248   case SSL_ERROR_EXPIRED_CERT_ALERT:
1249   case SSL_ERROR_REVOKED_CERT_ALERT:
1250     return true;
1251
1252   default:
1253     return false;
1254   }
1255 }
1256
1257 static Curl_recv nss_recv;
1258 static Curl_send nss_send;
1259
1260 static CURLcode nss_load_ca_certificates(struct connectdata *conn,
1261                                          int sockindex)
1262 {
1263   struct SessionHandle *data = conn->data;
1264   const char *cafile = data->set.ssl.CAfile;
1265   const char *capath = data->set.ssl.CApath;
1266
1267   if(cafile) {
1268     CURLcode rv = nss_load_cert(&conn->ssl[sockindex], cafile, PR_TRUE);
1269     if(CURLE_OK != rv)
1270       return rv;
1271   }
1272
1273   if(capath) {
1274     struct_stat st;
1275     if(stat(capath, &st) == -1)
1276       return CURLE_SSL_CACERT_BADFILE;
1277
1278     if(S_ISDIR(st.st_mode)) {
1279       PRDirEntry *entry;
1280       PRDir *dir = PR_OpenDir(capath);
1281       if(!dir)
1282         return CURLE_SSL_CACERT_BADFILE;
1283
1284       while((entry = PR_ReadDir(dir, PR_SKIP_BOTH | PR_SKIP_HIDDEN))) {
1285         char *fullpath = aprintf("%s/%s", capath, entry->name);
1286         if(!fullpath) {
1287           PR_CloseDir(dir);
1288           return CURLE_OUT_OF_MEMORY;
1289         }
1290
1291         if(CURLE_OK != nss_load_cert(&conn->ssl[sockindex], fullpath, PR_TRUE))
1292           /* This is purposefully tolerant of errors so non-PEM files can
1293            * be in the same directory */
1294           infof(data, "failed to load '%s' from CURLOPT_CAPATH\n", fullpath);
1295
1296         free(fullpath);
1297       }
1298
1299       PR_CloseDir(dir);
1300     }
1301     else
1302       infof(data, "warning: CURLOPT_CAPATH not a directory (%s)\n", capath);
1303   }
1304
1305   infof(data, "  CAfile: %s\n  CApath: %s\n",
1306       cafile ? cafile : "none",
1307       capath ? capath : "none");
1308
1309   return CURLE_OK;
1310 }
1311
1312 static CURLcode nss_init_sslver(SSLVersionRange *sslver,
1313                                 struct SessionHandle *data)
1314 {
1315   switch (data->set.ssl.version) {
1316   default:
1317   case CURL_SSLVERSION_DEFAULT:
1318     sslver->min = SSL_LIBRARY_VERSION_3_0;
1319     if(data->state.ssl_connect_retry) {
1320       infof(data, "TLS disabled due to previous handshake failure\n");
1321       sslver->max = SSL_LIBRARY_VERSION_3_0;
1322       return CURLE_OK;
1323     }
1324   /* intentional fall-through to default to highest TLS version if possible */
1325
1326   case CURL_SSLVERSION_TLSv1:
1327 #ifdef SSL_LIBRARY_VERSION_TLS_1_2
1328     sslver->max = SSL_LIBRARY_VERSION_TLS_1_2;
1329 #elif defined SSL_LIBRARY_VERSION_TLS_1_1
1330     sslver->max = SSL_LIBRARY_VERSION_TLS_1_1;
1331 #else
1332     sslver->max = SSL_LIBRARY_VERSION_TLS_1_0;
1333 #endif
1334     return CURLE_OK;
1335
1336   case CURL_SSLVERSION_SSLv2:
1337     sslver->min = SSL_LIBRARY_VERSION_2;
1338     sslver->max = SSL_LIBRARY_VERSION_2;
1339     return CURLE_OK;
1340
1341   case CURL_SSLVERSION_SSLv3:
1342     sslver->min = SSL_LIBRARY_VERSION_3_0;
1343     sslver->max = SSL_LIBRARY_VERSION_3_0;
1344     return CURLE_OK;
1345
1346   case CURL_SSLVERSION_TLSv1_0:
1347     sslver->min = SSL_LIBRARY_VERSION_TLS_1_0;
1348     sslver->max = SSL_LIBRARY_VERSION_TLS_1_0;
1349     return CURLE_OK;
1350
1351   case CURL_SSLVERSION_TLSv1_1:
1352 #ifdef SSL_LIBRARY_VERSION_TLS_1_1
1353     sslver->min = SSL_LIBRARY_VERSION_TLS_1_1;
1354     sslver->max = SSL_LIBRARY_VERSION_TLS_1_1;
1355     return CURLE_OK;
1356 #endif
1357     break;
1358
1359   case CURL_SSLVERSION_TLSv1_2:
1360 #ifdef SSL_LIBRARY_VERSION_TLS_1_2
1361     sslver->min = SSL_LIBRARY_VERSION_TLS_1_2;
1362     sslver->max = SSL_LIBRARY_VERSION_TLS_1_2;
1363     return CURLE_OK;
1364 #endif
1365     break;
1366   }
1367
1368   failf(data, "TLS minor version cannot be set");
1369   return CURLE_SSL_CONNECT_ERROR;
1370 }
1371
1372 static CURLcode nss_fail_connect(struct ssl_connect_data *connssl,
1373                                  struct SessionHandle *data,
1374                                  CURLcode curlerr)
1375 {
1376   SSLVersionRange sslver;
1377   PRErrorCode err = 0;
1378
1379   /* reset the flag to avoid an infinite loop */
1380   data->state.ssl_connect_retry = FALSE;
1381
1382   if(is_nss_error(curlerr)) {
1383     /* read NSPR error code */
1384     err = PR_GetError();
1385     if(is_cc_error(err))
1386       curlerr = CURLE_SSL_CERTPROBLEM;
1387
1388     /* print the error number and error string */
1389     infof(data, "NSS error %d (%s)\n", err, nss_error_to_name(err));
1390
1391     /* print a human-readable message describing the error if available */
1392     nss_print_error_message(data, err);
1393   }
1394
1395   /* cleanup on connection failure */
1396   Curl_llist_destroy(connssl->obj_list, NULL);
1397   connssl->obj_list = NULL;
1398
1399   if(connssl->handle
1400       && (SSL_VersionRangeGet(connssl->handle, &sslver) == SECSuccess)
1401       && (sslver.min == SSL_LIBRARY_VERSION_3_0)
1402       && (sslver.max != SSL_LIBRARY_VERSION_3_0)
1403       && isTLSIntoleranceError(err)) {
1404     /* schedule reconnect through Curl_retry_request() */
1405     data->state.ssl_connect_retry = TRUE;
1406     infof(data, "Error in TLS handshake, trying SSLv3...\n");
1407     return CURLE_OK;
1408   }
1409
1410   return curlerr;
1411 }
1412
1413 /* Switch the SSL socket into non-blocking mode. */
1414 static CURLcode nss_set_nonblock(struct ssl_connect_data *connssl,
1415                                  struct SessionHandle *data)
1416 {
1417   static PRSocketOptionData sock_opt;
1418   sock_opt.option = PR_SockOpt_Nonblocking;
1419   sock_opt.value.non_blocking = PR_TRUE;
1420
1421   if(PR_SetSocketOption(connssl->handle, &sock_opt) != PR_SUCCESS)
1422     return nss_fail_connect(connssl, data, CURLE_SSL_CONNECT_ERROR);
1423
1424   return CURLE_OK;
1425 }
1426
1427 static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
1428 {
1429   PRFileDesc *model = NULL;
1430   PRFileDesc *nspr_io = NULL;
1431   PRFileDesc *nspr_io_stub = NULL;
1432   PRBool ssl_no_cache;
1433   PRBool ssl_cbc_random_iv;
1434   struct SessionHandle *data = conn->data;
1435   curl_socket_t sockfd = conn->sock[sockindex];
1436   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1437   CURLcode curlerr;
1438
1439   SSLVersionRange sslver = {
1440     SSL_LIBRARY_VERSION_TLS_1_0,  /* min */
1441     SSL_LIBRARY_VERSION_TLS_1_0   /* max */
1442   };
1443
1444 #ifdef USE_NGHTTP2
1445 #if defined(SSL_ENABLE_NPN) || defined(SSL_ENABLE_ALPN)
1446   unsigned int alpn_protos_len = NGHTTP2_PROTO_VERSION_ID_LEN +
1447       ALPN_HTTP_1_1_LENGTH + 2;
1448   unsigned char alpn_protos[NGHTTP2_PROTO_VERSION_ID_LEN + ALPN_HTTP_1_1_LENGTH
1449       + 2];
1450   int cur = 0;
1451 #endif
1452 #endif
1453
1454
1455   if(connssl->state == ssl_connection_complete)
1456     return CURLE_OK;
1457
1458   connssl->data = data;
1459
1460   /* list of all NSS objects we need to destroy in Curl_nss_close() */
1461   connssl->obj_list = Curl_llist_alloc(nss_destroy_object);
1462   if(!connssl->obj_list)
1463     return CURLE_OUT_OF_MEMORY;
1464
1465   /* FIXME. NSS doesn't support multiple databases open at the same time. */
1466   PR_Lock(nss_initlock);
1467   curlerr = nss_init(conn->data);
1468   if(CURLE_OK != curlerr) {
1469     PR_Unlock(nss_initlock);
1470     goto error;
1471   }
1472
1473   curlerr = CURLE_SSL_CONNECT_ERROR;
1474
1475   if(!mod) {
1476     char *configstring = aprintf("library=%s name=PEM", pem_library);
1477     if(!configstring) {
1478       PR_Unlock(nss_initlock);
1479       goto error;
1480     }
1481     mod = SECMOD_LoadUserModule(configstring, NULL, PR_FALSE);
1482     free(configstring);
1483
1484     if(!mod || !mod->loaded) {
1485       if(mod) {
1486         SECMOD_DestroyModule(mod);
1487         mod = NULL;
1488       }
1489       infof(data, "WARNING: failed to load NSS PEM library %s. Using "
1490             "OpenSSL PEM certificates will not work.\n", pem_library);
1491     }
1492   }
1493
1494   PK11_SetPasswordFunc(nss_get_password);
1495   PR_Unlock(nss_initlock);
1496
1497   model = PR_NewTCPSocket();
1498   if(!model)
1499     goto error;
1500   model = SSL_ImportFD(NULL, model);
1501
1502   if(SSL_OptionSet(model, SSL_SECURITY, PR_TRUE) != SECSuccess)
1503     goto error;
1504   if(SSL_OptionSet(model, SSL_HANDSHAKE_AS_SERVER, PR_FALSE) != SECSuccess)
1505     goto error;
1506   if(SSL_OptionSet(model, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE) != SECSuccess)
1507     goto error;
1508
1509   /* do not use SSL cache if disabled or we are not going to verify peer */
1510   ssl_no_cache = (conn->ssl_config.sessionid && data->set.ssl.verifypeer) ?
1511     PR_FALSE : PR_TRUE;
1512   if(SSL_OptionSet(model, SSL_NO_CACHE, ssl_no_cache) != SECSuccess)
1513     goto error;
1514
1515   /* enable/disable the requested SSL version(s) */
1516   if(nss_init_sslver(&sslver, data) != CURLE_OK)
1517     goto error;
1518   if(SSL_VersionRangeSet(model, &sslver) != SECSuccess)
1519     goto error;
1520
1521   ssl_cbc_random_iv = !data->set.ssl_enable_beast;
1522 #ifdef SSL_CBC_RANDOM_IV
1523   /* unless the user explicitly asks to allow the protocol vulnerability, we
1524      use the work-around */
1525   if(SSL_OptionSet(model, SSL_CBC_RANDOM_IV, ssl_cbc_random_iv) != SECSuccess)
1526     infof(data, "warning: failed to set SSL_CBC_RANDOM_IV = %d\n",
1527           ssl_cbc_random_iv);
1528 #else
1529   if(ssl_cbc_random_iv)
1530     infof(data, "warning: support for SSL_CBC_RANDOM_IV not compiled in\n");
1531 #endif
1532
1533   /* reset the flag to avoid an infinite loop */
1534   data->state.ssl_connect_retry = FALSE;
1535
1536   if(data->set.ssl.cipher_list) {
1537     if(set_ciphers(data, model, data->set.ssl.cipher_list) != SECSuccess) {
1538       curlerr = CURLE_SSL_CIPHER;
1539       goto error;
1540     }
1541   }
1542
1543   if(!data->set.ssl.verifypeer && data->set.ssl.verifyhost)
1544     infof(data, "warning: ignoring value of ssl.verifyhost\n");
1545
1546   /* bypass the default SSL_AuthCertificate() hook in case we do not want to
1547    * verify peer */
1548   if(SSL_AuthCertificateHook(model, nss_auth_cert_hook, conn) != SECSuccess)
1549     goto error;
1550
1551   data->set.ssl.certverifyresult=0; /* not checked yet */
1552   if(SSL_BadCertHook(model, BadCertHandler, conn) != SECSuccess)
1553     goto error;
1554
1555   if(SSL_HandshakeCallback(model, HandshakeCallback, conn) != SECSuccess)
1556     goto error;
1557
1558   if(data->set.ssl.verifypeer) {
1559     const CURLcode rv = nss_load_ca_certificates(conn, sockindex);
1560     if(CURLE_OK != rv) {
1561       curlerr = rv;
1562       goto error;
1563     }
1564   }
1565
1566   if(data->set.ssl.CRLfile) {
1567     if(SECSuccess != nss_load_crl(data->set.ssl.CRLfile)) {
1568       curlerr = CURLE_SSL_CRL_BADFILE;
1569       goto error;
1570     }
1571     infof(data,
1572           "  CRLfile: %s\n",
1573           data->set.ssl.CRLfile ? data->set.ssl.CRLfile : "none");
1574   }
1575
1576   if(data->set.str[STRING_CERT]) {
1577     char *nickname = dup_nickname(data, STRING_CERT);
1578     if(nickname) {
1579       /* we are not going to use libnsspem.so to read the client cert */
1580       connssl->obj_clicert = NULL;
1581     }
1582     else {
1583       CURLcode rv = cert_stuff(conn, sockindex, data->set.str[STRING_CERT],
1584                                data->set.str[STRING_KEY]);
1585       if(CURLE_OK != rv) {
1586         /* failf() is already done in cert_stuff() */
1587         curlerr = rv;
1588         goto error;
1589       }
1590     }
1591
1592     /* store the nickname for SelectClientCert() called during handshake */
1593     connssl->client_nickname = nickname;
1594   }
1595   else
1596     connssl->client_nickname = NULL;
1597
1598   if(SSL_GetClientAuthDataHook(model, SelectClientCert,
1599                                (void *)connssl) != SECSuccess) {
1600     curlerr = CURLE_SSL_CERTPROBLEM;
1601     goto error;
1602   }
1603
1604   /* wrap OS file descriptor by NSPR's file descriptor abstraction */
1605   nspr_io = PR_ImportTCPSocket(sockfd);
1606   if(!nspr_io)
1607     goto error;
1608
1609   /* create our own NSPR I/O layer */
1610   nspr_io_stub = PR_CreateIOLayerStub(nspr_io_identity, &nspr_io_methods);
1611   if(!nspr_io_stub) {
1612     PR_Close(nspr_io);
1613     goto error;
1614   }
1615
1616   /* make the per-connection data accessible from NSPR I/O callbacks */
1617   nspr_io_stub->secret = (void *)connssl;
1618
1619   /* push our new layer to the NSPR I/O stack */
1620   if(PR_PushIOLayer(nspr_io, PR_TOP_IO_LAYER, nspr_io_stub) != PR_SUCCESS) {
1621     PR_Close(nspr_io);
1622     PR_Close(nspr_io_stub);
1623     goto error;
1624   }
1625
1626   /* import our model socket onto the current I/O stack */
1627   connssl->handle = SSL_ImportFD(model, nspr_io);
1628   if(!connssl->handle) {
1629     PR_Close(nspr_io);
1630     goto error;
1631   }
1632
1633   PR_Close(model); /* We don't need this any more */
1634   model = NULL;
1635
1636   /* This is the password associated with the cert that we're using */
1637   if(data->set.str[STRING_KEY_PASSWD]) {
1638     SSL_SetPKCS11PinArg(connssl->handle, data->set.str[STRING_KEY_PASSWD]);
1639   }
1640
1641 #ifdef USE_NGHTTP2
1642   if(data->set.httpversion == CURL_HTTP_VERSION_2_0) {
1643 #ifdef SSL_ENABLE_NPN
1644     if(data->set.ssl_enable_npn) {
1645       if(SSL_OptionSet(connssl->handle, SSL_ENABLE_NPN, PR_TRUE) != SECSuccess)
1646         goto error;
1647     }
1648 #endif
1649
1650 #ifdef SSL_ENABLE_ALPN
1651     if(data->set.ssl_enable_alpn) {
1652       if(SSL_OptionSet(connssl->handle, SSL_ENABLE_ALPN, PR_TRUE)
1653           != SECSuccess)
1654         goto error;
1655     }
1656 #endif
1657
1658 #if defined(SSL_ENABLE_NPN) || defined(SSL_ENABLE_ALPN)
1659     if(data->set.ssl_enable_npn || data->set.ssl_enable_alpn) {
1660       alpn_protos[cur] = NGHTTP2_PROTO_VERSION_ID_LEN;
1661       cur++;
1662       memcpy(&alpn_protos[cur], NGHTTP2_PROTO_VERSION_ID,
1663           NGHTTP2_PROTO_VERSION_ID_LEN);
1664       cur += NGHTTP2_PROTO_VERSION_ID_LEN;
1665       alpn_protos[cur] = ALPN_HTTP_1_1_LENGTH;
1666       cur++;
1667       memcpy(&alpn_protos[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH);
1668
1669       if(SSL_SetNextProtoNego(connssl->handle, alpn_protos, alpn_protos_len)
1670           != SECSuccess)
1671         goto error;
1672     }
1673     else {
1674       infof(data, "SSL, can't negotiate HTTP/2.0 with neither NPN nor ALPN\n");
1675     }
1676 #endif
1677   }
1678 #endif
1679
1680
1681   /* Force handshake on next I/O */
1682   SSL_ResetHandshake(connssl->handle, /* asServer */ PR_FALSE);
1683
1684   SSL_SetURL(connssl->handle, conn->host.name);
1685
1686   return CURLE_OK;
1687
1688 error:
1689   if(model)
1690     PR_Close(model);
1691
1692   return nss_fail_connect(connssl, data, curlerr);
1693 }
1694
1695 static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
1696 {
1697   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1698   struct SessionHandle *data = conn->data;
1699   CURLcode curlerr = CURLE_SSL_CONNECT_ERROR;
1700   PRUint32 timeout;
1701
1702   /* check timeout situation */
1703   const long time_left = Curl_timeleft(data, NULL, TRUE);
1704   if(time_left < 0L) {
1705     failf(data, "timed out before SSL handshake");
1706     curlerr = CURLE_OPERATION_TIMEDOUT;
1707     goto error;
1708   }
1709
1710   /* Force the handshake now */
1711   timeout = PR_MillisecondsToInterval((PRUint32) time_left);
1712   if(SSL_ForceHandshakeWithTimeout(connssl->handle, timeout) != SECSuccess) {
1713     if(PR_GetError() == PR_WOULD_BLOCK_ERROR)
1714       /* blocking direction is updated by nss_update_connecting_state() */
1715       return CURLE_AGAIN;
1716     else if(conn->data->set.ssl.certverifyresult == SSL_ERROR_BAD_CERT_DOMAIN)
1717       curlerr = CURLE_PEER_FAILED_VERIFICATION;
1718     else if(conn->data->set.ssl.certverifyresult!=0)
1719       curlerr = CURLE_SSL_CACERT;
1720     goto error;
1721   }
1722
1723   connssl->state = ssl_connection_complete;
1724   conn->recv[sockindex] = nss_recv;
1725   conn->send[sockindex] = nss_send;
1726
1727   display_conn_info(conn, connssl->handle);
1728
1729   if(data->set.str[STRING_SSL_ISSUERCERT]) {
1730     SECStatus ret = SECFailure;
1731     char *nickname = dup_nickname(data, STRING_SSL_ISSUERCERT);
1732     if(nickname) {
1733       /* we support only nicknames in case of STRING_SSL_ISSUERCERT for now */
1734       ret = check_issuer_cert(connssl->handle, nickname);
1735       free(nickname);
1736     }
1737
1738     if(SECFailure == ret) {
1739       infof(data,"SSL certificate issuer check failed\n");
1740       curlerr = CURLE_SSL_ISSUER_ERROR;
1741       goto error;
1742     }
1743     else {
1744       infof(data, "SSL certificate issuer check ok\n");
1745     }
1746   }
1747
1748   return CURLE_OK;
1749
1750 error:
1751   return nss_fail_connect(connssl, data, curlerr);
1752 }
1753
1754 static CURLcode nss_connect_common(struct connectdata *conn, int sockindex,
1755                                    bool *done)
1756 {
1757   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1758   struct SessionHandle *data = conn->data;
1759   const bool blocking = (done == NULL);
1760   CURLcode rv;
1761
1762   if(connssl->connecting_state == ssl_connect_1) {
1763     rv = nss_setup_connect(conn, sockindex);
1764     if(rv)
1765       /* we do not expect CURLE_AGAIN from nss_setup_connect() */
1766       return rv;
1767
1768     if(!blocking) {
1769       /* in non-blocking mode, set NSS non-blocking mode before handshake */
1770       rv = nss_set_nonblock(connssl, data);
1771       if(rv)
1772         return rv;
1773     }
1774
1775     connssl->connecting_state = ssl_connect_2;
1776   }
1777
1778   rv = nss_do_connect(conn, sockindex);
1779   switch(rv) {
1780   case CURLE_OK:
1781     break;
1782   case CURLE_AGAIN:
1783     if(!blocking)
1784       /* CURLE_AGAIN in non-blocking mode is not an error */
1785       return CURLE_OK;
1786     /* fall through */
1787   default:
1788     return rv;
1789   }
1790
1791   if(blocking) {
1792     /* in blocking mode, set NSS non-blocking mode _after_ SSL handshake */
1793     rv = nss_set_nonblock(connssl, data);
1794     if(rv)
1795       return rv;
1796   }
1797   else
1798     /* signal completed SSL handshake */
1799     *done = TRUE;
1800
1801   connssl->connecting_state = ssl_connect_done;
1802   return CURLE_OK;
1803 }
1804
1805 CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
1806 {
1807   return nss_connect_common(conn, sockindex, /* blocking */ NULL);
1808 }
1809
1810 CURLcode Curl_nss_connect_nonblocking(struct connectdata *conn,
1811                                       int sockindex, bool *done)
1812 {
1813   return nss_connect_common(conn, sockindex, done);
1814 }
1815
1816 static ssize_t nss_send(struct connectdata *conn,  /* connection data */
1817                         int sockindex,             /* socketindex */
1818                         const void *mem,           /* send this data */
1819                         size_t len,                /* amount to write */
1820                         CURLcode *curlcode)
1821 {
1822   ssize_t rc = PR_Send(conn->ssl[sockindex].handle, mem, (int)len, 0,
1823                        PR_INTERVAL_NO_WAIT);
1824   if(rc < 0) {
1825     PRInt32 err = PR_GetError();
1826     if(err == PR_WOULD_BLOCK_ERROR)
1827       *curlcode = CURLE_AGAIN;
1828     else {
1829       /* print the error number and error string */
1830       const char *err_name = nss_error_to_name(err);
1831       infof(conn->data, "SSL write: error %d (%s)\n", err, err_name);
1832
1833       /* print a human-readable message describing the error if available */
1834       nss_print_error_message(conn->data, err);
1835
1836       *curlcode = (is_cc_error(err))
1837         ? CURLE_SSL_CERTPROBLEM
1838         : CURLE_SEND_ERROR;
1839     }
1840     return -1;
1841   }
1842   return rc; /* number of bytes */
1843 }
1844
1845 static ssize_t nss_recv(struct connectdata * conn, /* connection data */
1846                         int num,                   /* socketindex */
1847                         char *buf,                 /* store read data here */
1848                         size_t buffersize,         /* max amount to read */
1849                         CURLcode *curlcode)
1850 {
1851   ssize_t nread = PR_Recv(conn->ssl[num].handle, buf, (int)buffersize, 0,
1852                           PR_INTERVAL_NO_WAIT);
1853   if(nread < 0) {
1854     /* failed SSL read */
1855     PRInt32 err = PR_GetError();
1856
1857     if(err == PR_WOULD_BLOCK_ERROR)
1858       *curlcode = CURLE_AGAIN;
1859     else {
1860       /* print the error number and error string */
1861       const char *err_name = nss_error_to_name(err);
1862       infof(conn->data, "SSL read: errno %d (%s)\n", err, err_name);
1863
1864       /* print a human-readable message describing the error if available */
1865       nss_print_error_message(conn->data, err);
1866
1867       *curlcode = (is_cc_error(err))
1868         ? CURLE_SSL_CERTPROBLEM
1869         : CURLE_RECV_ERROR;
1870     }
1871     return -1;
1872   }
1873   return nread;
1874 }
1875
1876 size_t Curl_nss_version(char *buffer, size_t size)
1877 {
1878   return snprintf(buffer, size, "NSS/%s", NSS_VERSION);
1879 }
1880
1881 int Curl_nss_seed(struct SessionHandle *data)
1882 {
1883   /* make sure that NSS is initialized */
1884   return !!Curl_nss_force_init(data);
1885 }
1886
1887 void Curl_nss_random(struct SessionHandle *data,
1888                      unsigned char *entropy,
1889                      size_t length)
1890 {
1891   Curl_nss_seed(data);  /* Initiate the seed if not already done */
1892   if(SECSuccess != PK11_GenerateRandom(entropy, curlx_uztosi(length))) {
1893     /* no way to signal a failure from here, we have to abort */
1894     failf(data, "PK11_GenerateRandom() failed, calling abort()...");
1895     abort();
1896   }
1897 }
1898
1899 void Curl_nss_md5sum(unsigned char *tmp, /* input */
1900                      size_t tmplen,
1901                      unsigned char *md5sum, /* output */
1902                      size_t md5len)
1903 {
1904   PK11Context *MD5pw = PK11_CreateDigestContext(SEC_OID_MD5);
1905   unsigned int MD5out;
1906   PK11_DigestOp(MD5pw, tmp, curlx_uztoui(tmplen));
1907   PK11_DigestFinal(MD5pw, md5sum, &MD5out, curlx_uztoui(md5len));
1908   PK11_DestroyContext(MD5pw, PR_TRUE);
1909 }
1910
1911 #endif /* USE_NSS */