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