Imported Upstream version 3.25.0
[platform/upstream/cmake.git] / Utilities / cmcurl / lib / vtls / nss.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2022, 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 https://curl.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  * SPDX-License-Identifier: curl
22  *
23  ***************************************************************************/
24
25 /*
26  * Source file for all NSS-specific code for the TLS/SSL layer. No code
27  * but vtls.c should ever call or use these functions.
28  */
29
30 #include "curl_setup.h"
31
32 #ifdef USE_NSS
33
34 #include "urldata.h"
35 #include "sendf.h"
36 #include "formdata.h" /* for the boundary function */
37 #include "url.h" /* for the ssl config check function */
38 #include "connect.h"
39 #include "strcase.h"
40 #include "select.h"
41 #include "vtls.h"
42 #include "llist.h"
43 #include "multiif.h"
44 #include "curl_printf.h"
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 #include <keyhi.h>         /* for SECKEY_DestroyPublicKey() */
63 #include <private/pprio.h> /* for PR_ImportTCPSocket */
64
65 #define NSSVERNUM ((NSS_VMAJOR<<16)|(NSS_VMINOR<<8)|NSS_VPATCH)
66
67 #if NSSVERNUM >= 0x030f00 /* 3.15.0 */
68 #include <ocsp.h>
69 #endif
70
71 #include "strcase.h"
72 #include "warnless.h"
73 #include "x509asn1.h"
74
75 /* The last #include files should be: */
76 #include "curl_memory.h"
77 #include "memdebug.h"
78
79 #define SSL_DIR "/etc/pki/nssdb"
80
81 /* enough to fit the string "PEM Token #[0|1]" */
82 #define SLOTSIZE 13
83
84 struct ssl_backend_data {
85   PRFileDesc *handle;
86   char *client_nickname;
87   struct Curl_easy *data;
88   struct Curl_llist obj_list;
89   PK11GenericObject *obj_clicert;
90 };
91
92 static PRLock *nss_initlock = NULL;
93 static PRLock *nss_crllock = NULL;
94 static PRLock *nss_findslot_lock = NULL;
95 static PRLock *nss_trustload_lock = NULL;
96 static struct Curl_llist nss_crl_list;
97 static NSSInitContext *nss_context = NULL;
98 static volatile int initialized = 0;
99
100 /* type used to wrap pointers as list nodes */
101 struct ptr_list_wrap {
102   void *ptr;
103   struct Curl_llist_element node;
104 };
105
106 struct cipher_s {
107   const char *name;
108   int num;
109 };
110
111 #define PK11_SETATTRS(_attr, _idx, _type, _val, _len) do {  \
112   CK_ATTRIBUTE *ptr = (_attr) + ((_idx)++);                 \
113   ptr->type = (_type);                                      \
114   ptr->pValue = (_val);                                     \
115   ptr->ulValueLen = (_len);                                 \
116 } while(0)
117
118 #define CERT_NewTempCertificate __CERT_NewTempCertificate
119
120 #define NUM_OF_CIPHERS sizeof(cipherlist)/sizeof(cipherlist[0])
121 static const struct cipher_s cipherlist[] = {
122   /* SSL2 cipher suites */
123   {"rc4",                        SSL_EN_RC4_128_WITH_MD5},
124   {"rc4-md5",                    SSL_EN_RC4_128_WITH_MD5},
125   {"rc4export",                  SSL_EN_RC4_128_EXPORT40_WITH_MD5},
126   {"rc2",                        SSL_EN_RC2_128_CBC_WITH_MD5},
127   {"rc2export",                  SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5},
128   {"des",                        SSL_EN_DES_64_CBC_WITH_MD5},
129   {"desede3",                    SSL_EN_DES_192_EDE3_CBC_WITH_MD5},
130   /* SSL3/TLS cipher suites */
131   {"rsa_rc4_128_md5",            SSL_RSA_WITH_RC4_128_MD5},
132   {"rsa_rc4_128_sha",            SSL_RSA_WITH_RC4_128_SHA},
133   {"rsa_3des_sha",               SSL_RSA_WITH_3DES_EDE_CBC_SHA},
134   {"rsa_des_sha",                SSL_RSA_WITH_DES_CBC_SHA},
135   {"rsa_rc4_40_md5",             SSL_RSA_EXPORT_WITH_RC4_40_MD5},
136   {"rsa_rc2_40_md5",             SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5},
137   {"rsa_null_md5",               SSL_RSA_WITH_NULL_MD5},
138   {"rsa_null_sha",               SSL_RSA_WITH_NULL_SHA},
139   {"fips_3des_sha",              SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA},
140   {"fips_des_sha",               SSL_RSA_FIPS_WITH_DES_CBC_SHA},
141   {"fortezza",                   SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA},
142   {"fortezza_rc4_128_sha",       SSL_FORTEZZA_DMS_WITH_RC4_128_SHA},
143   {"fortezza_null",              SSL_FORTEZZA_DMS_WITH_NULL_SHA},
144   {"dhe_rsa_3des_sha",           SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA},
145   {"dhe_dss_3des_sha",           SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA},
146   {"dhe_rsa_des_sha",            SSL_DHE_RSA_WITH_DES_CBC_SHA},
147   {"dhe_dss_des_sha",            SSL_DHE_DSS_WITH_DES_CBC_SHA},
148   /* TLS 1.0: Exportable 56-bit Cipher Suites. */
149   {"rsa_des_56_sha",             TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA},
150   {"rsa_rc4_56_sha",             TLS_RSA_EXPORT1024_WITH_RC4_56_SHA},
151   /* Ephemeral DH with RC4 bulk encryption */
152   {"dhe_dss_rc4_128_sha",    TLS_DHE_DSS_WITH_RC4_128_SHA},
153   /* AES ciphers. */
154   {"dhe_dss_aes_128_cbc_sha",    TLS_DHE_DSS_WITH_AES_128_CBC_SHA},
155   {"dhe_dss_aes_256_cbc_sha",    TLS_DHE_DSS_WITH_AES_256_CBC_SHA},
156   {"dhe_rsa_aes_128_cbc_sha",    TLS_DHE_RSA_WITH_AES_128_CBC_SHA},
157   {"dhe_rsa_aes_256_cbc_sha",    TLS_DHE_RSA_WITH_AES_256_CBC_SHA},
158   {"rsa_aes_128_sha",            TLS_RSA_WITH_AES_128_CBC_SHA},
159   {"rsa_aes_256_sha",            TLS_RSA_WITH_AES_256_CBC_SHA},
160   /* ECC ciphers. */
161   {"ecdh_ecdsa_null_sha",        TLS_ECDH_ECDSA_WITH_NULL_SHA},
162   {"ecdh_ecdsa_rc4_128_sha",     TLS_ECDH_ECDSA_WITH_RC4_128_SHA},
163   {"ecdh_ecdsa_3des_sha",        TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA},
164   {"ecdh_ecdsa_aes_128_sha",     TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA},
165   {"ecdh_ecdsa_aes_256_sha",     TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA},
166   {"ecdhe_ecdsa_null_sha",       TLS_ECDHE_ECDSA_WITH_NULL_SHA},
167   {"ecdhe_ecdsa_rc4_128_sha",    TLS_ECDHE_ECDSA_WITH_RC4_128_SHA},
168   {"ecdhe_ecdsa_3des_sha",       TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA},
169   {"ecdhe_ecdsa_aes_128_sha",    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA},
170   {"ecdhe_ecdsa_aes_256_sha",    TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
171   {"ecdh_rsa_null_sha",          TLS_ECDH_RSA_WITH_NULL_SHA},
172   {"ecdh_rsa_128_sha",           TLS_ECDH_RSA_WITH_RC4_128_SHA},
173   {"ecdh_rsa_3des_sha",          TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA},
174   {"ecdh_rsa_aes_128_sha",       TLS_ECDH_RSA_WITH_AES_128_CBC_SHA},
175   {"ecdh_rsa_aes_256_sha",       TLS_ECDH_RSA_WITH_AES_256_CBC_SHA},
176   {"ecdhe_rsa_null",             TLS_ECDHE_RSA_WITH_NULL_SHA},
177   {"ecdhe_rsa_rc4_128_sha",      TLS_ECDHE_RSA_WITH_RC4_128_SHA},
178   {"ecdhe_rsa_3des_sha",         TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA},
179   {"ecdhe_rsa_aes_128_sha",      TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
180   {"ecdhe_rsa_aes_256_sha",      TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
181   {"ecdh_anon_null_sha",         TLS_ECDH_anon_WITH_NULL_SHA},
182   {"ecdh_anon_rc4_128sha",       TLS_ECDH_anon_WITH_RC4_128_SHA},
183   {"ecdh_anon_3des_sha",         TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA},
184   {"ecdh_anon_aes_128_sha",      TLS_ECDH_anon_WITH_AES_128_CBC_SHA},
185   {"ecdh_anon_aes_256_sha",      TLS_ECDH_anon_WITH_AES_256_CBC_SHA},
186 #ifdef TLS_RSA_WITH_NULL_SHA256
187   /* new HMAC-SHA256 cipher suites specified in RFC */
188   {"rsa_null_sha_256",                TLS_RSA_WITH_NULL_SHA256},
189   {"rsa_aes_128_cbc_sha_256",         TLS_RSA_WITH_AES_128_CBC_SHA256},
190   {"rsa_aes_256_cbc_sha_256",         TLS_RSA_WITH_AES_256_CBC_SHA256},
191   {"dhe_rsa_aes_128_cbc_sha_256",     TLS_DHE_RSA_WITH_AES_128_CBC_SHA256},
192   {"dhe_rsa_aes_256_cbc_sha_256",     TLS_DHE_RSA_WITH_AES_256_CBC_SHA256},
193   {"ecdhe_ecdsa_aes_128_cbc_sha_256", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256},
194   {"ecdhe_rsa_aes_128_cbc_sha_256",   TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},
195 #endif
196 #ifdef TLS_RSA_WITH_AES_128_GCM_SHA256
197   /* AES GCM cipher suites in RFC 5288 and RFC 5289 */
198   {"rsa_aes_128_gcm_sha_256",         TLS_RSA_WITH_AES_128_GCM_SHA256},
199   {"dhe_rsa_aes_128_gcm_sha_256",     TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
200   {"dhe_dss_aes_128_gcm_sha_256",     TLS_DHE_DSS_WITH_AES_128_GCM_SHA256},
201   {"ecdhe_ecdsa_aes_128_gcm_sha_256", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
202   {"ecdh_ecdsa_aes_128_gcm_sha_256",  TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256},
203   {"ecdhe_rsa_aes_128_gcm_sha_256",   TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
204   {"ecdh_rsa_aes_128_gcm_sha_256",    TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256},
205 #endif
206 #ifdef TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
207   /* cipher suites using SHA384 */
208   {"rsa_aes_256_gcm_sha_384",         TLS_RSA_WITH_AES_256_GCM_SHA384},
209   {"dhe_rsa_aes_256_gcm_sha_384",     TLS_DHE_RSA_WITH_AES_256_GCM_SHA384},
210   {"dhe_dss_aes_256_gcm_sha_384",     TLS_DHE_DSS_WITH_AES_256_GCM_SHA384},
211   {"ecdhe_ecdsa_aes_256_sha_384",     TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384},
212   {"ecdhe_rsa_aes_256_sha_384",       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384},
213   {"ecdhe_ecdsa_aes_256_gcm_sha_384", TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384},
214   {"ecdhe_rsa_aes_256_gcm_sha_384",   TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384},
215 #endif
216 #ifdef TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
217   /* chacha20-poly1305 cipher suites */
218  {"ecdhe_rsa_chacha20_poly1305_sha_256",
219      TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
220  {"ecdhe_ecdsa_chacha20_poly1305_sha_256",
221      TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256},
222  {"dhe_rsa_chacha20_poly1305_sha_256",
223      TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
224 #endif
225 #ifdef TLS_AES_256_GCM_SHA384
226  {"aes_128_gcm_sha_256",              TLS_AES_128_GCM_SHA256},
227  {"aes_256_gcm_sha_384",              TLS_AES_256_GCM_SHA384},
228  {"chacha20_poly1305_sha_256",        TLS_CHACHA20_POLY1305_SHA256},
229 #endif
230 #ifdef TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
231   /* AES CBC cipher suites in RFC 5246. Introduced in NSS release 3.20 */
232   {"dhe_dss_aes_128_sha_256",         TLS_DHE_DSS_WITH_AES_128_CBC_SHA256},
233   {"dhe_dss_aes_256_sha_256",         TLS_DHE_DSS_WITH_AES_256_CBC_SHA256},
234 #endif
235 #ifdef TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
236   /* Camellia cipher suites in RFC 4132/5932.
237      Introduced in NSS release 3.12 */
238   {"dhe_rsa_camellia_128_sha",        TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA},
239   {"dhe_dss_camellia_128_sha",        TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA},
240   {"dhe_rsa_camellia_256_sha",        TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA},
241   {"dhe_dss_camellia_256_sha",        TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA},
242   {"rsa_camellia_128_sha",            TLS_RSA_WITH_CAMELLIA_128_CBC_SHA},
243   {"rsa_camellia_256_sha",            TLS_RSA_WITH_CAMELLIA_256_CBC_SHA},
244 #endif
245 #ifdef TLS_RSA_WITH_SEED_CBC_SHA
246   /* SEED cipher suite in RFC 4162. Introduced in NSS release 3.12.3 */
247   {"rsa_seed_sha",                    TLS_RSA_WITH_SEED_CBC_SHA},
248 #endif
249 };
250
251 #if defined(WIN32)
252 static const char *pem_library = "nsspem.dll";
253 static const char *trust_library = "nssckbi.dll";
254 #elif defined(__APPLE__)
255 static const char *pem_library = "libnsspem.dylib";
256 static const char *trust_library = "libnssckbi.dylib";
257 #else
258 static const char *pem_library = "libnsspem.so";
259 static const char *trust_library = "libnssckbi.so";
260 #endif
261
262 static SECMODModule *pem_module = NULL;
263 static SECMODModule *trust_module = NULL;
264
265 /* NSPR I/O layer we use to detect blocking direction during SSL handshake */
266 static PRDescIdentity nspr_io_identity = PR_INVALID_IO_LAYER;
267 static PRIOMethods nspr_io_methods;
268
269 static const char *nss_error_to_name(PRErrorCode code)
270 {
271   const char *name = PR_ErrorToName(code);
272   if(name)
273     return name;
274
275   return "unknown error";
276 }
277
278 static void nss_print_error_message(struct Curl_easy *data, PRUint32 err)
279 {
280   failf(data, "%s", PR_ErrorToString(err, PR_LANGUAGE_I_DEFAULT));
281 }
282
283 static char *nss_sslver_to_name(PRUint16 nssver)
284 {
285   switch(nssver) {
286   case SSL_LIBRARY_VERSION_2:
287     return strdup("SSLv2");
288   case SSL_LIBRARY_VERSION_3_0:
289     return strdup("SSLv3");
290   case SSL_LIBRARY_VERSION_TLS_1_0:
291     return strdup("TLSv1.0");
292 #ifdef SSL_LIBRARY_VERSION_TLS_1_1
293   case SSL_LIBRARY_VERSION_TLS_1_1:
294     return strdup("TLSv1.1");
295 #endif
296 #ifdef SSL_LIBRARY_VERSION_TLS_1_2
297   case SSL_LIBRARY_VERSION_TLS_1_2:
298     return strdup("TLSv1.2");
299 #endif
300 #ifdef SSL_LIBRARY_VERSION_TLS_1_3
301   case SSL_LIBRARY_VERSION_TLS_1_3:
302     return strdup("TLSv1.3");
303 #endif
304   default:
305     return curl_maprintf("0x%04x", nssver);
306   }
307 }
308
309 /* the longest cipher name this supports */
310 #define MAX_CIPHER_LENGTH 128
311
312 static SECStatus set_ciphers(struct Curl_easy *data, PRFileDesc *model,
313                              const char *cipher_list)
314 {
315   unsigned int i;
316   const char *cipher;
317
318   /* use accessors to avoid dynamic linking issues after an update of NSS */
319   const PRUint16 num_implemented_ciphers = SSL_GetNumImplementedCiphers();
320   const PRUint16 *implemented_ciphers = SSL_GetImplementedCiphers();
321   if(!implemented_ciphers)
322     return SECFailure;
323
324   /* First disable all ciphers. This uses a different max value in case
325    * NSS adds more ciphers later we don't want them available by
326    * accident
327    */
328   for(i = 0; i < num_implemented_ciphers; i++) {
329     SSL_CipherPrefSet(model, implemented_ciphers[i], PR_FALSE);
330   }
331
332   cipher = cipher_list;
333
334   while(cipher && cipher[0]) {
335     const char *end;
336     char name[MAX_CIPHER_LENGTH + 1];
337     size_t len;
338     bool found = FALSE;
339     while((*cipher) && (ISBLANK(*cipher)))
340       ++cipher;
341
342     end = strpbrk(cipher, ":, ");
343     if(end)
344       len = end - cipher;
345     else
346       len = strlen(cipher);
347
348     if(len > MAX_CIPHER_LENGTH) {
349       failf(data, "Bad cipher list");
350       return SECFailure;
351     }
352     else if(len) {
353       memcpy(name, cipher, len);
354       name[len] = 0;
355
356       for(i = 0; i<NUM_OF_CIPHERS; i++) {
357         if(strcasecompare(name, cipherlist[i].name)) {
358           /* Enable the selected cipher */
359           if(SSL_CipherPrefSet(model, cipherlist[i].num, PR_TRUE) !=
360              SECSuccess) {
361             failf(data, "cipher-suite not supported by NSS: %s", name);
362             return SECFailure;
363           }
364           found = TRUE;
365           break;
366         }
367       }
368     }
369
370     if(!found && len) {
371       failf(data, "Unknown cipher: %s", name);
372       return SECFailure;
373     }
374     if(end)
375       cipher = ++end;
376     else
377       break;
378   }
379
380   return SECSuccess;
381 }
382
383 /*
384  * Return true if at least one cipher-suite is enabled. Used to determine
385  * if we need to call NSS_SetDomesticPolicy() to enable the default ciphers.
386  */
387 static bool any_cipher_enabled(void)
388 {
389   unsigned int i;
390
391   for(i = 0; i<NUM_OF_CIPHERS; i++) {
392     PRInt32 policy = 0;
393     SSL_CipherPolicyGet(cipherlist[i].num, &policy);
394     if(policy)
395       return TRUE;
396   }
397
398   return FALSE;
399 }
400
401 /*
402  * Determine whether the nickname passed in is a filename that needs to
403  * be loaded as a PEM or a regular NSS nickname.
404  *
405  * returns 1 for a file
406  * returns 0 for not a file (NSS nickname)
407  */
408 static int is_file(const char *filename)
409 {
410   struct_stat st;
411
412   if(!filename)
413     return 0;
414
415   if(stat(filename, &st) == 0)
416     if(S_ISREG(st.st_mode) || S_ISFIFO(st.st_mode) || S_ISCHR(st.st_mode))
417       return 1;
418
419   return 0;
420 }
421
422 /* Check if the given string is filename or nickname of a certificate.  If the
423  * given string is recognized as filename, return NULL.  If the given string is
424  * recognized as nickname, return a duplicated string.  The returned string
425  * should be later deallocated using free().  If the OOM failure occurs, we
426  * return NULL, too.
427  */
428 static char *dup_nickname(struct Curl_easy *data, const char *str)
429 {
430   const char *n;
431
432   if(!is_file(str))
433     /* no such file exists, use the string as nickname */
434     return strdup(str);
435
436   /* search the first slash; we require at least one slash in a file name */
437   n = strchr(str, '/');
438   if(!n) {
439     infof(data, "WARNING: certificate file name \"%s\" handled as nickname; "
440           "please use \"./%s\" to force file name", str, str);
441     return strdup(str);
442   }
443
444   /* we'll use the PEM reader to read the certificate from file */
445   return NULL;
446 }
447
448 /* Lock/unlock wrapper for PK11_FindSlotByName() to work around race condition
449  * in nssSlot_IsTokenPresent() causing spurious SEC_ERROR_NO_TOKEN.  For more
450  * details, go to <https://bugzilla.mozilla.org/1297397>.
451  */
452 static PK11SlotInfo* nss_find_slot_by_name(const char *slot_name)
453 {
454   PK11SlotInfo *slot;
455   PR_Lock(nss_findslot_lock);
456   slot = PK11_FindSlotByName(slot_name);
457   PR_Unlock(nss_findslot_lock);
458   return slot;
459 }
460
461 /* wrap 'ptr' as list node and tail-insert into 'list' */
462 static CURLcode insert_wrapped_ptr(struct Curl_llist *list, void *ptr)
463 {
464   struct ptr_list_wrap *wrap = malloc(sizeof(*wrap));
465   if(!wrap)
466     return CURLE_OUT_OF_MEMORY;
467
468   wrap->ptr = ptr;
469   Curl_llist_insert_next(list, list->tail, wrap, &wrap->node);
470   return CURLE_OK;
471 }
472
473 /* Call PK11_CreateGenericObject() with the given obj_class and filename.  If
474  * the call succeeds, append the object handle to the list of objects so that
475  * the object can be destroyed in nss_close(). */
476 static CURLcode nss_create_object(struct ssl_connect_data *connssl,
477                                   CK_OBJECT_CLASS obj_class,
478                                   const char *filename, bool cacert)
479 {
480   PK11SlotInfo *slot;
481   PK11GenericObject *obj;
482   CK_BBOOL cktrue = CK_TRUE;
483   CK_BBOOL ckfalse = CK_FALSE;
484   CK_ATTRIBUTE attrs[/* max count of attributes */ 4];
485   int attr_cnt = 0;
486   CURLcode result = (cacert)
487     ? CURLE_SSL_CACERT_BADFILE
488     : CURLE_SSL_CERTPROBLEM;
489
490   const int slot_id = (cacert) ? 0 : 1;
491   char *slot_name = aprintf("PEM Token #%d", slot_id);
492   struct ssl_backend_data *backend = connssl->backend;
493
494   DEBUGASSERT(backend);
495
496   if(!slot_name)
497     return CURLE_OUT_OF_MEMORY;
498
499   slot = nss_find_slot_by_name(slot_name);
500   free(slot_name);
501   if(!slot)
502     return result;
503
504   PK11_SETATTRS(attrs, attr_cnt, CKA_CLASS, &obj_class, sizeof(obj_class));
505   PK11_SETATTRS(attrs, attr_cnt, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL));
506   PK11_SETATTRS(attrs, attr_cnt, CKA_LABEL, (unsigned char *)filename,
507                 (CK_ULONG)strlen(filename) + 1);
508
509   if(CKO_CERTIFICATE == obj_class) {
510     CK_BBOOL *pval = (cacert) ? (&cktrue) : (&ckfalse);
511     PK11_SETATTRS(attrs, attr_cnt, CKA_TRUST, pval, sizeof(*pval));
512   }
513
514   /* PK11_CreateManagedGenericObject() was introduced in NSS 3.34 because
515    * PK11_DestroyGenericObject() does not release resources allocated by
516    * PK11_CreateGenericObject() early enough.  */
517   obj =
518 #ifdef HAVE_PK11_CREATEMANAGEDGENERICOBJECT
519     PK11_CreateManagedGenericObject
520 #else
521     PK11_CreateGenericObject
522 #endif
523     (slot, attrs, attr_cnt, PR_FALSE);
524
525   PK11_FreeSlot(slot);
526   if(!obj)
527     return result;
528
529   if(insert_wrapped_ptr(&backend->obj_list, obj) != CURLE_OK) {
530     PK11_DestroyGenericObject(obj);
531     return CURLE_OUT_OF_MEMORY;
532   }
533
534   if(!cacert && CKO_CERTIFICATE == obj_class)
535     /* store reference to a client certificate */
536     backend->obj_clicert = obj;
537
538   return CURLE_OK;
539 }
540
541 /* Destroy the NSS object whose handle is given by ptr.  This function is
542  * a callback of Curl_llist_alloc() used by Curl_llist_destroy() to destroy
543  * NSS objects in nss_close() */
544 static void nss_destroy_object(void *user, void *ptr)
545 {
546   struct ptr_list_wrap *wrap = (struct ptr_list_wrap *) ptr;
547   PK11GenericObject *obj = (PK11GenericObject *) wrap->ptr;
548   (void) user;
549   PK11_DestroyGenericObject(obj);
550   free(wrap);
551 }
552
553 /* same as nss_destroy_object() but for CRL items */
554 static void nss_destroy_crl_item(void *user, void *ptr)
555 {
556   struct ptr_list_wrap *wrap = (struct ptr_list_wrap *) ptr;
557   SECItem *crl_der = (SECItem *) wrap->ptr;
558   (void) user;
559   SECITEM_FreeItem(crl_der, PR_TRUE);
560   free(wrap);
561 }
562
563 static CURLcode nss_load_cert(struct ssl_connect_data *ssl,
564                               const char *filename, PRBool cacert)
565 {
566   CURLcode result = (cacert)
567     ? CURLE_SSL_CACERT_BADFILE
568     : CURLE_SSL_CERTPROBLEM;
569
570   /* libnsspem.so leaks memory if the requested file does not exist.  For more
571    * details, go to <https://bugzilla.redhat.com/734760>. */
572   if(is_file(filename))
573     result = nss_create_object(ssl, CKO_CERTIFICATE, filename, cacert);
574
575   if(!result && !cacert) {
576     /* we have successfully loaded a client certificate */
577     char *nickname = NULL;
578     char *n = strrchr(filename, '/');
579     if(n)
580       n++;
581
582     /* The following undocumented magic helps to avoid a SIGSEGV on call
583      * of PK11_ReadRawAttribute() from SelectClientCert() when using an
584      * immature version of libnsspem.so.  For more details, go to
585      * <https://bugzilla.redhat.com/733685>. */
586     nickname = aprintf("PEM Token #1:%s", n);
587     if(nickname) {
588       CERTCertificate *cert = PK11_FindCertFromNickname(nickname, NULL);
589       if(cert)
590         CERT_DestroyCertificate(cert);
591
592       free(nickname);
593     }
594   }
595
596   return result;
597 }
598
599 /* add given CRL to cache if it is not already there */
600 static CURLcode nss_cache_crl(SECItem *crl_der)
601 {
602   CERTCertDBHandle *db = CERT_GetDefaultCertDB();
603   CERTSignedCrl *crl = SEC_FindCrlByDERCert(db, crl_der, 0);
604   if(crl) {
605     /* CRL already cached */
606     SEC_DestroyCrl(crl);
607     SECITEM_FreeItem(crl_der, PR_TRUE);
608     return CURLE_OK;
609   }
610
611   /* acquire lock before call of CERT_CacheCRL() and accessing nss_crl_list */
612   PR_Lock(nss_crllock);
613
614   if(SECSuccess != CERT_CacheCRL(db, crl_der)) {
615     /* unable to cache CRL */
616     SECITEM_FreeItem(crl_der, PR_TRUE);
617     PR_Unlock(nss_crllock);
618     return CURLE_SSL_CRL_BADFILE;
619   }
620
621   /* store the CRL item so that we can free it in nss_cleanup() */
622   if(insert_wrapped_ptr(&nss_crl_list, crl_der) != CURLE_OK) {
623     if(SECSuccess == CERT_UncacheCRL(db, crl_der))
624       SECITEM_FreeItem(crl_der, PR_TRUE);
625     PR_Unlock(nss_crllock);
626     return CURLE_OUT_OF_MEMORY;
627   }
628
629   /* we need to clear session cache, so that the CRL could take effect */
630   SSL_ClearSessionCache();
631   PR_Unlock(nss_crllock);
632   return CURLE_OK;
633 }
634
635 static CURLcode nss_load_crl(const char *crlfilename)
636 {
637   PRFileDesc *infile;
638   PRFileInfo  info;
639   SECItem filedata = { 0, NULL, 0 };
640   SECItem *crl_der = NULL;
641   char *body;
642
643   infile = PR_Open(crlfilename, PR_RDONLY, 0);
644   if(!infile)
645     return CURLE_SSL_CRL_BADFILE;
646
647   if(PR_SUCCESS != PR_GetOpenFileInfo(infile, &info))
648     goto fail;
649
650   if(!SECITEM_AllocItem(NULL, &filedata, info.size + /* zero ended */ 1))
651     goto fail;
652
653   if(info.size != PR_Read(infile, filedata.data, info.size))
654     goto fail;
655
656   crl_der = SECITEM_AllocItem(NULL, NULL, 0U);
657   if(!crl_der)
658     goto fail;
659
660   /* place a trailing zero right after the visible data */
661   body = (char *)filedata.data;
662   body[--filedata.len] = '\0';
663
664   body = strstr(body, "-----BEGIN");
665   if(body) {
666     /* assume ASCII */
667     char *trailer;
668     char *begin = PORT_Strchr(body, '\n');
669     if(!begin)
670       begin = PORT_Strchr(body, '\r');
671     if(!begin)
672       goto fail;
673
674     trailer = strstr(++begin, "-----END");
675     if(!trailer)
676       goto fail;
677
678     /* retrieve DER from ASCII */
679     *trailer = '\0';
680     if(ATOB_ConvertAsciiToItem(crl_der, begin))
681       goto fail;
682
683     SECITEM_FreeItem(&filedata, PR_FALSE);
684   }
685   else
686     /* assume DER */
687     *crl_der = filedata;
688
689   PR_Close(infile);
690   return nss_cache_crl(crl_der);
691
692 fail:
693   PR_Close(infile);
694   SECITEM_FreeItem(crl_der, PR_TRUE);
695   SECITEM_FreeItem(&filedata, PR_FALSE);
696   return CURLE_SSL_CRL_BADFILE;
697 }
698
699 static CURLcode nss_load_key(struct Curl_easy *data, struct connectdata *conn,
700                              int sockindex, char *key_file)
701 {
702   PK11SlotInfo *slot, *tmp;
703   SECStatus status;
704   CURLcode result;
705   struct ssl_connect_data *ssl = conn->ssl;
706
707   (void)sockindex; /* unused */
708
709   result = nss_create_object(ssl, CKO_PRIVATE_KEY, key_file, FALSE);
710   if(result) {
711     PR_SetError(SEC_ERROR_BAD_KEY, 0);
712     return result;
713   }
714
715   slot = nss_find_slot_by_name("PEM Token #1");
716   if(!slot)
717     return CURLE_SSL_CERTPROBLEM;
718
719   /* This will force the token to be seen as re-inserted */
720   tmp = SECMOD_WaitForAnyTokenEvent(pem_module, 0, 0);
721   if(tmp)
722     PK11_FreeSlot(tmp);
723   if(!PK11_IsPresent(slot)) {
724     PK11_FreeSlot(slot);
725     return CURLE_SSL_CERTPROBLEM;
726   }
727
728   status = PK11_Authenticate(slot, PR_TRUE, SSL_SET_OPTION(key_passwd));
729   PK11_FreeSlot(slot);
730
731   return (SECSuccess == status) ? CURLE_OK : CURLE_SSL_CERTPROBLEM;
732 }
733
734 static int display_error(struct Curl_easy *data, PRInt32 err,
735                          const char *filename)
736 {
737   switch(err) {
738   case SEC_ERROR_BAD_PASSWORD:
739     failf(data, "Unable to load client key: Incorrect password");
740     return 1;
741   case SEC_ERROR_UNKNOWN_CERT:
742     failf(data, "Unable to load certificate %s", filename);
743     return 1;
744   default:
745     break;
746   }
747   return 0; /* The caller will print a generic error */
748 }
749
750 static CURLcode cert_stuff(struct Curl_easy *data, struct connectdata *conn,
751                            int sockindex, char *cert_file, char *key_file)
752 {
753   CURLcode result;
754
755   if(cert_file) {
756     result = nss_load_cert(&conn->ssl[sockindex], cert_file, PR_FALSE);
757     if(result) {
758       const PRErrorCode err = PR_GetError();
759       if(!display_error(data, err, cert_file)) {
760         const char *err_name = nss_error_to_name(err);
761         failf(data, "unable to load client cert: %d (%s)", err, err_name);
762       }
763
764       return result;
765     }
766   }
767
768   if(key_file || (is_file(cert_file))) {
769     if(key_file)
770       result = nss_load_key(data, conn, sockindex, key_file);
771     else
772       /* In case the cert file also has the key */
773       result = nss_load_key(data, conn, sockindex, cert_file);
774     if(result) {
775       const PRErrorCode err = PR_GetError();
776       if(!display_error(data, err, key_file)) {
777         const char *err_name = nss_error_to_name(err);
778         failf(data, "unable to load client key: %d (%s)", err, err_name);
779       }
780
781       return result;
782     }
783   }
784
785   return CURLE_OK;
786 }
787
788 static char *nss_get_password(PK11SlotInfo *slot, PRBool retry, void *arg)
789 {
790   (void)slot; /* unused */
791
792   if(retry || !arg)
793     return NULL;
794   else
795     return (char *)PORT_Strdup((char *)arg);
796 }
797
798 /* bypass the default SSL_AuthCertificate() hook in case we do not want to
799  * verify peer */
800 static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig,
801                                     PRBool isServer)
802 {
803   struct Curl_easy *data = (struct Curl_easy *)arg;
804   struct connectdata *conn = data->conn;
805
806 #ifdef SSL_ENABLE_OCSP_STAPLING
807   if(SSL_CONN_CONFIG(verifystatus)) {
808     SECStatus cacheResult;
809
810     const SECItemArray *csa = SSL_PeerStapledOCSPResponses(fd);
811     if(!csa) {
812       failf(data, "Invalid OCSP response");
813       return SECFailure;
814     }
815
816     if(csa->len == 0) {
817       failf(data, "No OCSP response received");
818       return SECFailure;
819     }
820
821     cacheResult = CERT_CacheOCSPResponseFromSideChannel(
822       CERT_GetDefaultCertDB(), SSL_PeerCertificate(fd),
823       PR_Now(), &csa->items[0], arg
824     );
825
826     if(cacheResult != SECSuccess) {
827       failf(data, "Invalid OCSP response");
828       return cacheResult;
829     }
830   }
831 #endif
832
833   if(!SSL_CONN_CONFIG(verifypeer)) {
834     infof(data, "skipping SSL peer certificate verification");
835     return SECSuccess;
836   }
837
838   return SSL_AuthCertificate(CERT_GetDefaultCertDB(), fd, checksig, isServer);
839 }
840
841 /**
842  * Inform the application that the handshake is complete.
843  */
844 static void HandshakeCallback(PRFileDesc *sock, void *arg)
845 {
846   struct Curl_easy *data = (struct Curl_easy *)arg;
847   struct connectdata *conn = data->conn;
848   unsigned int buflenmax = 50;
849   unsigned char buf[50];
850   unsigned int buflen;
851   SSLNextProtoState state;
852
853   if(!conn->bits.tls_enable_alpn) {
854     return;
855   }
856
857   if(SSL_GetNextProto(sock, &state, buf, &buflen, buflenmax) == SECSuccess) {
858
859     switch(state) {
860 #if NSSVERNUM >= 0x031a00 /* 3.26.0 */
861     /* used by NSS internally to implement 0-RTT */
862     case SSL_NEXT_PROTO_EARLY_VALUE:
863       /* fall through! */
864 #endif
865     case SSL_NEXT_PROTO_NO_SUPPORT:
866     case SSL_NEXT_PROTO_NO_OVERLAP:
867       infof(data, VTLS_INFOF_NO_ALPN);
868       return;
869 #ifdef SSL_ENABLE_ALPN
870     case SSL_NEXT_PROTO_SELECTED:
871       infof(data, VTLS_INFOF_ALPN_ACCEPTED_LEN_1STR, buflen, buf);
872       break;
873 #endif
874     default:
875       /* ignore SSL_NEXT_PROTO_NEGOTIATED */
876       break;
877     }
878
879 #ifdef USE_HTTP2
880     if(buflen == ALPN_H2_LENGTH &&
881        !memcmp(ALPN_H2, buf, ALPN_H2_LENGTH)) {
882       conn->alpn = CURL_HTTP_VERSION_2;
883     }
884     else
885 #endif
886     if(buflen == ALPN_HTTP_1_1_LENGTH &&
887        !memcmp(ALPN_HTTP_1_1, buf, ALPN_HTTP_1_1_LENGTH)) {
888       conn->alpn = CURL_HTTP_VERSION_1_1;
889     }
890
891     /* This callback might get called when PR_Recv() is used within
892      * close_one() during a connection shutdown. At that point there might not
893      * be any "bundle" associated with the connection anymore.
894      */
895     if(conn->bundle)
896       Curl_multiuse_state(data, conn->alpn == CURL_HTTP_VERSION_2 ?
897                           BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
898   }
899 }
900
901 #if NSSVERNUM >= 0x030f04 /* 3.15.4 */
902 static SECStatus CanFalseStartCallback(PRFileDesc *sock, void *client_data,
903                                        PRBool *canFalseStart)
904 {
905   struct Curl_easy *data = (struct Curl_easy *)client_data;
906
907   SSLChannelInfo channelInfo;
908   SSLCipherSuiteInfo cipherInfo;
909
910   SECStatus rv;
911   PRBool negotiatedExtension;
912
913   *canFalseStart = PR_FALSE;
914
915   if(SSL_GetChannelInfo(sock, &channelInfo, sizeof(channelInfo)) != SECSuccess)
916     return SECFailure;
917
918   if(SSL_GetCipherSuiteInfo(channelInfo.cipherSuite, &cipherInfo,
919                             sizeof(cipherInfo)) != SECSuccess)
920     return SECFailure;
921
922   /* Prevent version downgrade attacks from TLS 1.2, and avoid False Start for
923    * TLS 1.3 and later. See https://bugzilla.mozilla.org/show_bug.cgi?id=861310
924    */
925   if(channelInfo.protocolVersion != SSL_LIBRARY_VERSION_TLS_1_2)
926     goto end;
927
928   /* Only allow ECDHE key exchange algorithm.
929    * See https://bugzilla.mozilla.org/show_bug.cgi?id=952863 */
930   if(cipherInfo.keaType != ssl_kea_ecdh)
931     goto end;
932
933   /* Prevent downgrade attacks on the symmetric cipher. We do not allow CBC
934    * mode due to BEAST, POODLE, and other attacks on the MAC-then-Encrypt
935    * design. See https://bugzilla.mozilla.org/show_bug.cgi?id=1109766 */
936   if(cipherInfo.symCipher != ssl_calg_aes_gcm)
937     goto end;
938
939   /* Enforce ALPN to do False Start, as an indicator of server
940      compatibility. */
941   rv = SSL_HandshakeNegotiatedExtension(sock, ssl_app_layer_protocol_xtn,
942                                         &negotiatedExtension);
943   if(rv != SECSuccess || !negotiatedExtension) {
944     rv = SSL_HandshakeNegotiatedExtension(sock, ssl_next_proto_nego_xtn,
945                                           &negotiatedExtension);
946   }
947
948   if(rv != SECSuccess || !negotiatedExtension)
949     goto end;
950
951   *canFalseStart = PR_TRUE;
952
953   infof(data, "Trying TLS False Start");
954
955 end:
956   return SECSuccess;
957 }
958 #endif
959
960 static void display_cert_info(struct Curl_easy *data,
961                               CERTCertificate *cert)
962 {
963   char *subject, *issuer, *common_name;
964   PRExplodedTime printableTime;
965   char timeString[256];
966   PRTime notBefore, notAfter;
967
968   subject = CERT_NameToAscii(&cert->subject);
969   issuer = CERT_NameToAscii(&cert->issuer);
970   common_name = CERT_GetCommonName(&cert->subject);
971   infof(data, "subject: %s", subject);
972
973   CERT_GetCertTimes(cert, &notBefore, &notAfter);
974   PR_ExplodeTime(notBefore, PR_GMTParameters, &printableTime);
975   PR_FormatTime(timeString, 256, "%b %d %H:%M:%S %Y GMT", &printableTime);
976   infof(data, " start date: %s", timeString);
977   PR_ExplodeTime(notAfter, PR_GMTParameters, &printableTime);
978   PR_FormatTime(timeString, 256, "%b %d %H:%M:%S %Y GMT", &printableTime);
979   infof(data, " expire date: %s", timeString);
980   infof(data, " common name: %s", common_name);
981   infof(data, " issuer: %s", issuer);
982
983   PR_Free(subject);
984   PR_Free(issuer);
985   PR_Free(common_name);
986 }
987
988 /* A number of certs that will never occur in a real server handshake */
989 #define TOO_MANY_CERTS 300
990
991 static CURLcode display_conn_info(struct Curl_easy *data, PRFileDesc *sock)
992 {
993   CURLcode result = CURLE_OK;
994   SSLChannelInfo channel;
995   SSLCipherSuiteInfo suite;
996   CERTCertificate *cert;
997   CERTCertificate *cert2;
998   CERTCertificate *cert3;
999   PRTime now;
1000
1001   if(SSL_GetChannelInfo(sock, &channel, sizeof(channel)) ==
1002      SECSuccess && channel.length == sizeof(channel) &&
1003      channel.cipherSuite) {
1004     if(SSL_GetCipherSuiteInfo(channel.cipherSuite,
1005                               &suite, sizeof(suite)) == SECSuccess) {
1006       infof(data, "SSL connection using %s", suite.cipherSuiteName);
1007     }
1008   }
1009
1010   cert = SSL_PeerCertificate(sock);
1011   if(cert) {
1012     infof(data, "Server certificate:");
1013
1014     if(!data->set.ssl.certinfo) {
1015       display_cert_info(data, cert);
1016       CERT_DestroyCertificate(cert);
1017     }
1018     else {
1019       /* Count certificates in chain. */
1020       int i = 1;
1021       now = PR_Now();
1022       if(!cert->isRoot) {
1023         cert2 = CERT_FindCertIssuer(cert, now, certUsageSSLCA);
1024         while(cert2) {
1025           i++;
1026           if(i >= TOO_MANY_CERTS) {
1027             CERT_DestroyCertificate(cert2);
1028             failf(data, "certificate loop");
1029             return CURLE_SSL_CERTPROBLEM;
1030           }
1031           if(cert2->isRoot) {
1032             CERT_DestroyCertificate(cert2);
1033             break;
1034           }
1035           cert3 = CERT_FindCertIssuer(cert2, now, certUsageSSLCA);
1036           CERT_DestroyCertificate(cert2);
1037           cert2 = cert3;
1038         }
1039       }
1040
1041       result = Curl_ssl_init_certinfo(data, i);
1042       if(!result) {
1043         for(i = 0; cert; cert = cert2) {
1044           result = Curl_extract_certinfo(data, i++, (char *)cert->derCert.data,
1045                                          (char *)cert->derCert.data +
1046                                                  cert->derCert.len);
1047           if(result)
1048             break;
1049
1050           if(cert->isRoot) {
1051             CERT_DestroyCertificate(cert);
1052             break;
1053           }
1054
1055           cert2 = CERT_FindCertIssuer(cert, now, certUsageSSLCA);
1056           CERT_DestroyCertificate(cert);
1057         }
1058       }
1059     }
1060   }
1061
1062   return result;
1063 }
1064
1065 static SECStatus BadCertHandler(void *arg, PRFileDesc *sock)
1066 {
1067   struct Curl_easy *data = (struct Curl_easy *)arg;
1068   struct connectdata *conn = data->conn;
1069   PRErrorCode err = PR_GetError();
1070   CERTCertificate *cert;
1071
1072   /* remember the cert verification result */
1073   SSL_SET_OPTION_LVALUE(certverifyresult) = err;
1074
1075   if(err == SSL_ERROR_BAD_CERT_DOMAIN && !SSL_CONN_CONFIG(verifyhost))
1076     /* we are asked not to verify the host name */
1077     return SECSuccess;
1078
1079   /* print only info about the cert, the error is printed off the callback */
1080   cert = SSL_PeerCertificate(sock);
1081   if(cert) {
1082     infof(data, "Server certificate:");
1083     display_cert_info(data, cert);
1084     CERT_DestroyCertificate(cert);
1085   }
1086
1087   return SECFailure;
1088 }
1089
1090 /**
1091  *
1092  * Check that the Peer certificate's issuer certificate matches the one found
1093  * by issuer_nickname.  This is not exactly the way OpenSSL and GNU TLS do the
1094  * issuer check, so we provide comments that mimic the OpenSSL
1095  * X509_check_issued function (in x509v3/v3_purp.c)
1096  */
1097 static SECStatus check_issuer_cert(PRFileDesc *sock,
1098                                    char *issuer_nickname)
1099 {
1100   CERTCertificate *cert, *cert_issuer, *issuer;
1101   SECStatus res = SECSuccess;
1102   void *proto_win = NULL;
1103
1104   cert = SSL_PeerCertificate(sock);
1105   cert_issuer = CERT_FindCertIssuer(cert, PR_Now(), certUsageObjectSigner);
1106
1107   proto_win = SSL_RevealPinArg(sock);
1108   issuer = PK11_FindCertFromNickname(issuer_nickname, proto_win);
1109
1110   if((!cert_issuer) || (!issuer))
1111     res = SECFailure;
1112   else if(SECITEM_CompareItem(&cert_issuer->derCert,
1113                               &issuer->derCert) != SECEqual)
1114     res = SECFailure;
1115
1116   CERT_DestroyCertificate(cert);
1117   CERT_DestroyCertificate(issuer);
1118   CERT_DestroyCertificate(cert_issuer);
1119   return res;
1120 }
1121
1122 static CURLcode cmp_peer_pubkey(struct ssl_connect_data *connssl,
1123                                 const char *pinnedpubkey)
1124 {
1125   CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
1126   struct ssl_backend_data *backend = connssl->backend;
1127   struct Curl_easy *data = NULL;
1128   CERTCertificate *cert;
1129
1130   DEBUGASSERT(backend);
1131   data = backend->data;
1132
1133   if(!pinnedpubkey)
1134     /* no pinned public key specified */
1135     return CURLE_OK;
1136
1137   /* get peer certificate */
1138   cert = SSL_PeerCertificate(backend->handle);
1139   if(cert) {
1140     /* extract public key from peer certificate */
1141     SECKEYPublicKey *pubkey = CERT_ExtractPublicKey(cert);
1142     if(pubkey) {
1143       /* encode the public key as DER */
1144       SECItem *cert_der = PK11_DEREncodePublicKey(pubkey);
1145       if(cert_der) {
1146         /* compare the public key with the pinned public key */
1147         result = Curl_pin_peer_pubkey(data, pinnedpubkey, cert_der->data,
1148                                       cert_der->len);
1149         SECITEM_FreeItem(cert_der, PR_TRUE);
1150       }
1151       SECKEY_DestroyPublicKey(pubkey);
1152     }
1153     CERT_DestroyCertificate(cert);
1154   }
1155
1156   /* report the resulting status */
1157   switch(result) {
1158   case CURLE_OK:
1159     infof(data, "pinned public key verified successfully");
1160     break;
1161   case CURLE_SSL_PINNEDPUBKEYNOTMATCH:
1162     failf(data, "failed to verify pinned public key");
1163     break;
1164   default:
1165     /* OOM, etc. */
1166     break;
1167   }
1168
1169   return result;
1170 }
1171
1172 /**
1173  *
1174  * Callback to pick the SSL client certificate.
1175  */
1176 static SECStatus SelectClientCert(void *arg, PRFileDesc *sock,
1177                                   struct CERTDistNamesStr *caNames,
1178                                   struct CERTCertificateStr **pRetCert,
1179                                   struct SECKEYPrivateKeyStr **pRetKey)
1180 {
1181   struct ssl_connect_data *connssl = (struct ssl_connect_data *)arg;
1182   struct ssl_backend_data *backend = connssl->backend;
1183   struct Curl_easy *data = NULL;
1184   const char *nickname = NULL;
1185   static const char pem_slotname[] = "PEM Token #1";
1186
1187   DEBUGASSERT(backend);
1188
1189   data = backend->data;
1190   nickname = backend->client_nickname;
1191
1192   if(backend->obj_clicert) {
1193     /* use the cert/key provided by PEM reader */
1194     SECItem cert_der = { 0, NULL, 0 };
1195     void *proto_win = SSL_RevealPinArg(sock);
1196     struct CERTCertificateStr *cert;
1197     struct SECKEYPrivateKeyStr *key;
1198
1199     PK11SlotInfo *slot = nss_find_slot_by_name(pem_slotname);
1200     if(!slot) {
1201       failf(data, "NSS: PK11 slot not found: %s", pem_slotname);
1202       return SECFailure;
1203     }
1204
1205     if(PK11_ReadRawAttribute(PK11_TypeGeneric, backend->obj_clicert, CKA_VALUE,
1206                              &cert_der) != SECSuccess) {
1207       failf(data, "NSS: CKA_VALUE not found in PK11 generic object");
1208       PK11_FreeSlot(slot);
1209       return SECFailure;
1210     }
1211
1212     cert = PK11_FindCertFromDERCertItem(slot, &cert_der, proto_win);
1213     SECITEM_FreeItem(&cert_der, PR_FALSE);
1214     if(!cert) {
1215       failf(data, "NSS: client certificate from file not found");
1216       PK11_FreeSlot(slot);
1217       return SECFailure;
1218     }
1219
1220     key = PK11_FindPrivateKeyFromCert(slot, cert, NULL);
1221     PK11_FreeSlot(slot);
1222     if(!key) {
1223       failf(data, "NSS: private key from file not found");
1224       CERT_DestroyCertificate(cert);
1225       return SECFailure;
1226     }
1227
1228     infof(data, "NSS: client certificate from file");
1229     display_cert_info(data, cert);
1230
1231     *pRetCert = cert;
1232     *pRetKey = key;
1233     return SECSuccess;
1234   }
1235
1236   /* use the default NSS hook */
1237   if(SECSuccess != NSS_GetClientAuthData((void *)nickname, sock, caNames,
1238                                           pRetCert, pRetKey)
1239      || !*pRetCert) {
1240
1241     if(!nickname)
1242       failf(data, "NSS: client certificate not found (nickname not "
1243             "specified)");
1244     else
1245       failf(data, "NSS: client certificate not found: %s", nickname);
1246
1247     return SECFailure;
1248   }
1249
1250   /* get certificate nickname if any */
1251   nickname = (*pRetCert)->nickname;
1252   if(!nickname)
1253     nickname = "[unknown]";
1254
1255   if(!strncmp(nickname, pem_slotname, sizeof(pem_slotname) - 1U)) {
1256     failf(data, "NSS: refusing previously loaded certificate from file: %s",
1257           nickname);
1258     return SECFailure;
1259   }
1260
1261   if(!*pRetKey) {
1262     failf(data, "NSS: private key not found for certificate: %s", nickname);
1263     return SECFailure;
1264   }
1265
1266   infof(data, "NSS: using client certificate: %s", nickname);
1267   display_cert_info(data, *pRetCert);
1268   return SECSuccess;
1269 }
1270
1271 /* update blocking direction in case of PR_WOULD_BLOCK_ERROR */
1272 static void nss_update_connecting_state(ssl_connect_state state, void *secret)
1273 {
1274   struct ssl_connect_data *connssl = (struct ssl_connect_data *)secret;
1275   if(PR_GetError() != PR_WOULD_BLOCK_ERROR)
1276     /* an unrelated error is passing by */
1277     return;
1278
1279   switch(connssl->connecting_state) {
1280   case ssl_connect_2:
1281   case ssl_connect_2_reading:
1282   case ssl_connect_2_writing:
1283     break;
1284   default:
1285     /* we are not called from an SSL handshake */
1286     return;
1287   }
1288
1289   /* update the state accordingly */
1290   connssl->connecting_state = state;
1291 }
1292
1293 /* recv() wrapper we use to detect blocking direction during SSL handshake */
1294 static PRInt32 nspr_io_recv(PRFileDesc *fd, void *buf, PRInt32 amount,
1295                             PRIntn flags, PRIntervalTime timeout)
1296 {
1297   const PRRecvFN recv_fn = fd->lower->methods->recv;
1298   const PRInt32 rv = recv_fn(fd->lower, buf, amount, flags, timeout);
1299   if(rv < 0)
1300     /* check for PR_WOULD_BLOCK_ERROR and update blocking direction */
1301     nss_update_connecting_state(ssl_connect_2_reading, fd->secret);
1302   return rv;
1303 }
1304
1305 /* send() wrapper we use to detect blocking direction during SSL handshake */
1306 static PRInt32 nspr_io_send(PRFileDesc *fd, const void *buf, PRInt32 amount,
1307                             PRIntn flags, PRIntervalTime timeout)
1308 {
1309   const PRSendFN send_fn = fd->lower->methods->send;
1310   const PRInt32 rv = send_fn(fd->lower, buf, amount, flags, timeout);
1311   if(rv < 0)
1312     /* check for PR_WOULD_BLOCK_ERROR and update blocking direction */
1313     nss_update_connecting_state(ssl_connect_2_writing, fd->secret);
1314   return rv;
1315 }
1316
1317 /* close() wrapper to avoid assertion failure due to fd->secret != NULL */
1318 static PRStatus nspr_io_close(PRFileDesc *fd)
1319 {
1320   const PRCloseFN close_fn = PR_GetDefaultIOMethods()->close;
1321   fd->secret = NULL;
1322   return close_fn(fd);
1323 }
1324
1325 /* load a PKCS #11 module */
1326 static CURLcode nss_load_module(SECMODModule **pmod, const char *library,
1327                                 const char *name)
1328 {
1329   char *config_string;
1330   SECMODModule *module = *pmod;
1331   if(module)
1332     /* already loaded */
1333     return CURLE_OK;
1334
1335   config_string = aprintf("library=%s name=%s", library, name);
1336   if(!config_string)
1337     return CURLE_OUT_OF_MEMORY;
1338
1339   module = SECMOD_LoadUserModule(config_string, NULL, PR_FALSE);
1340   free(config_string);
1341
1342   if(module && module->loaded) {
1343     /* loaded successfully */
1344     *pmod = module;
1345     return CURLE_OK;
1346   }
1347
1348   if(module)
1349     SECMOD_DestroyModule(module);
1350   return CURLE_FAILED_INIT;
1351 }
1352
1353 /* unload a PKCS #11 module */
1354 static void nss_unload_module(SECMODModule **pmod)
1355 {
1356   SECMODModule *module = *pmod;
1357   if(!module)
1358     /* not loaded */
1359     return;
1360
1361   if(SECMOD_UnloadUserModule(module) != SECSuccess)
1362     /* unload failed */
1363     return;
1364
1365   SECMOD_DestroyModule(module);
1366   *pmod = NULL;
1367 }
1368
1369 /* data might be NULL */
1370 static CURLcode nss_init_core(struct Curl_easy *data, const char *cert_dir)
1371 {
1372   NSSInitParameters initparams;
1373   PRErrorCode err;
1374   const char *err_name;
1375
1376   if(nss_context)
1377     return CURLE_OK;
1378
1379   memset((void *) &initparams, '\0', sizeof(initparams));
1380   initparams.length = sizeof(initparams);
1381
1382   if(cert_dir) {
1383     char *certpath = aprintf("sql:%s", cert_dir);
1384     if(!certpath)
1385       return CURLE_OUT_OF_MEMORY;
1386
1387     infof(data, "Initializing NSS with certpath: %s", certpath);
1388     nss_context = NSS_InitContext(certpath, "", "", "", &initparams,
1389                                   NSS_INIT_READONLY | NSS_INIT_PK11RELOAD);
1390     free(certpath);
1391
1392     if(nss_context)
1393       return CURLE_OK;
1394
1395     err = PR_GetError();
1396     err_name = nss_error_to_name(err);
1397     infof(data, "Unable to initialize NSS database: %d (%s)", err, err_name);
1398   }
1399
1400   infof(data, "Initializing NSS with certpath: none");
1401   nss_context = NSS_InitContext("", "", "", "", &initparams, NSS_INIT_READONLY
1402          | NSS_INIT_NOCERTDB   | NSS_INIT_NOMODDB       | NSS_INIT_FORCEOPEN
1403          | NSS_INIT_NOROOTINIT | NSS_INIT_OPTIMIZESPACE | NSS_INIT_PK11RELOAD);
1404   if(nss_context)
1405     return CURLE_OK;
1406
1407   err = PR_GetError();
1408   err_name = nss_error_to_name(err);
1409   failf(data, "Unable to initialize NSS: %d (%s)", err, err_name);
1410   return CURLE_SSL_CACERT_BADFILE;
1411 }
1412
1413 /* data might be NULL */
1414 static CURLcode nss_setup(struct Curl_easy *data)
1415 {
1416   char *cert_dir;
1417   struct_stat st;
1418   CURLcode result;
1419
1420   if(initialized)
1421     return CURLE_OK;
1422
1423   /* list of all CRL items we need to destroy in nss_cleanup() */
1424   Curl_llist_init(&nss_crl_list, nss_destroy_crl_item);
1425
1426   /* First we check if $SSL_DIR points to a valid dir */
1427   cert_dir = getenv("SSL_DIR");
1428   if(cert_dir) {
1429     if((stat(cert_dir, &st) != 0) ||
1430         (!S_ISDIR(st.st_mode))) {
1431       cert_dir = NULL;
1432     }
1433   }
1434
1435   /* Now we check if the default location is a valid dir */
1436   if(!cert_dir) {
1437     if((stat(SSL_DIR, &st) == 0) &&
1438         (S_ISDIR(st.st_mode))) {
1439       cert_dir = (char *)SSL_DIR;
1440     }
1441   }
1442
1443   if(nspr_io_identity == PR_INVALID_IO_LAYER) {
1444     /* allocate an identity for our own NSPR I/O layer */
1445     nspr_io_identity = PR_GetUniqueIdentity("libcurl");
1446     if(nspr_io_identity == PR_INVALID_IO_LAYER)
1447       return CURLE_OUT_OF_MEMORY;
1448
1449     /* the default methods just call down to the lower I/O layer */
1450     memcpy(&nspr_io_methods, PR_GetDefaultIOMethods(),
1451            sizeof(nspr_io_methods));
1452
1453     /* override certain methods in the table by our wrappers */
1454     nspr_io_methods.recv  = nspr_io_recv;
1455     nspr_io_methods.send  = nspr_io_send;
1456     nspr_io_methods.close = nspr_io_close;
1457   }
1458
1459   result = nss_init_core(data, cert_dir);
1460   if(result)
1461     return result;
1462
1463   if(!any_cipher_enabled())
1464     NSS_SetDomesticPolicy();
1465
1466   initialized = 1;
1467
1468   return CURLE_OK;
1469 }
1470
1471 /**
1472  * Global SSL init
1473  *
1474  * @retval 0 error initializing SSL
1475  * @retval 1 SSL initialized successfully
1476  */
1477 static int nss_init(void)
1478 {
1479   /* curl_global_init() is not thread-safe so this test is ok */
1480   if(!nss_initlock) {
1481     PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
1482     nss_initlock = PR_NewLock();
1483     nss_crllock = PR_NewLock();
1484     nss_findslot_lock = PR_NewLock();
1485     nss_trustload_lock = PR_NewLock();
1486   }
1487
1488   /* We will actually initialize NSS later */
1489
1490   return 1;
1491 }
1492
1493 /* data might be NULL */
1494 CURLcode Curl_nss_force_init(struct Curl_easy *data)
1495 {
1496   CURLcode result;
1497   if(!nss_initlock) {
1498     if(data)
1499       failf(data, "unable to initialize NSS, curl_global_init() should have "
1500                   "been called with CURL_GLOBAL_SSL or CURL_GLOBAL_ALL");
1501     return CURLE_FAILED_INIT;
1502   }
1503
1504   PR_Lock(nss_initlock);
1505   result = nss_setup(data);
1506   PR_Unlock(nss_initlock);
1507
1508   return result;
1509 }
1510
1511 /* Global cleanup */
1512 static void nss_cleanup(void)
1513 {
1514   /* This function isn't required to be threadsafe and this is only done
1515    * as a safety feature.
1516    */
1517   PR_Lock(nss_initlock);
1518   if(initialized) {
1519     /* Free references to client certificates held in the SSL session cache.
1520      * Omitting this hampers destruction of the security module owning
1521      * the certificates. */
1522     SSL_ClearSessionCache();
1523
1524     nss_unload_module(&pem_module);
1525     nss_unload_module(&trust_module);
1526     NSS_ShutdownContext(nss_context);
1527     nss_context = NULL;
1528   }
1529
1530   /* destroy all CRL items */
1531   Curl_llist_destroy(&nss_crl_list, NULL);
1532
1533   PR_Unlock(nss_initlock);
1534
1535   PR_DestroyLock(nss_initlock);
1536   PR_DestroyLock(nss_crllock);
1537   PR_DestroyLock(nss_findslot_lock);
1538   PR_DestroyLock(nss_trustload_lock);
1539   nss_initlock = NULL;
1540
1541   initialized = 0;
1542 }
1543
1544 /*
1545  * This function uses SSL_peek to determine connection status.
1546  *
1547  * Return codes:
1548  *     1 means the connection is still in place
1549  *     0 means the connection has been closed
1550  *    -1 means the connection status is unknown
1551  */
1552 static int nss_check_cxn(struct connectdata *conn)
1553 {
1554   struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
1555   struct ssl_backend_data *backend = connssl->backend;
1556   int rc;
1557   char buf;
1558
1559   DEBUGASSERT(backend);
1560
1561   rc =
1562     PR_Recv(backend->handle, (void *)&buf, 1, PR_MSG_PEEK,
1563             PR_SecondsToInterval(1));
1564   if(rc > 0)
1565     return 1; /* connection still in place */
1566
1567   if(rc == 0)
1568     return 0; /* connection has been closed */
1569
1570   return -1;  /* connection status unknown */
1571 }
1572
1573 static void close_one(struct ssl_connect_data *connssl)
1574 {
1575   /* before the cleanup, check whether we are using a client certificate */
1576   struct ssl_backend_data *backend = connssl->backend;
1577   bool client_cert = true;
1578
1579   DEBUGASSERT(backend);
1580
1581   client_cert = (backend->client_nickname != NULL)
1582     || (backend->obj_clicert != NULL);
1583
1584   if(backend->handle) {
1585     char buf[32];
1586     /* Maybe the server has already sent a close notify alert.
1587        Read it to avoid an RST on the TCP connection. */
1588     (void)PR_Recv(backend->handle, buf, (int)sizeof(buf), 0,
1589                   PR_INTERVAL_NO_WAIT);
1590   }
1591
1592   free(backend->client_nickname);
1593   backend->client_nickname = NULL;
1594
1595   /* destroy all NSS objects in order to avoid failure of NSS shutdown */
1596   Curl_llist_destroy(&backend->obj_list, NULL);
1597   backend->obj_clicert = NULL;
1598
1599   if(backend->handle) {
1600     if(client_cert)
1601       /* A server might require different authentication based on the
1602        * particular path being requested by the client.  To support this
1603        * scenario, we must ensure that a connection will never reuse the
1604        * authentication data from a previous connection. */
1605       SSL_InvalidateSession(backend->handle);
1606
1607     PR_Close(backend->handle);
1608     backend->handle = NULL;
1609   }
1610 }
1611
1612 /*
1613  * This function is called when an SSL connection is closed.
1614  */
1615 static void nss_close(struct Curl_easy *data, struct connectdata *conn,
1616                       int sockindex)
1617 {
1618   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1619 #ifndef CURL_DISABLE_PROXY
1620   struct ssl_connect_data *connssl_proxy = &conn->proxy_ssl[sockindex];
1621 #endif
1622   struct ssl_backend_data *backend = connssl->backend;
1623   (void)data;
1624
1625   DEBUGASSERT(backend);
1626 #ifndef CURL_DISABLE_PROXY
1627   DEBUGASSERT(connssl_proxy->backend != NULL);
1628 #endif
1629
1630   if(backend->handle
1631 #ifndef CURL_DISABLE_PROXY
1632     || connssl_proxy->backend->handle
1633 #endif
1634     ) {
1635     /* NSS closes the socket we previously handed to it, so we must mark it
1636        as closed to avoid double close */
1637     fake_sclose(conn->sock[sockindex]);
1638     conn->sock[sockindex] = CURL_SOCKET_BAD;
1639   }
1640
1641 #ifndef CURL_DISABLE_PROXY
1642   if(backend->handle)
1643     /* nss_close(connssl) will transitively close also
1644        connssl_proxy->backend->handle if both are used. Clear it to avoid
1645        a double close leading to crash. */
1646     connssl_proxy->backend->handle = NULL;
1647
1648   close_one(connssl_proxy);
1649 #endif
1650   close_one(connssl);
1651 }
1652
1653 /* return true if NSS can provide error code (and possibly msg) for the
1654    error */
1655 static bool is_nss_error(CURLcode err)
1656 {
1657   switch(err) {
1658   case CURLE_PEER_FAILED_VERIFICATION:
1659   case CURLE_SSL_CERTPROBLEM:
1660   case CURLE_SSL_CONNECT_ERROR:
1661   case CURLE_SSL_ISSUER_ERROR:
1662     return true;
1663
1664   default:
1665     return false;
1666   }
1667 }
1668
1669 /* return true if the given error code is related to a client certificate */
1670 static bool is_cc_error(PRInt32 err)
1671 {
1672   switch(err) {
1673   case SSL_ERROR_BAD_CERT_ALERT:
1674   case SSL_ERROR_EXPIRED_CERT_ALERT:
1675   case SSL_ERROR_REVOKED_CERT_ALERT:
1676     return true;
1677
1678   default:
1679     return false;
1680   }
1681 }
1682
1683 static Curl_recv nss_recv;
1684 static Curl_send nss_send;
1685
1686 static CURLcode nss_load_ca_certificates(struct Curl_easy *data,
1687                                          struct connectdata *conn,
1688                                          int sockindex)
1689 {
1690   const char *cafile = SSL_CONN_CONFIG(CAfile);
1691   const char *capath = SSL_CONN_CONFIG(CApath);
1692   bool use_trust_module;
1693   CURLcode result = CURLE_OK;
1694
1695   /* treat empty string as unset */
1696   if(cafile && !cafile[0])
1697     cafile = NULL;
1698   if(capath && !capath[0])
1699     capath = NULL;
1700
1701   infof(data, " CAfile: %s", cafile ? cafile : "none");
1702   infof(data, " CApath: %s", capath ? capath : "none");
1703
1704   /* load libnssckbi.so if no other trust roots were specified */
1705   use_trust_module = !cafile && !capath;
1706
1707   PR_Lock(nss_trustload_lock);
1708   if(use_trust_module && !trust_module) {
1709     /* libnssckbi.so needed but not yet loaded --> load it! */
1710     result = nss_load_module(&trust_module, trust_library, "trust");
1711     infof(data, "%s %s", (result) ? "failed to load" : "loaded",
1712           trust_library);
1713     if(result == CURLE_FAILED_INIT)
1714       /* If libnssckbi.so is not available (or fails to load), one can still
1715          use CA certificates stored in NSS database.  Ignore the failure. */
1716       result = CURLE_OK;
1717   }
1718   else if(!use_trust_module && trust_module) {
1719     /* libnssckbi.so not needed but already loaded --> unload it! */
1720     infof(data, "unloading %s", trust_library);
1721     nss_unload_module(&trust_module);
1722   }
1723   PR_Unlock(nss_trustload_lock);
1724
1725   if(cafile)
1726     result = nss_load_cert(&conn->ssl[sockindex], cafile, PR_TRUE);
1727
1728   if(result)
1729     return result;
1730
1731   if(capath) {
1732     struct_stat st;
1733     if(stat(capath, &st) == -1)
1734       return CURLE_SSL_CACERT_BADFILE;
1735
1736     if(S_ISDIR(st.st_mode)) {
1737       PRDirEntry *entry;
1738       PRDir *dir = PR_OpenDir(capath);
1739       if(!dir)
1740         return CURLE_SSL_CACERT_BADFILE;
1741
1742       while((entry =
1743              PR_ReadDir(dir, (PRDirFlags)(PR_SKIP_BOTH | PR_SKIP_HIDDEN)))) {
1744         char *fullpath = aprintf("%s/%s", capath, entry->name);
1745         if(!fullpath) {
1746           PR_CloseDir(dir);
1747           return CURLE_OUT_OF_MEMORY;
1748         }
1749
1750         if(CURLE_OK != nss_load_cert(&conn->ssl[sockindex], fullpath, PR_TRUE))
1751           /* This is purposefully tolerant of errors so non-PEM files can
1752            * be in the same directory */
1753           infof(data, "failed to load '%s' from CURLOPT_CAPATH", fullpath);
1754
1755         free(fullpath);
1756       }
1757
1758       PR_CloseDir(dir);
1759     }
1760     else
1761       infof(data, "WARNING: CURLOPT_CAPATH not a directory (%s)", capath);
1762   }
1763
1764   return CURLE_OK;
1765 }
1766
1767 static CURLcode nss_sslver_from_curl(PRUint16 *nssver, long version)
1768 {
1769   switch(version) {
1770   case CURL_SSLVERSION_SSLv2:
1771     *nssver = SSL_LIBRARY_VERSION_2;
1772     return CURLE_OK;
1773
1774   case CURL_SSLVERSION_SSLv3:
1775     return CURLE_NOT_BUILT_IN;
1776
1777   case CURL_SSLVERSION_TLSv1_0:
1778     *nssver = SSL_LIBRARY_VERSION_TLS_1_0;
1779     return CURLE_OK;
1780
1781   case CURL_SSLVERSION_TLSv1_1:
1782 #ifdef SSL_LIBRARY_VERSION_TLS_1_1
1783     *nssver = SSL_LIBRARY_VERSION_TLS_1_1;
1784     return CURLE_OK;
1785 #else
1786     return CURLE_SSL_CONNECT_ERROR;
1787 #endif
1788
1789   case CURL_SSLVERSION_TLSv1_2:
1790 #ifdef SSL_LIBRARY_VERSION_TLS_1_2
1791     *nssver = SSL_LIBRARY_VERSION_TLS_1_2;
1792     return CURLE_OK;
1793 #else
1794     return CURLE_SSL_CONNECT_ERROR;
1795 #endif
1796
1797   case CURL_SSLVERSION_TLSv1_3:
1798 #ifdef SSL_LIBRARY_VERSION_TLS_1_3
1799     *nssver = SSL_LIBRARY_VERSION_TLS_1_3;
1800     return CURLE_OK;
1801 #else
1802     return CURLE_SSL_CONNECT_ERROR;
1803 #endif
1804
1805   default:
1806     return CURLE_SSL_CONNECT_ERROR;
1807   }
1808 }
1809
1810 static CURLcode nss_init_sslver(SSLVersionRange *sslver,
1811                                 struct Curl_easy *data,
1812                                 struct connectdata *conn)
1813 {
1814   CURLcode result;
1815   const long min = SSL_CONN_CONFIG(version);
1816   const long max = SSL_CONN_CONFIG(version_max);
1817   SSLVersionRange vrange;
1818
1819   switch(min) {
1820   case CURL_SSLVERSION_TLSv1:
1821   case CURL_SSLVERSION_DEFAULT:
1822     /* Bump our minimum TLS version if NSS has stricter requirements. */
1823     if(SSL_VersionRangeGetDefault(ssl_variant_stream, &vrange) != SECSuccess)
1824       return CURLE_SSL_CONNECT_ERROR;
1825     if(sslver->min < vrange.min)
1826       sslver->min = vrange.min;
1827     break;
1828   default:
1829     result = nss_sslver_from_curl(&sslver->min, min);
1830     if(result) {
1831       failf(data, "unsupported min version passed via CURLOPT_SSLVERSION");
1832       return result;
1833     }
1834   }
1835
1836   switch(max) {
1837   case CURL_SSLVERSION_MAX_NONE:
1838   case CURL_SSLVERSION_MAX_DEFAULT:
1839     break;
1840   default:
1841     result = nss_sslver_from_curl(&sslver->max, max >> 16);
1842     if(result) {
1843       failf(data, "unsupported max version passed via CURLOPT_SSLVERSION");
1844       return result;
1845     }
1846   }
1847
1848   return CURLE_OK;
1849 }
1850
1851 static CURLcode nss_fail_connect(struct ssl_connect_data *connssl,
1852                                  struct Curl_easy *data,
1853                                  CURLcode curlerr)
1854 {
1855   struct ssl_backend_data *backend = connssl->backend;
1856
1857   DEBUGASSERT(backend);
1858
1859   if(is_nss_error(curlerr)) {
1860     /* read NSPR error code */
1861     PRErrorCode err = PR_GetError();
1862     if(is_cc_error(err))
1863       curlerr = CURLE_SSL_CERTPROBLEM;
1864
1865     /* print the error number and error string */
1866     infof(data, "NSS error %d (%s)", err, nss_error_to_name(err));
1867
1868     /* print a human-readable message describing the error if available */
1869     nss_print_error_message(data, err);
1870   }
1871
1872   /* cleanup on connection failure */
1873   Curl_llist_destroy(&backend->obj_list, NULL);
1874
1875   return curlerr;
1876 }
1877
1878 /* Switch the SSL socket into blocking or non-blocking mode. */
1879 static CURLcode nss_set_blocking(struct ssl_connect_data *connssl,
1880                                  struct Curl_easy *data,
1881                                  bool blocking)
1882 {
1883   PRSocketOptionData sock_opt;
1884   struct ssl_backend_data *backend = connssl->backend;
1885
1886   DEBUGASSERT(backend);
1887
1888   sock_opt.option = PR_SockOpt_Nonblocking;
1889   sock_opt.value.non_blocking = !blocking;
1890
1891   if(PR_SetSocketOption(backend->handle, &sock_opt) != PR_SUCCESS)
1892     return nss_fail_connect(connssl, data, CURLE_SSL_CONNECT_ERROR);
1893
1894   return CURLE_OK;
1895 }
1896
1897 static CURLcode nss_setup_connect(struct Curl_easy *data,
1898                                   struct connectdata *conn, int sockindex)
1899 {
1900   PRFileDesc *model = NULL;
1901   PRFileDesc *nspr_io = NULL;
1902   PRFileDesc *nspr_io_stub = NULL;
1903   PRBool ssl_no_cache;
1904   PRBool ssl_cbc_random_iv;
1905   curl_socket_t sockfd = conn->sock[sockindex];
1906   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1907   struct ssl_backend_data *backend = connssl->backend;
1908   CURLcode result;
1909   bool second_layer = FALSE;
1910   SSLVersionRange sslver_supported;
1911   SSLVersionRange sslver = {
1912     SSL_LIBRARY_VERSION_TLS_1_0,  /* min */
1913 #ifdef SSL_LIBRARY_VERSION_TLS_1_3
1914     SSL_LIBRARY_VERSION_TLS_1_3   /* max */
1915 #elif defined SSL_LIBRARY_VERSION_TLS_1_2
1916     SSL_LIBRARY_VERSION_TLS_1_2
1917 #elif defined SSL_LIBRARY_VERSION_TLS_1_1
1918     SSL_LIBRARY_VERSION_TLS_1_1
1919 #else
1920     SSL_LIBRARY_VERSION_TLS_1_0
1921 #endif
1922   };
1923   char *snihost = Curl_ssl_snihost(data, SSL_HOST_NAME(), NULL);
1924   if(!snihost) {
1925     failf(data, "Failed to set SNI");
1926     return CURLE_SSL_CONNECT_ERROR;
1927   }
1928
1929   DEBUGASSERT(backend);
1930
1931   backend->data = data;
1932
1933   /* list of all NSS objects we need to destroy in nss_do_close() */
1934   Curl_llist_init(&backend->obj_list, nss_destroy_object);
1935
1936   PR_Lock(nss_initlock);
1937   result = nss_setup(data);
1938   if(result) {
1939     PR_Unlock(nss_initlock);
1940     goto error;
1941   }
1942
1943   PK11_SetPasswordFunc(nss_get_password);
1944
1945   result = nss_load_module(&pem_module, pem_library, "PEM");
1946   PR_Unlock(nss_initlock);
1947   if(result == CURLE_FAILED_INIT)
1948     infof(data, "WARNING: failed to load NSS PEM library %s. Using "
1949                 "OpenSSL PEM certificates will not work.", pem_library);
1950   else if(result)
1951     goto error;
1952
1953   result = CURLE_SSL_CONNECT_ERROR;
1954
1955   model = PR_NewTCPSocket();
1956   if(!model)
1957     goto error;
1958   model = SSL_ImportFD(NULL, model);
1959
1960   if(SSL_OptionSet(model, SSL_SECURITY, PR_TRUE) != SECSuccess)
1961     goto error;
1962   if(SSL_OptionSet(model, SSL_HANDSHAKE_AS_SERVER, PR_FALSE) != SECSuccess)
1963     goto error;
1964   if(SSL_OptionSet(model, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE) != SECSuccess)
1965     goto error;
1966
1967   /* do not use SSL cache if disabled or we are not going to verify peer */
1968   ssl_no_cache = (SSL_SET_OPTION(primary.sessionid)
1969                   && SSL_CONN_CONFIG(verifypeer)) ? PR_FALSE : PR_TRUE;
1970   if(SSL_OptionSet(model, SSL_NO_CACHE, ssl_no_cache) != SECSuccess)
1971     goto error;
1972
1973   /* enable/disable the requested SSL version(s) */
1974   if(nss_init_sslver(&sslver, data, conn) != CURLE_OK)
1975     goto error;
1976   if(SSL_VersionRangeGetSupported(ssl_variant_stream,
1977                                   &sslver_supported) != SECSuccess)
1978     goto error;
1979   if(sslver_supported.max < sslver.max && sslver_supported.max >= sslver.min) {
1980     char *sslver_req_str, *sslver_supp_str;
1981     sslver_req_str = nss_sslver_to_name(sslver.max);
1982     sslver_supp_str = nss_sslver_to_name(sslver_supported.max);
1983     if(sslver_req_str && sslver_supp_str)
1984       infof(data, "Falling back from %s to max supported SSL version (%s)",
1985             sslver_req_str, sslver_supp_str);
1986     free(sslver_req_str);
1987     free(sslver_supp_str);
1988     sslver.max = sslver_supported.max;
1989   }
1990   if(SSL_VersionRangeSet(model, &sslver) != SECSuccess)
1991     goto error;
1992
1993   ssl_cbc_random_iv = !SSL_SET_OPTION(enable_beast);
1994 #ifdef SSL_CBC_RANDOM_IV
1995   /* unless the user explicitly asks to allow the protocol vulnerability, we
1996      use the work-around */
1997   if(SSL_OptionSet(model, SSL_CBC_RANDOM_IV, ssl_cbc_random_iv) != SECSuccess)
1998     infof(data, "WARNING: failed to set SSL_CBC_RANDOM_IV = %d",
1999           ssl_cbc_random_iv);
2000 #else
2001   if(ssl_cbc_random_iv)
2002     infof(data, "WARNING: support for SSL_CBC_RANDOM_IV not compiled in");
2003 #endif
2004
2005   if(SSL_CONN_CONFIG(cipher_list)) {
2006     if(set_ciphers(data, model, SSL_CONN_CONFIG(cipher_list)) != SECSuccess) {
2007       result = CURLE_SSL_CIPHER;
2008       goto error;
2009     }
2010   }
2011
2012   if(!SSL_CONN_CONFIG(verifypeer) && SSL_CONN_CONFIG(verifyhost))
2013     infof(data, "WARNING: ignoring value of ssl.verifyhost");
2014
2015   /* bypass the default SSL_AuthCertificate() hook in case we do not want to
2016    * verify peer */
2017   if(SSL_AuthCertificateHook(model, nss_auth_cert_hook, data) != SECSuccess)
2018     goto error;
2019
2020   /* not checked yet */
2021   SSL_SET_OPTION_LVALUE(certverifyresult) = 0;
2022
2023   if(SSL_BadCertHook(model, BadCertHandler, data) != SECSuccess)
2024     goto error;
2025
2026   if(SSL_HandshakeCallback(model, HandshakeCallback, data) != SECSuccess)
2027     goto error;
2028
2029   {
2030     const CURLcode rv = nss_load_ca_certificates(data, conn, sockindex);
2031     if((rv == CURLE_SSL_CACERT_BADFILE) && !SSL_CONN_CONFIG(verifypeer))
2032       /* not a fatal error because we are not going to verify the peer */
2033       infof(data, "WARNING: CA certificates failed to load");
2034     else if(rv) {
2035       result = rv;
2036       goto error;
2037     }
2038   }
2039
2040   if(SSL_SET_OPTION(primary.CRLfile)) {
2041     const CURLcode rv = nss_load_crl(SSL_SET_OPTION(primary.CRLfile));
2042     if(rv) {
2043       result = rv;
2044       goto error;
2045     }
2046     infof(data, "  CRLfile: %s", SSL_SET_OPTION(primary.CRLfile));
2047   }
2048
2049   if(SSL_SET_OPTION(primary.clientcert)) {
2050     char *nickname = dup_nickname(data, SSL_SET_OPTION(primary.clientcert));
2051     if(nickname) {
2052       /* we are not going to use libnsspem.so to read the client cert */
2053       backend->obj_clicert = NULL;
2054     }
2055     else {
2056       CURLcode rv = cert_stuff(data, conn, sockindex,
2057                                SSL_SET_OPTION(primary.clientcert),
2058                                SSL_SET_OPTION(key));
2059       if(rv) {
2060         /* failf() is already done in cert_stuff() */
2061         result = rv;
2062         goto error;
2063       }
2064     }
2065
2066     /* store the nickname for SelectClientCert() called during handshake */
2067     backend->client_nickname = nickname;
2068   }
2069   else
2070     backend->client_nickname = NULL;
2071
2072   if(SSL_GetClientAuthDataHook(model, SelectClientCert,
2073                                (void *)connssl) != SECSuccess) {
2074     result = CURLE_SSL_CERTPROBLEM;
2075     goto error;
2076   }
2077
2078 #ifndef CURL_DISABLE_PROXY
2079   if(conn->proxy_ssl[sockindex].use) {
2080     struct ssl_backend_data *proxy_backend;
2081     proxy_backend = conn->proxy_ssl[sockindex].backend;
2082     DEBUGASSERT(ssl_connection_complete == conn->proxy_ssl[sockindex].state);
2083     DEBUGASSERT(proxy_backend);
2084     DEBUGASSERT(proxy_backend->handle);
2085     nspr_io = proxy_backend->handle;
2086     second_layer = TRUE;
2087   }
2088 #endif
2089   else {
2090     /* wrap OS file descriptor by NSPR's file descriptor abstraction */
2091     nspr_io = PR_ImportTCPSocket(sockfd);
2092     if(!nspr_io)
2093       goto error;
2094   }
2095
2096   /* create our own NSPR I/O layer */
2097   nspr_io_stub = PR_CreateIOLayerStub(nspr_io_identity, &nspr_io_methods);
2098   if(!nspr_io_stub) {
2099     if(!second_layer)
2100       PR_Close(nspr_io);
2101     goto error;
2102   }
2103
2104   /* make the per-connection data accessible from NSPR I/O callbacks */
2105   nspr_io_stub->secret = (void *)connssl;
2106
2107   /* push our new layer to the NSPR I/O stack */
2108   if(PR_PushIOLayer(nspr_io, PR_TOP_IO_LAYER, nspr_io_stub) != PR_SUCCESS) {
2109     if(!second_layer)
2110       PR_Close(nspr_io);
2111     PR_Close(nspr_io_stub);
2112     goto error;
2113   }
2114
2115   /* import our model socket onto the current I/O stack */
2116   backend->handle = SSL_ImportFD(model, nspr_io);
2117   if(!backend->handle) {
2118     if(!second_layer)
2119       PR_Close(nspr_io);
2120     goto error;
2121   }
2122
2123   PR_Close(model); /* We don't need this any more */
2124   model = NULL;
2125
2126   /* This is the password associated with the cert that we're using */
2127   if(SSL_SET_OPTION(key_passwd)) {
2128     SSL_SetPKCS11PinArg(backend->handle, SSL_SET_OPTION(key_passwd));
2129   }
2130
2131 #ifdef SSL_ENABLE_OCSP_STAPLING
2132   if(SSL_CONN_CONFIG(verifystatus)) {
2133     if(SSL_OptionSet(backend->handle, SSL_ENABLE_OCSP_STAPLING, PR_TRUE)
2134         != SECSuccess)
2135       goto error;
2136   }
2137 #endif
2138
2139 #ifdef SSL_ENABLE_ALPN
2140   if(SSL_OptionSet(backend->handle, SSL_ENABLE_ALPN, conn->bits.tls_enable_alpn
2141                    ? PR_TRUE : PR_FALSE) != SECSuccess)
2142     goto error;
2143 #endif
2144
2145 #if NSSVERNUM >= 0x030f04 /* 3.15.4 */
2146   if(data->set.ssl.falsestart) {
2147     if(SSL_OptionSet(backend->handle, SSL_ENABLE_FALSE_START, PR_TRUE)
2148         != SECSuccess)
2149       goto error;
2150
2151     if(SSL_SetCanFalseStartCallback(backend->handle, CanFalseStartCallback,
2152         data) != SECSuccess)
2153       goto error;
2154   }
2155 #endif
2156
2157 #if defined(SSL_ENABLE_ALPN)
2158   if(conn->bits.tls_enable_alpn) {
2159     int cur = 0;
2160     unsigned char protocols[128];
2161
2162 #ifdef USE_HTTP2
2163     if(data->state.httpwant >= CURL_HTTP_VERSION_2
2164 #ifndef CURL_DISABLE_PROXY
2165        && (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)
2166 #endif
2167       ) {
2168       protocols[cur++] = ALPN_H2_LENGTH;
2169       memcpy(&protocols[cur], ALPN_H2, ALPN_H2_LENGTH);
2170       cur += ALPN_H2_LENGTH;
2171     }
2172 #endif
2173     protocols[cur++] = ALPN_HTTP_1_1_LENGTH;
2174     memcpy(&protocols[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH);
2175     cur += ALPN_HTTP_1_1_LENGTH;
2176
2177     if(SSL_SetNextProtoNego(backend->handle, protocols, cur) != SECSuccess)
2178       goto error;
2179   }
2180 #endif
2181
2182
2183   /* Force handshake on next I/O */
2184   if(SSL_ResetHandshake(backend->handle, /* asServer */ PR_FALSE)
2185       != SECSuccess)
2186     goto error;
2187
2188   /* propagate hostname to the TLS layer */
2189   if(SSL_SetURL(backend->handle, snihost) != SECSuccess)
2190     goto error;
2191
2192   /* prevent NSS from re-using the session for a different hostname */
2193   if(SSL_SetSockPeerID(backend->handle, snihost) != SECSuccess)
2194     goto error;
2195
2196   return CURLE_OK;
2197
2198 error:
2199   if(model)
2200     PR_Close(model);
2201
2202   return nss_fail_connect(connssl, data, result);
2203 }
2204
2205 static CURLcode nss_do_connect(struct Curl_easy *data,
2206                                struct connectdata *conn, int sockindex)
2207 {
2208   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
2209   struct ssl_backend_data *backend = connssl->backend;
2210   CURLcode result = CURLE_SSL_CONNECT_ERROR;
2211   PRUint32 timeout;
2212
2213   /* check timeout situation */
2214   const timediff_t time_left = Curl_timeleft(data, NULL, TRUE);
2215   if(time_left < 0) {
2216     failf(data, "timed out before SSL handshake");
2217     result = CURLE_OPERATION_TIMEDOUT;
2218     goto error;
2219   }
2220
2221   DEBUGASSERT(backend);
2222
2223   /* Force the handshake now */
2224   timeout = PR_MillisecondsToInterval((PRUint32) time_left);
2225   if(SSL_ForceHandshakeWithTimeout(backend->handle, timeout) != SECSuccess) {
2226     if(PR_GetError() == PR_WOULD_BLOCK_ERROR)
2227       /* blocking direction is updated by nss_update_connecting_state() */
2228       return CURLE_AGAIN;
2229     else if(SSL_SET_OPTION(certverifyresult) == SSL_ERROR_BAD_CERT_DOMAIN)
2230       result = CURLE_PEER_FAILED_VERIFICATION;
2231     else if(SSL_SET_OPTION(certverifyresult) != 0)
2232       result = CURLE_PEER_FAILED_VERIFICATION;
2233     goto error;
2234   }
2235
2236   result = display_conn_info(data, backend->handle);
2237   if(result)
2238     goto error;
2239
2240   if(SSL_CONN_CONFIG(issuercert)) {
2241     SECStatus ret = SECFailure;
2242     char *nickname = dup_nickname(data, SSL_CONN_CONFIG(issuercert));
2243     if(nickname) {
2244       /* we support only nicknames in case of issuercert for now */
2245       ret = check_issuer_cert(backend->handle, nickname);
2246       free(nickname);
2247     }
2248
2249     if(SECFailure == ret) {
2250       infof(data, "SSL certificate issuer check failed");
2251       result = CURLE_SSL_ISSUER_ERROR;
2252       goto error;
2253     }
2254     else {
2255       infof(data, "SSL certificate issuer check ok");
2256     }
2257   }
2258
2259   result = cmp_peer_pubkey(connssl, SSL_PINNED_PUB_KEY());
2260   if(result)
2261     /* status already printed */
2262     goto error;
2263
2264   return CURLE_OK;
2265
2266 error:
2267   return nss_fail_connect(connssl, data, result);
2268 }
2269
2270 static CURLcode nss_connect_common(struct Curl_easy *data,
2271                                    struct connectdata *conn, int sockindex,
2272                                    bool *done)
2273 {
2274   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
2275   const bool blocking = (done == NULL);
2276   CURLcode result;
2277
2278   if(connssl->state == ssl_connection_complete) {
2279     if(!blocking)
2280       *done = TRUE;
2281     return CURLE_OK;
2282   }
2283
2284   if(connssl->connecting_state == ssl_connect_1) {
2285     result = nss_setup_connect(data, conn, sockindex);
2286     if(result)
2287       /* we do not expect CURLE_AGAIN from nss_setup_connect() */
2288       return result;
2289
2290     connssl->connecting_state = ssl_connect_2;
2291   }
2292
2293   /* enable/disable blocking mode before handshake */
2294   result = nss_set_blocking(connssl, data, blocking);
2295   if(result)
2296     return result;
2297
2298   result = nss_do_connect(data, conn, sockindex);
2299   switch(result) {
2300   case CURLE_OK:
2301     break;
2302   case CURLE_AGAIN:
2303     /* CURLE_AGAIN in non-blocking mode is not an error */
2304     if(!blocking)
2305       return CURLE_OK;
2306     else
2307       return result;
2308   default:
2309     return result;
2310   }
2311
2312   if(blocking) {
2313     /* in blocking mode, set NSS non-blocking mode _after_ SSL handshake */
2314     result = nss_set_blocking(connssl, data, /* blocking */ FALSE);
2315     if(result)
2316       return result;
2317   }
2318   else
2319     /* signal completed SSL handshake */
2320     *done = TRUE;
2321
2322   connssl->state = ssl_connection_complete;
2323   conn->recv[sockindex] = nss_recv;
2324   conn->send[sockindex] = nss_send;
2325
2326   /* ssl_connect_done is never used outside, go back to the initial state */
2327   connssl->connecting_state = ssl_connect_1;
2328
2329   return CURLE_OK;
2330 }
2331
2332 static CURLcode nss_connect(struct Curl_easy *data, struct connectdata *conn,
2333                             int sockindex)
2334 {
2335   return nss_connect_common(data, conn, sockindex, /* blocking */ NULL);
2336 }
2337
2338 static CURLcode nss_connect_nonblocking(struct Curl_easy *data,
2339                                         struct connectdata *conn,
2340                                         int sockindex, bool *done)
2341 {
2342   return nss_connect_common(data, conn, sockindex, done);
2343 }
2344
2345 static ssize_t nss_send(struct Curl_easy *data,    /* transfer */
2346                         int sockindex,             /* socketindex */
2347                         const void *mem,           /* send this data */
2348                         size_t len,                /* amount to write */
2349                         CURLcode *curlcode)
2350 {
2351   struct connectdata *conn = data->conn;
2352   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
2353   struct ssl_backend_data *backend = connssl->backend;
2354   ssize_t rc;
2355
2356   DEBUGASSERT(backend);
2357
2358   /* The SelectClientCert() hook uses this for infof() and failf() but the
2359      handle stored in nss_setup_connect() could have already been freed. */
2360   backend->data = data;
2361
2362   rc = PR_Send(backend->handle, mem, (int)len, 0, PR_INTERVAL_NO_WAIT);
2363   if(rc < 0) {
2364     PRInt32 err = PR_GetError();
2365     if(err == PR_WOULD_BLOCK_ERROR)
2366       *curlcode = CURLE_AGAIN;
2367     else {
2368       /* print the error number and error string */
2369       const char *err_name = nss_error_to_name(err);
2370       infof(data, "SSL write: error %d (%s)", err, err_name);
2371
2372       /* print a human-readable message describing the error if available */
2373       nss_print_error_message(data, err);
2374
2375       *curlcode = (is_cc_error(err))
2376         ? CURLE_SSL_CERTPROBLEM
2377         : CURLE_SEND_ERROR;
2378     }
2379
2380     return -1;
2381   }
2382
2383   return rc; /* number of bytes */
2384 }
2385
2386 static ssize_t nss_recv(struct Curl_easy *data,    /* transfer */
2387                         int sockindex,             /* socketindex */
2388                         char *buf,             /* store read data here */
2389                         size_t buffersize,     /* max amount to read */
2390                         CURLcode *curlcode)
2391 {
2392   struct connectdata *conn = data->conn;
2393   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
2394   struct ssl_backend_data *backend = connssl->backend;
2395   ssize_t nread;
2396
2397   DEBUGASSERT(backend);
2398
2399   /* The SelectClientCert() hook uses this for infof() and failf() but the
2400      handle stored in nss_setup_connect() could have already been freed. */
2401   backend->data = data;
2402
2403   nread = PR_Recv(backend->handle, buf, (int)buffersize, 0,
2404                   PR_INTERVAL_NO_WAIT);
2405   if(nread < 0) {
2406     /* failed SSL read */
2407     PRInt32 err = PR_GetError();
2408
2409     if(err == PR_WOULD_BLOCK_ERROR)
2410       *curlcode = CURLE_AGAIN;
2411     else {
2412       /* print the error number and error string */
2413       const char *err_name = nss_error_to_name(err);
2414       infof(data, "SSL read: errno %d (%s)", err, err_name);
2415
2416       /* print a human-readable message describing the error if available */
2417       nss_print_error_message(data, err);
2418
2419       *curlcode = (is_cc_error(err))
2420         ? CURLE_SSL_CERTPROBLEM
2421         : CURLE_RECV_ERROR;
2422     }
2423
2424     return -1;
2425   }
2426
2427   return nread;
2428 }
2429
2430 static size_t nss_version(char *buffer, size_t size)
2431 {
2432   return msnprintf(buffer, size, "NSS/%s", NSS_GetVersion());
2433 }
2434
2435 /* data might be NULL */
2436 static int Curl_nss_seed(struct Curl_easy *data)
2437 {
2438   /* make sure that NSS is initialized */
2439   return !!Curl_nss_force_init(data);
2440 }
2441
2442 /* data might be NULL */
2443 static CURLcode nss_random(struct Curl_easy *data,
2444                            unsigned char *entropy,
2445                            size_t length)
2446 {
2447   Curl_nss_seed(data);  /* Initiate the seed if not already done */
2448
2449   if(SECSuccess != PK11_GenerateRandom(entropy, curlx_uztosi(length)))
2450     /* signal a failure */
2451     return CURLE_FAILED_INIT;
2452
2453   return CURLE_OK;
2454 }
2455
2456 static CURLcode nss_sha256sum(const unsigned char *tmp, /* input */
2457                               size_t tmplen,
2458                               unsigned char *sha256sum, /* output */
2459                               size_t sha256len)
2460 {
2461   PK11Context *SHA256pw = PK11_CreateDigestContext(SEC_OID_SHA256);
2462   unsigned int SHA256out;
2463
2464   if(!SHA256pw)
2465     return CURLE_NOT_BUILT_IN;
2466
2467   PK11_DigestOp(SHA256pw, tmp, curlx_uztoui(tmplen));
2468   PK11_DigestFinal(SHA256pw, sha256sum, &SHA256out, curlx_uztoui(sha256len));
2469   PK11_DestroyContext(SHA256pw, PR_TRUE);
2470
2471   return CURLE_OK;
2472 }
2473
2474 static bool nss_cert_status_request(void)
2475 {
2476 #ifdef SSL_ENABLE_OCSP_STAPLING
2477   return TRUE;
2478 #else
2479   return FALSE;
2480 #endif
2481 }
2482
2483 static bool nss_false_start(void)
2484 {
2485 #if NSSVERNUM >= 0x030f04 /* 3.15.4 */
2486   return TRUE;
2487 #else
2488   return FALSE;
2489 #endif
2490 }
2491
2492 static void *nss_get_internals(struct ssl_connect_data *connssl,
2493                                CURLINFO info UNUSED_PARAM)
2494 {
2495   struct ssl_backend_data *backend = connssl->backend;
2496   (void)info;
2497   DEBUGASSERT(backend);
2498   return backend->handle;
2499 }
2500
2501 const struct Curl_ssl Curl_ssl_nss = {
2502   { CURLSSLBACKEND_NSS, "nss" }, /* info */
2503
2504   SSLSUPP_CA_PATH |
2505   SSLSUPP_CERTINFO |
2506   SSLSUPP_PINNEDPUBKEY |
2507   SSLSUPP_HTTPS_PROXY,
2508
2509   sizeof(struct ssl_backend_data),
2510
2511   nss_init,                     /* init */
2512   nss_cleanup,                  /* cleanup */
2513   nss_version,                  /* version */
2514   nss_check_cxn,                /* check_cxn */
2515   /* NSS has no shutdown function provided and thus always fail */
2516   Curl_none_shutdown,           /* shutdown */
2517   Curl_none_data_pending,       /* data_pending */
2518   nss_random,                   /* random */
2519   nss_cert_status_request,      /* cert_status_request */
2520   nss_connect,                  /* connect */
2521   nss_connect_nonblocking,      /* connect_nonblocking */
2522   Curl_ssl_getsock,             /* getsock */
2523   nss_get_internals,            /* get_internals */
2524   nss_close,                    /* close_one */
2525   Curl_none_close_all,          /* close_all */
2526   /* NSS has its own session ID cache */
2527   Curl_none_session_free,       /* session_free */
2528   Curl_none_set_engine,         /* set_engine */
2529   Curl_none_set_engine_default, /* set_engine_default */
2530   Curl_none_engines_list,       /* engines_list */
2531   nss_false_start,              /* false_start */
2532   nss_sha256sum,                /* sha256sum */
2533   NULL,                         /* associate_connection */
2534   NULL                          /* disassociate_connection */
2535 };
2536
2537 #endif /* USE_NSS */