LCOV - code coverage report
Current view: top level - security/manager/ssl - nsPKCS12Blob.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 260 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 15 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* This Source Code Form is subject to the terms of the Mozilla Public
       2             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       3             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       4             : 
       5             : #include "nsPKCS12Blob.h"
       6             : 
       7             : #include "ScopedNSSTypes.h"
       8             : #include "mozilla/Assertions.h"
       9             : #include "mozilla/Casting.h"
      10             : #include "mozilla/Unused.h"
      11             : #include "nsICertificateDialogs.h"
      12             : #include "nsIFile.h"
      13             : #include "nsIInputStream.h"
      14             : #include "nsNSSCertHelper.h"
      15             : #include "nsNSSCertificate.h"
      16             : #include "nsNSSHelper.h"
      17             : #include "nsNetUtil.h"
      18             : #include "nsReadableUtils.h"
      19             : #include "nsThreadUtils.h"
      20             : #include "pkix/pkixtypes.h"
      21             : #include "secerr.h"
      22             : 
      23             : using namespace mozilla;
      24             : extern LazyLogModule gPIPNSSLog;
      25             : 
      26             : #define PIP_PKCS12_TMPFILENAME   NS_LITERAL_CSTRING(".pip_p12tmp")
      27             : #define PIP_PKCS12_BUFFER_SIZE   2048
      28             : #define PIP_PKCS12_USER_CANCELED       3
      29             : #define PIP_PKCS12_NOSMARTCARD_EXPORT  4
      30             : #define PIP_PKCS12_RESTORE_FAILED      5
      31             : #define PIP_PKCS12_BACKUP_FAILED       6
      32             : #define PIP_PKCS12_NSS_ERROR           7
      33             : 
      34             : // constructor
      35           0 : nsPKCS12Blob::nsPKCS12Blob()
      36             :   : mCertArray(nullptr)
      37           0 :   , mTmpFile(nullptr)
      38             : {
      39           0 :   mUIContext = new PipUIContext();
      40           0 : }
      41             : 
      42             : // destructor
      43           0 : nsPKCS12Blob::~nsPKCS12Blob()
      44             : {
      45           0 :   nsNSSShutDownPreventionLock locker;
      46           0 :   if (isAlreadyShutDown()) {
      47           0 :     return;
      48             :   }
      49             : 
      50           0 :   shutdown(ShutdownCalledFrom::Object);
      51           0 : }
      52             : 
      53             : // nsPKCS12Blob::ImportFromFile
      54             : //
      55             : // Given a file handle, read a PKCS#12 blob from that file, decode it, and
      56             : // import the results into the internal database.
      57             : nsresult
      58           0 : nsPKCS12Blob::ImportFromFile(nsIFile *file)
      59             : {
      60           0 :   nsNSSShutDownPreventionLock locker;
      61           0 :   nsresult rv = NS_OK;
      62             : 
      63             :   RetryReason wantRetry;
      64             : 
      65           0 :   do {
      66           0 :     rv = ImportFromFileHelper(file, im_standard_prompt, wantRetry);
      67             : 
      68           0 :     if (NS_SUCCEEDED(rv) && wantRetry == rr_auto_retry_empty_password_flavors) {
      69           0 :       rv = ImportFromFileHelper(file, im_try_zero_length_secitem, wantRetry);
      70             :     }
      71             :   }
      72           0 :   while (NS_SUCCEEDED(rv) && (wantRetry != rr_do_not_retry));
      73             : 
      74           0 :   return rv;
      75             : }
      76             : 
      77             : nsresult
      78           0 : nsPKCS12Blob::ImportFromFileHelper(nsIFile *file,
      79             :                                    nsPKCS12Blob::ImportMode aImportMode,
      80             :                                    nsPKCS12Blob::RetryReason &aWantRetry)
      81             : {
      82           0 :   nsNSSShutDownPreventionLock locker;
      83           0 :   nsresult rv = NS_OK;
      84           0 :   SECStatus srv = SECSuccess;
      85           0 :   SEC_PKCS12DecoderContext *dcx = nullptr;
      86           0 :   SECItem unicodePw = { siBuffer, nullptr, 0  };
      87             : 
      88           0 :   aWantRetry = rr_do_not_retry;
      89             : 
      90           0 :   UniquePK11SlotInfo slot(PK11_GetInternalKeySlot());
      91           0 :   if (!slot) {
      92           0 :     srv = SECFailure;
      93           0 :     goto finish;
      94             :   }
      95             : 
      96           0 :   if (aImportMode == im_try_zero_length_secitem) {
      97           0 :     unicodePw.len = 0;
      98             :   } else {
      99             :     // get file password (unicode)
     100           0 :     rv = getPKCS12FilePassword(&unicodePw);
     101           0 :     if (NS_FAILED(rv)) goto finish;
     102           0 :     if (!unicodePw.data) {
     103           0 :       handleError(PIP_PKCS12_USER_CANCELED);
     104           0 :       return NS_OK;
     105             :     }
     106             :   }
     107             : 
     108             :   // initialize the decoder
     109           0 :   dcx = SEC_PKCS12DecoderStart(&unicodePw, slot.get(), nullptr, nullptr,
     110           0 :                                nullptr, nullptr, nullptr, nullptr);
     111           0 :   if (!dcx) {
     112           0 :     srv = SECFailure;
     113           0 :     goto finish;
     114             :   }
     115             :   // read input file and feed it to the decoder
     116           0 :   rv = inputToDecoder(dcx, file);
     117           0 :   if (NS_FAILED(rv)) {
     118           0 :     if (NS_ERROR_ABORT == rv) {
     119             :       // inputToDecoder indicated a NSS error
     120           0 :       srv = SECFailure;
     121             :     }
     122           0 :     goto finish;
     123             :   }
     124             :   // verify the blob
     125           0 :   srv = SEC_PKCS12DecoderVerify(dcx);
     126           0 :   if (srv) goto finish;
     127             :   // validate bags
     128           0 :   srv = SEC_PKCS12DecoderValidateBags(dcx, nickname_collision);
     129           0 :   if (srv) goto finish;
     130             :   // import cert and key
     131           0 :   srv = SEC_PKCS12DecoderImportBags(dcx);
     132           0 :   if (srv) goto finish;
     133             :   // Later - check to see if this should become default email cert
     134             : finish:
     135             :   // If srv != SECSuccess, NSS probably set a specific error code.
     136             :   // We should use that error code instead of inventing a new one
     137             :   // for every error possible.
     138           0 :   if (srv != SECSuccess) {
     139           0 :     if (SEC_ERROR_BAD_PASSWORD == PORT_GetError()) {
     140           0 :       if (unicodePw.len == sizeof(char16_t))
     141             :       {
     142             :         // no password chars available,
     143             :         // unicodeToItem allocated space for the trailing zero character only.
     144           0 :         aWantRetry = rr_auto_retry_empty_password_flavors;
     145             :       }
     146             :       else
     147             :       {
     148           0 :         aWantRetry = rr_bad_password;
     149           0 :         handleError(PIP_PKCS12_NSS_ERROR);
     150             :       }
     151             :     }
     152             :     else
     153             :     {
     154           0 :       handleError(PIP_PKCS12_NSS_ERROR);
     155             :     }
     156           0 :   } else if (NS_FAILED(rv)) {
     157           0 :     handleError(PIP_PKCS12_RESTORE_FAILED);
     158             :   }
     159             :   // finish the decoder
     160           0 :   if (dcx)
     161           0 :     SEC_PKCS12DecoderFinish(dcx);
     162           0 :   SECITEM_ZfreeItem(&unicodePw, false);
     163           0 :   return NS_OK;
     164             : }
     165             : 
     166             : static bool
     167           0 : isExtractable(SECKEYPrivateKey *privKey)
     168             : {
     169           0 :   ScopedAutoSECItem value;
     170             :   SECStatus rv = PK11_ReadRawAttribute(PK11_TypePrivKey, privKey,
     171           0 :                                        CKA_EXTRACTABLE, &value);
     172           0 :   if (rv != SECSuccess) {
     173           0 :     return false;
     174             :   }
     175             : 
     176           0 :   bool isExtractable = false;
     177           0 :   if ((value.len == 1) && value.data) {
     178           0 :     isExtractable = !!(*(CK_BBOOL*)value.data);
     179             :   }
     180           0 :   return isExtractable;
     181             : }
     182             : 
     183             : // nsPKCS12Blob::ExportToFile
     184             : //
     185             : // Having already loaded the certs, form them into a blob (loading the keys
     186             : // also), encode the blob, and stuff it into the file.
     187             : nsresult
     188           0 : nsPKCS12Blob::ExportToFile(nsIFile *file,
     189             :                            nsIX509Cert **certs, int numCerts)
     190             : {
     191           0 :   nsNSSShutDownPreventionLock locker;
     192             :   nsresult rv;
     193           0 :   SECStatus srv = SECSuccess;
     194           0 :   SEC_PKCS12ExportContext *ecx = nullptr;
     195           0 :   SEC_PKCS12SafeInfo *certSafe = nullptr, *keySafe = nullptr;
     196             :   SECItem unicodePw;
     197           0 :   nsAutoString filePath;
     198             :   int i;
     199           0 :   nsCOMPtr<nsIFile> localFileRef;
     200             :   // init slot
     201             : 
     202           0 :   bool InformedUserNoSmartcardBackup = false;
     203           0 :   int numCertsExported = 0;
     204             : 
     205             :   // get file password (unicode)
     206           0 :   unicodePw.data = nullptr;
     207           0 :   rv = newPKCS12FilePassword(&unicodePw);
     208           0 :   if (NS_FAILED(rv)) goto finish;
     209           0 :   if (!unicodePw.data) {
     210           0 :     handleError(PIP_PKCS12_USER_CANCELED);
     211           0 :     return NS_OK;
     212             :   }
     213             :   // what about slotToUse in psm 1.x ???
     214             :   // create export context
     215           0 :   ecx = SEC_PKCS12CreateExportContext(nullptr, nullptr, nullptr /*slot*/, nullptr);
     216           0 :   if (!ecx) {
     217           0 :     srv = SECFailure;
     218           0 :     goto finish;
     219             :   }
     220             :   // add password integrity
     221           0 :   srv = SEC_PKCS12AddPasswordIntegrity(ecx, &unicodePw, SEC_OID_SHA1);
     222           0 :   if (srv) goto finish;
     223           0 :   for (i=0; i<numCerts; i++) {
     224           0 :     nsNSSCertificate *cert = (nsNSSCertificate *)certs[i];
     225             :     // get it as a CERTCertificate XXX
     226           0 :     UniqueCERTCertificate nssCert(cert->GetCert());
     227           0 :     if (!nssCert) {
     228           0 :       rv = NS_ERROR_FAILURE;
     229           0 :       goto finish;
     230             :     }
     231             :     // We can only successfully export certs that are on
     232             :     // internal token.  Most, if not all, smart card vendors
     233             :     // won't let you extract the private key (in any way
     234             :     // shape or form) from the card.  So let's punt if
     235             :     // the cert is not in the internal db.
     236           0 :     if (nssCert->slot && !PK11_IsInternal(nssCert->slot)) {
     237             :       // we aren't the internal token, see if the key is extractable.
     238           0 :       SECKEYPrivateKey *privKey=PK11_FindKeyByDERCert(nssCert->slot,
     239           0 :                                                       nssCert.get(), this);
     240             : 
     241           0 :       if (privKey) {
     242           0 :         bool privKeyIsExtractable = isExtractable(privKey);
     243             : 
     244           0 :         SECKEY_DestroyPrivateKey(privKey);
     245             : 
     246           0 :         if (!privKeyIsExtractable) {
     247           0 :           if (!InformedUserNoSmartcardBackup) {
     248           0 :             InformedUserNoSmartcardBackup = true;
     249           0 :             handleError(PIP_PKCS12_NOSMARTCARD_EXPORT);
     250             :           }
     251           0 :           continue;
     252             :         }
     253             :       }
     254             :     }
     255             : 
     256             :     // XXX this is why, to verify the slot is the same
     257             :     // PK11_FindObjectForCert(nssCert, nullptr, slot);
     258             :     // create the cert and key safes
     259           0 :     keySafe = SEC_PKCS12CreateUnencryptedSafe(ecx);
     260           0 :     if (!SEC_PKCS12IsEncryptionAllowed() || PK11_IsFIPS()) {
     261           0 :       certSafe = keySafe;
     262             :     } else {
     263             :       certSafe = SEC_PKCS12CreatePasswordPrivSafe(ecx, &unicodePw,
     264           0 :                            SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC);
     265             :     }
     266           0 :     if (!certSafe || !keySafe) {
     267           0 :       rv = NS_ERROR_FAILURE;
     268           0 :       goto finish;
     269             :     }
     270             :     // add the cert and key to the blob
     271           0 :     srv = SEC_PKCS12AddCertAndKey(ecx, certSafe, nullptr, nssCert.get(),
     272             :                                   CERT_GetDefaultCertDB(), // XXX
     273             :                                   keySafe, nullptr, true, &unicodePw,
     274           0 :                       SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC);
     275           0 :     if (srv) goto finish;
     276             :     // cert was dup'ed, so release it
     277           0 :     ++numCertsExported;
     278             :   }
     279             : 
     280           0 :   if (!numCertsExported) goto finish;
     281             : 
     282             :   // prepare the instance to write to an export file
     283           0 :   this->mTmpFile = nullptr;
     284           0 :   file->GetPath(filePath);
     285             :   // Use the nsCOMPtr var localFileRef so that
     286             :   // the reference to the nsIFile we create gets released as soon as
     287             :   // we're out of scope, ie when this function exits.
     288           0 :   if (filePath.RFind(".p12", true, -1, 4) < 0) {
     289             :     // We're going to add the .p12 extension to the file name just like
     290             :     // Communicator used to.  We create a new nsIFile and initialize
     291             :     // it with the new patch.
     292           0 :     filePath.AppendLiteral(".p12");
     293           0 :     localFileRef = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
     294           0 :     if (NS_FAILED(rv)) goto finish;
     295           0 :     localFileRef->InitWithPath(filePath);
     296           0 :     file = localFileRef;
     297             :   }
     298           0 :   rv = file->OpenNSPRFileDesc(PR_RDWR|PR_CREATE_FILE|PR_TRUNCATE, 0664,
     299           0 :                               &mTmpFile);
     300           0 :   if (NS_FAILED(rv) || !this->mTmpFile) goto finish;
     301             :   // encode and write
     302           0 :   srv = SEC_PKCS12Encode(ecx, write_export_file, this);
     303           0 :   if (srv) goto finish;
     304             : finish:
     305           0 :   if (NS_FAILED(rv) || srv != SECSuccess) {
     306           0 :     handleError(PIP_PKCS12_BACKUP_FAILED);
     307             :   }
     308           0 :   if (ecx)
     309           0 :     SEC_PKCS12DestroyExportContext(ecx);
     310           0 :   if (this->mTmpFile) {
     311           0 :     PR_Close(this->mTmpFile);
     312           0 :     this->mTmpFile = nullptr;
     313             :   }
     314           0 :   SECITEM_ZfreeItem(&unicodePw, false);
     315           0 :   return rv;
     316             : }
     317             : 
     318             : ///////////////////////////////////////////////////////////////////////
     319             : //
     320             : //  private members
     321             : //
     322             : ///////////////////////////////////////////////////////////////////////
     323             : 
     324             : // unicodeToItem
     325             : //
     326             : // For the NSS PKCS#12 library, must convert PRUnichars (shorts) to
     327             : // a buffer of octets.  Must handle byte order correctly.
     328             : nsresult
     329           0 : nsPKCS12Blob::unicodeToItem(const nsString& uni, SECItem* item)
     330             : {
     331           0 :   uint32_t len = uni.Length() + 1; // +1 for the null terminator.
     332           0 :   if (!SECITEM_AllocItem(nullptr, item, sizeof(char16_t) * len)) {
     333           0 :     return NS_ERROR_OUT_OF_MEMORY;
     334             :   }
     335             : 
     336             :   // We have to use a cast here because on Windows, uni.get() returns
     337             :   // char16ptr_t instead of char16_t*.
     338           0 :   mozilla::NativeEndian::copyAndSwapToBigEndian(
     339           0 :     item->data,
     340           0 :     static_cast<const char16_t*>(uni.get()),
     341           0 :     len);
     342             : 
     343           0 :   return NS_OK;
     344             : }
     345             : 
     346             : // newPKCS12FilePassword
     347             : //
     348             : // Launch a dialog requesting the user for a new PKCS#12 file passowrd.
     349             : // Handle user canceled by returning null password (caller must catch).
     350             : nsresult
     351           0 : nsPKCS12Blob::newPKCS12FilePassword(SECItem *unicodePw)
     352             : {
     353           0 :   nsresult rv = NS_OK;
     354           0 :   nsAutoString password;
     355           0 :   nsCOMPtr<nsICertificateDialogs> certDialogs;
     356           0 :   rv = ::getNSSDialogs(getter_AddRefs(certDialogs),
     357             :                        NS_GET_IID(nsICertificateDialogs),
     358           0 :                        NS_CERTIFICATEDIALOGS_CONTRACTID);
     359           0 :   if (NS_FAILED(rv)) return rv;
     360             :   bool pressedOK;
     361           0 :   rv = certDialogs->SetPKCS12FilePassword(mUIContext, password, &pressedOK);
     362           0 :   if (NS_FAILED(rv) || !pressedOK) return rv;
     363           0 :   return unicodeToItem(password, unicodePw);
     364             : }
     365             : 
     366             : // getPKCS12FilePassword
     367             : //
     368             : // Launch a dialog requesting the user for the password to a PKCS#12 file.
     369             : // Handle user canceled by returning null password (caller must catch).
     370             : nsresult
     371           0 : nsPKCS12Blob::getPKCS12FilePassword(SECItem *unicodePw)
     372             : {
     373           0 :   nsresult rv = NS_OK;
     374           0 :   nsAutoString password;
     375           0 :   nsCOMPtr<nsICertificateDialogs> certDialogs;
     376           0 :   rv = ::getNSSDialogs(getter_AddRefs(certDialogs),
     377             :                        NS_GET_IID(nsICertificateDialogs),
     378           0 :                        NS_CERTIFICATEDIALOGS_CONTRACTID);
     379           0 :   if (NS_FAILED(rv)) return rv;
     380             :   bool pressedOK;
     381           0 :   rv = certDialogs->GetPKCS12FilePassword(mUIContext, password, &pressedOK);
     382           0 :   if (NS_FAILED(rv) || !pressedOK) return rv;
     383           0 :   return unicodeToItem(password, unicodePw);
     384             : }
     385             : 
     386             : // inputToDecoder
     387             : //
     388             : // Given a decoder, read bytes from file and input them to the decoder.
     389             : nsresult
     390           0 : nsPKCS12Blob::inputToDecoder(SEC_PKCS12DecoderContext *dcx, nsIFile *file)
     391             : {
     392           0 :   nsNSSShutDownPreventionLock locker;
     393             :   nsresult rv;
     394             :   SECStatus srv;
     395             :   uint32_t amount;
     396             :   char buf[PIP_PKCS12_BUFFER_SIZE];
     397             : 
     398           0 :   nsCOMPtr<nsIInputStream> fileStream;
     399           0 :   rv = NS_NewLocalFileInputStream(getter_AddRefs(fileStream), file);
     400             : 
     401           0 :   if (NS_FAILED(rv)) {
     402           0 :     return rv;
     403             :   }
     404             : 
     405             :   while (true) {
     406           0 :     rv = fileStream->Read(buf, PIP_PKCS12_BUFFER_SIZE, &amount);
     407           0 :     if (NS_FAILED(rv)) {
     408           0 :       return rv;
     409             :     }
     410             :     // feed the file data into the decoder
     411           0 :     srv = SEC_PKCS12DecoderUpdate(dcx,
     412             :                                   (unsigned char*) buf,
     413           0 :                                   amount);
     414           0 :     if (srv) {
     415             :       // don't allow the close call to overwrite our precious error code
     416           0 :       int pr_err = PORT_GetError();
     417           0 :       PORT_SetError(pr_err);
     418           0 :       return NS_ERROR_ABORT;
     419             :     }
     420           0 :     if (amount < PIP_PKCS12_BUFFER_SIZE)
     421           0 :       break;
     422           0 :   }
     423           0 :   return NS_OK;
     424             : }
     425             : 
     426             : // nickname_collision
     427             : // what to do when the nickname collides with one already in the db.
     428             : // TODO: not handled, throw a dialog allowing the nick to be changed?
     429             : SECItem *
     430           0 : nsPKCS12Blob::nickname_collision(SECItem *oldNick, PRBool *cancel, void *wincx)
     431             : {
     432           0 :   nsNSSShutDownPreventionLock locker;
     433           0 :   *cancel = false;
     434           0 :   int count = 1;
     435           0 :   nsCString nickname;
     436           0 :   nsAutoString nickFromProp;
     437           0 :   nsresult rv = GetPIPNSSBundleString("P12DefaultNickname", nickFromProp);
     438           0 :   if (NS_FAILED(rv)) {
     439           0 :     return nullptr;
     440             :   }
     441           0 :   NS_ConvertUTF16toUTF8 nickFromPropC(nickFromProp);
     442             :   // The user is trying to import a PKCS#12 file that doesn't have the
     443             :   // attribute we use to set the nickname.  So in order to reduce the
     444             :   // number of interactions we require with the user, we'll build a nickname
     445             :   // for the user.  The nickname isn't prominently displayed in the UI,
     446             :   // so it's OK if we generate one on our own here.
     447             :   //   XXX If the NSS API were smarter and actually passed a pointer to
     448             :   //       the CERTCertificate* we're importing we could actually just
     449             :   //       call default_nickname (which is what the issuance code path
     450             :   //       does) and come up with a reasonable nickname.  Alas, the NSS
     451             :   //       API limits our ability to produce a useful nickname without
     452             :   //       bugging the user.  :(
     453             :   while (1) {
     454             :     // If we've gotten this far, that means there isn't a certificate
     455             :     // in the database that has the same subject name as the cert we're
     456             :     // trying to import.  So we need to come up with a "nickname" to
     457             :     // satisfy the NSS requirement or fail in trying to import.
     458             :     // Basically we use a default nickname from a properties file and
     459             :     // see if a certificate exists with that nickname.  If there isn't, then
     460             :     // create update the count by one and append the string '#1' Or
     461             :     // whatever the count currently is, and look for a cert with
     462             :     // that nickname.  Keep updating the count until we find a nickname
     463             :     // without a corresponding cert.
     464             :     //  XXX If a user imports *many* certs without the 'friendly name'
     465             :     //      attribute, then this may take a long time.  :(
     466           0 :     nickname = nickFromPropC;
     467           0 :     if (count > 1) {
     468           0 :       nickname.AppendPrintf(" #%d", count);
     469             :     }
     470             :     UniqueCERTCertificate cert(CERT_FindCertByNickname(CERT_GetDefaultCertDB(),
     471           0 :                                                        nickname.get()));
     472           0 :     if (!cert) {
     473           0 :       break;
     474             :     }
     475           0 :     count++;
     476           0 :   }
     477           0 :   SECItem *newNick = new SECItem;
     478           0 :   if (!newNick)
     479           0 :     return nullptr;
     480             : 
     481           0 :   newNick->type = siAsciiString;
     482           0 :   newNick->data = (unsigned char*) strdup(nickname.get());
     483           0 :   newNick->len  = strlen((char*)newNick->data);
     484           0 :   return newNick;
     485             : }
     486             : 
     487             : // write_export_file
     488             : // write bytes to the exported PKCS#12 file
     489             : void
     490           0 : nsPKCS12Blob::write_export_file(void *arg, const char *buf, unsigned long len)
     491             : {
     492           0 :   nsPKCS12Blob *cx = (nsPKCS12Blob *)arg;
     493           0 :   PR_Write(cx->mTmpFile, buf, len);
     494           0 : }
     495             : 
     496             : // pip_ucs2_ascii_conversion_fn
     497             : // required to be set by NSS (to do PKCS#12), but since we've already got
     498             : // unicode make this a no-op.
     499             : PRBool
     500           0 : pip_ucs2_ascii_conversion_fn(PRBool toUnicode,
     501             :                              unsigned char *inBuf,
     502             :                              unsigned int inBufLen,
     503             :                              unsigned char *outBuf,
     504             :                              unsigned int maxOutBufLen,
     505             :                              unsigned int *outBufLen,
     506             :                              PRBool swapBytes)
     507             : {
     508             :   // do a no-op, since I've already got unicode.  Hah!
     509           0 :   *outBufLen = inBufLen;
     510           0 :   memcpy(outBuf, inBuf, inBufLen);
     511           0 :   return true;
     512             : }
     513             : 
     514             : void
     515           0 : nsPKCS12Blob::handleError(int myerr)
     516             : {
     517           0 :   MOZ_ASSERT(NS_IsMainThread());
     518           0 :   if (!NS_IsMainThread()) {
     519           0 :     return;
     520             :   }
     521             : 
     522           0 :   int prerr = PORT_GetError();
     523           0 :   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("PKCS12: NSS/NSPR error(%d)", prerr));
     524           0 :   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("PKCS12: I called(%d)", myerr));
     525             : 
     526           0 :   const char * msgID = nullptr;
     527             : 
     528           0 :   switch (myerr) {
     529             :   case PIP_PKCS12_USER_CANCELED:
     530           0 :     return;  /* Just ignore it for now */
     531           0 :   case PIP_PKCS12_NOSMARTCARD_EXPORT: msgID = "PKCS12InfoNoSmartcardBackup"; break;
     532           0 :   case PIP_PKCS12_RESTORE_FAILED:   msgID = "PKCS12UnknownErrRestore"; break;
     533           0 :   case PIP_PKCS12_BACKUP_FAILED:    msgID = "PKCS12UnknownErrBackup"; break;
     534             :   case PIP_PKCS12_NSS_ERROR:
     535           0 :     switch (prerr) {
     536             :     // The following errors have the potential to be "handled", by asking
     537             :     // the user (via a dialog) whether s/he wishes to continue
     538           0 :     case 0: break;
     539             :     case SEC_ERROR_PKCS12_CERT_COLLISION:
     540             :       /* pop a dialog saying the cert is already in the database */
     541             :       /* ask to keep going?  what happens if one collision but others ok? */
     542             :       // The following errors cannot be "handled", notify the user (via an alert)
     543             :       // that the operation failed.
     544           0 :     case SEC_ERROR_BAD_PASSWORD: msgID = "PK11BadPassword"; break;
     545             : 
     546             :     case SEC_ERROR_BAD_DER:
     547             :     case SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE:
     548             :     case SEC_ERROR_PKCS12_INVALID_MAC:
     549           0 :       msgID = "PKCS12DecodeErr";
     550           0 :       break;
     551             : 
     552           0 :     case SEC_ERROR_PKCS12_DUPLICATE_DATA: msgID = "PKCS12DupData"; break;
     553             :     }
     554           0 :     break;
     555             :   }
     556             : 
     557           0 :   if (!msgID)
     558           0 :     msgID = "PKCS12UnknownErr";
     559             : 
     560           0 :   nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
     561           0 :   if (!wwatch) {
     562           0 :     return;
     563             :   }
     564           0 :   nsCOMPtr<nsIPrompt> prompter;
     565           0 :   if (NS_FAILED(wwatch->GetNewPrompter(nullptr, getter_AddRefs(prompter)))) {
     566           0 :     return;
     567             :   }
     568           0 :   nsAutoString message;
     569           0 :   if (NS_FAILED(GetPIPNSSBundleString(msgID, message))) {
     570           0 :     return;
     571             :   }
     572             : 
     573           0 :   Unused << prompter->Alert(nullptr, message.get());
     574             : }

Generated by: LCOV version 1.13