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