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