LCOV - app.info - security/manager/ssl/src/nsCrypto.cpp

LCOV - code coverage report
| Current view: | directory - security/manager/ssl/src - nsCrypto.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 1315 | 0 | 0.0 %
| Date: | 2012-04-21 | Functions: | 112 | 0 | 0.0 %

           1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
           2                 :  *
           3                 :  * ***** BEGIN LICENSE BLOCK *****
           4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           5                 :  *
           6                 :  * The contents of this file are subject to the Mozilla Public License Version
           7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           8                 :  * the License. You may obtain a copy of the License at
           9                 :  * http://www.mozilla.org/MPL/
          10                 :  *
          11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          13                 :  * for the specific language governing rights and limitations under the
          14                 :  * License.
          15                 :  *
          16                 :  * The Original Code is mozilla.org code.
          17                 :  *
          18                 :  * The Initial Developer of the Original Code is
          19                 :  * Netscape Communications Corporation.
          20                 :  * Portions created by the Initial Developer are Copyright (C) 2001
          21                 :  * the Initial Developer. All Rights Reserved.
          22                 :  *
          23                 :  * Contributor(s):
          24                 :  *   Javier Delgadillo <javi@netscape.com>
          25                 :  *
          26                 :  * Alternatively, the contents of this file may be used under the terms of
          27                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
          28                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          30                 :  * of those above. If you wish to allow use of your version of this file only
          31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          32                 :  * use your version of this file under the terms of the MPL, indicate your
          33                 :  * decision by deleting the provisions above and replace them with the notice
          34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          35                 :  * the provisions above, a recipient may use your version of this file under
          36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          37                 :  *
          38                 :  * ***** END LICENSE BLOCK ***** */
          39                 : #include "nsNSSComponent.h"
          40                 : #include "nsCrypto.h"
          41                 : #include "nsKeygenHandler.h"
          42                 : #include "nsKeygenThread.h"
          43                 : #include "nsNSSCertificate.h"
          44                 : #include "nsNSSCertificateDB.h"
          45                 : #include "nsPKCS12Blob.h"
          46                 : #include "nsPK11TokenDB.h"
          47                 : #include "nsThreadUtils.h"
          48                 : #include "nsIServiceManager.h"
          49                 : #include "nsIMemory.h"
          50                 : #include "nsAutoPtr.h"
          51                 : #include "nsAlgorithm.h"
          52                 : #include "nsCRT.h"
          53                 : #include "prprf.h"
          54                 : #include "prmem.h"
          55                 : #include "nsDOMCID.h"
          56                 : #include "nsIDOMWindow.h"
          57                 : #include "nsIDOMClassInfo.h"
          58                 : #include "nsIDOMDocument.h"
          59                 : #include "nsIDocument.h"
          60                 : #include "nsIScriptObjectPrincipal.h"
          61                 : #include "nsIScriptContext.h"
          62                 : #include "nsIScriptGlobalObject.h"
          63                 : #include "nsDOMJSUtils.h"
          64                 : #include "nsIXPConnect.h"
          65                 : #include "nsIRunnable.h"
          66                 : #include "nsIWindowWatcher.h"
          67                 : #include "nsIPrompt.h"
          68                 : #include "nsIFilePicker.h"
          69                 : #include "nsJSPrincipals.h"
          70                 : #include "nsIPrincipal.h"
          71                 : #include "nsIScriptSecurityManager.h"
          72                 : #include "nsXPIDLString.h"
          73                 : #include "nsIGenKeypairInfoDlg.h"
          74                 : #include "nsIDOMCryptoDialogs.h"
          75                 : #include "nsIFormSigningDialog.h"
          76                 : #include "nsIJSContextStack.h"
          77                 : #include "jsapi.h"
          78                 : #include "jsdbgapi.h"
          79                 : #include <ctype.h>
          80                 : #include "nsReadableUtils.h"
          81                 : #include "pk11func.h"
          82                 : #include "keyhi.h"
          83                 : #include "cryptohi.h"
          84                 : #include "seccomon.h"
          85                 : #include "secerr.h"
          86                 : #include "sechash.h"
          87                 : extern "C" {
          88                 : #include "crmf.h"
          89                 : #include "pk11pqg.h"
          90                 : }
          91                 : #include "cmmf.h"
          92                 : #include "nssb64.h"
          93                 : #include "base64.h"
          94                 : #include "cert.h"
          95                 : #include "certdb.h"
          96                 : #include "secmod.h"
          97                 : #include "nsISaveAsCharset.h"
          98                 :
          99                 : #include "ssl.h" // For SSL_ClearSessionCache
         100                 :
         101                 : #include "nsNSSCleaner.h"
         102               0 : NSSCleanupAutoPtrClass(SECKEYPrivateKey, SECKEY_DestroyPrivateKey)
         103               0 : NSSCleanupAutoPtrClass(PK11SlotInfo, PK11_FreeSlot)
         104               0 : NSSCleanupAutoPtrClass(CERTCertNicknames, CERT_FreeNicknames)
         105               0 : NSSCleanupAutoPtrClass(PK11SymKey, PK11_FreeSymKey)
         106               0 : NSSCleanupAutoPtrClass_WithParam(PK11Context, PK11_DestroyContext, TrueParam, true)
         107               0 : NSSCleanupAutoPtrClass_WithParam(SECItem, SECITEM_FreeItem, TrueParam, true)
         108                 :
         109                 : #include "nsNSSShutDown.h"
         110                 : #include "nsNSSCertHelper.h"
         111                 :
         112                 : /*
         113                 :  * These are the most common error strings that are returned
         114                 :  * by the JavaScript methods in case of error.
         115                 :  */
         116                 :
         117                 : #define JS_ERROR       "error:"
         118                 : #define JS_ERROR_INTERNAL  JS_ERROR"internalError"
         119                 :
         120                 : #undef REPORT_INCORRECT_NUM_ARGS
         121                 :
         122                 : #define JS_OK_ADD_MOD                      3
         123                 : #define JS_OK_DEL_EXTERNAL_MOD             2
         124                 : #define JS_OK_DEL_INTERNAL_MOD             1
         125                 :
         126                 : #define JS_ERR_INTERNAL                   -1
         127                 : #define JS_ERR_USER_CANCEL_ACTION         -2
         128                 : #define JS_ERR_INCORRECT_NUM_OF_ARGUMENTS -3
         129                 : #define JS_ERR_DEL_MOD                    -4
         130                 : #define JS_ERR_ADD_MOD                    -5
         131                 : #define JS_ERR_BAD_MODULE_NAME            -6
         132                 : #define JS_ERR_BAD_DLL_NAME               -7
         133                 : #define JS_ERR_BAD_MECHANISM_FLAGS        -8
         134                 : #define JS_ERR_BAD_CIPHER_ENABLE_FLAGS    -9
         135                 : #define JS_ERR_ADD_DUPLICATE_MOD          -10
         136                 :
         137                 : /*
         138                 :  * This structure is used to store information for one key generation.
         139                 :  * The nsCrypto::GenerateCRMFRequest method parses the inputs and then
         140                 :  * stores one of these structures for every key generation that happens.
         141                 :  * The information stored in this structure is then used to set some
         142                 :  * values in the CRMF request.
         143                 :  */
         144                 : typedef enum {
         145                 :   rsaEnc, rsaDualUse, rsaSign, rsaNonrepudiation, rsaSignNonrepudiation,
         146                 :   ecEnc, ecDualUse, ecSign, ecNonrepudiation, ecSignNonrepudiation,
         147                 :   dhEx, dsaSignNonrepudiation, dsaSign, dsaNonrepudiation, invalidKeyGen
         148                 : } nsKeyGenType;
         149                 :
         150               0 : bool isECKeyGenType(nsKeyGenType kgt)
         151                 : {
         152               0 :   switch (kgt)
         153                 :   {
         154                 :     case ecEnc:
         155                 :     case ecDualUse:
         156                 :     case ecSign:
         157                 :     case ecNonrepudiation:
         158                 :     case ecSignNonrepudiation:
         159               0 :       return true;
         160                 :
         161                 :     default:
         162                 :       break;
         163                 :   }
         164                 :
         165               0 :   return false;
         166                 : }
         167                 :
         168                 : typedef struct nsKeyPairInfoStr {
         169                 :   SECKEYPublicKey  *pubKey;     /* The putlic key associated with gen'd
         170                 :                                    priv key. */
         171                 :   SECKEYPrivateKey *privKey;    /* The private key we generated */
         172                 :   nsKeyGenType      keyGenType; /* What type of key gen are we doing.*/
         173                 :
         174                 :   CERTCertificate *ecPopCert;
         175                 :                    /* null: use signing for pop
         176                 :                       other than null: a cert that defines EC keygen params
         177                 :                                        and will be used for dhMac PoP. */
         178                 :
         179                 :   SECKEYPublicKey  *ecPopPubKey;
         180                 :                    /* extracted public key from ecPopCert */
         181                 : } nsKeyPairInfo;
         182                 :
         183                 :
         184                 : //This class is just used to pass arguments
         185                 : //to the nsCryptoRunnable event.
         186                 : class nsCryptoRunArgs : public nsISupports {
         187                 : public:
         188                 :   nsCryptoRunArgs();
         189                 :   virtual ~nsCryptoRunArgs();
         190                 :   nsCOMPtr<nsISupports> m_kungFuDeathGrip;
         191                 :   JSContext *m_cx;
         192                 :   JSObject  *m_scope;
         193                 :   nsCOMPtr<nsIPrincipal> m_principals;
         194                 :   nsXPIDLCString m_jsCallback;
         195                 :   NS_DECL_ISUPPORTS
         196                 : };
         197                 :
         198                 : //This class is used to run the callback code
         199                 : //passed to crypto.generateCRMFRequest
         200                 : //We have to do that for backwards compatibility
         201                 : //reasons w/ PSM 1.x and Communciator 4.x
         202                 : class nsCryptoRunnable : public nsIRunnable {
         203                 : public:
         204                 :   nsCryptoRunnable(nsCryptoRunArgs *args);
         205                 :   virtual ~nsCryptoRunnable();
         206                 :
         207                 :   NS_IMETHOD Run ();
         208                 :   NS_DECL_ISUPPORTS
         209                 : private:
         210                 :   nsCryptoRunArgs *m_args;
         211                 : };
         212                 :
         213                 :
         214                 : //We're going to inherit the memory passed
         215                 : //into us.
         216                 : //This class backs up an array of certificates
         217                 : //as an event.
         218                 : class nsP12Runnable : public nsIRunnable {
         219                 : public:
         220                 :   nsP12Runnable(nsIX509Cert **certArr, PRInt32 numCerts, nsIPK11Token *token);
         221                 :   virtual ~nsP12Runnable();
         222                 :
         223                 :   NS_IMETHOD Run();
         224                 :   NS_DECL_ISUPPORTS
         225                 : private:
         226                 :   nsCOMPtr<nsIPK11Token> mToken;
         227                 :   nsIX509Cert **mCertArr;
         228                 :   PRInt32       mNumCerts;
         229                 : };
         230                 :
         231                 : // QueryInterface implementation for nsCrypto
         232               0 : NS_INTERFACE_MAP_BEGIN(nsCrypto)
         233               0 :   NS_INTERFACE_MAP_ENTRY(nsIDOMCrypto)
         234               0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
         235               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Crypto)
         236               0 : NS_INTERFACE_MAP_END
         237                 :
         238               0 : NS_IMPL_ADDREF(nsCrypto)
         239               0 : NS_IMPL_RELEASE(nsCrypto)
         240                 :
         241                 : // QueryInterface implementation for nsCRMFObject
         242               0 : NS_INTERFACE_MAP_BEGIN(nsCRMFObject)
         243               0 :   NS_INTERFACE_MAP_ENTRY(nsIDOMCRMFObject)
         244               0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
         245               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CRMFObject)
         246               0 : NS_INTERFACE_MAP_END
         247                 :
         248               0 : NS_IMPL_ADDREF(nsCRMFObject)
         249               0 : NS_IMPL_RELEASE(nsCRMFObject)
         250                 :
         251                 : // QueryInterface implementation for nsPkcs11
         252               0 : NS_INTERFACE_MAP_BEGIN(nsPkcs11)
         253               0 :   NS_INTERFACE_MAP_ENTRY(nsIPKCS11)
         254               0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
         255               0 : NS_INTERFACE_MAP_END
         256                 :
         257               0 : NS_IMPL_ADDREF(nsPkcs11)
         258               0 : NS_IMPL_RELEASE(nsPkcs11)
         259                 :
         260                 : // ISupports implementation for nsCryptoRunnable
         261               0 : NS_IMPL_ISUPPORTS1(nsCryptoRunnable, nsIRunnable)
         262                 :
         263                 : // ISupports implementation for nsP12Runnable
         264               0 : NS_IMPL_ISUPPORTS1(nsP12Runnable, nsIRunnable)
         265                 :
         266                 : // ISupports implementation for nsCryptoRunArgs
         267               0 : NS_IMPL_ISUPPORTS0(nsCryptoRunArgs)
         268                 :
         269                 : static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
         270                 :
         271               0 : nsCrypto::nsCrypto() :
         272               0 :   mEnableSmartCardEvents(false)
         273                 : {
         274               0 : }
         275                 :
         276               0 : nsCrypto::~nsCrypto()
         277                 : {
         278               0 : }
         279                 :
         280                 : NS_IMETHODIMP
         281               0 : nsCrypto::SetEnableSmartCardEvents(bool aEnable)
         282                 : {
         283               0 :   nsresult rv = NS_OK;
         284                 :
         285                 :   // this has the side effect of starting the nssComponent (and initializing
         286                 :   // NSS) even if it isn't already going. Starting the nssComponent is a
         287                 :   // prerequisite for getting smartCard events.
         288               0 :   if (aEnable) {
         289               0 :     nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
         290                 :   }
         291                 :
         292               0 :   if (NS_FAILED(rv)) {
         293               0 :     return rv;
         294                 :   }
         295                 :
         296               0 :   mEnableSmartCardEvents = aEnable;
         297               0 :   return NS_OK;
         298                 : }
         299                 :
         300                 : NS_IMETHODIMP
         301               0 : nsCrypto::GetEnableSmartCardEvents(bool *aEnable)
         302                 : {
         303               0 :   *aEnable = mEnableSmartCardEvents;
         304               0 :   return NS_OK;
         305                 : }
         306                 :
         307                 : //A quick function to let us know if the key we're trying to generate
         308                 : //can be escrowed.
         309                 : static bool
         310               0 : ns_can_escrow(nsKeyGenType keyGenType)
         311                 : {
         312                 :   /* For now, we only escrow rsa-encryption and ec-encryption keys. */
         313               0 :   return (bool)(keyGenType == rsaEnc || keyGenType == ecEnc);
         314                 : }
         315                 :
         316                 : //Retrieve crypto.version so that callers know what
         317                 : //version of PSM this is.
         318                 : NS_IMETHODIMP
         319               0 : nsCrypto::GetVersion(nsAString& aVersion)
         320                 : {
         321               0 :   aVersion.Assign(NS_LITERAL_STRING(PSM_VERSION_STRING).get());
         322               0 :   return NS_OK;
         323                 : }
         324                 :
         325                 : /*
         326                 :  * Given an nsKeyGenType, return the PKCS11 mechanism that will
         327                 :  * perform the correct key generation.
         328                 :  */
         329                 : static PRUint32
         330               0 : cryptojs_convert_to_mechanism(nsKeyGenType keyGenType)
         331                 : {
         332                 :   PRUint32 retMech;
         333                 :
         334               0 :   switch (keyGenType) {
         335                 :   case rsaEnc:
         336                 :   case rsaDualUse:
         337                 :   case rsaSign:
         338                 :   case rsaNonrepudiation:
         339                 :   case rsaSignNonrepudiation:
         340               0 :     retMech = CKM_RSA_PKCS_KEY_PAIR_GEN;
         341               0 :     break;
         342                 :   case ecEnc:
         343                 :   case ecDualUse:
         344                 :   case ecSign:
         345                 :   case ecNonrepudiation:
         346                 :   case ecSignNonrepudiation:
         347               0 :     retMech = CKM_EC_KEY_PAIR_GEN;
         348               0 :     break;
         349                 :   case dhEx:
         350               0 :     retMech = CKM_DH_PKCS_KEY_PAIR_GEN;
         351               0 :     break;
         352                 :   case dsaSign:
         353                 :   case dsaSignNonrepudiation:
         354                 :   case dsaNonrepudiation:
         355               0 :     retMech = CKM_DSA_KEY_PAIR_GEN;
         356               0 :     break;
         357                 :   default:
         358               0 :     retMech = CKM_INVALID_MECHANISM;
         359                 :   }
         360               0 :   return retMech;
         361                 : }
         362                 :
         363                 : /*
         364                 :  * This function converts a string read through JavaScript parameters
         365                 :  * and translates it to the internal enumeration representing the
         366                 :  * key gen type.
         367                 :  */
         368                 : static nsKeyGenType
         369               0 : cryptojs_interpret_key_gen_type(char *keyAlg)
         370                 : {
         371                 :   char *end;
         372               0 :   if (keyAlg == nsnull) {
         373               0 :     return invalidKeyGen;
         374                 :   }
         375                 :   /* First let's remove all leading and trailing white space */
         376               0 :   while (isspace(keyAlg[0])) keyAlg++;
         377               0 :   end = strchr(keyAlg, '\0');
         378               0 :   if (end == nsnull) {
         379               0 :     return invalidKeyGen;
         380                 :   }
         381               0 :   end--;
         382               0 :   while (isspace(*end)) end--;
         383               0 :   end[1] = '\0';
         384               0 :   if (strcmp(keyAlg, "rsa-ex") == 0) {
         385               0 :     return rsaEnc;
         386               0 :   } else if (strcmp(keyAlg, "rsa-dual-use") == 0) {
         387               0 :     return rsaDualUse;
         388               0 :   } else if (strcmp(keyAlg, "rsa-sign") == 0) {
         389               0 :     return rsaSign;
         390               0 :   } else if (strcmp(keyAlg, "rsa-sign-nonrepudiation") == 0) {
         391               0 :     return rsaSignNonrepudiation;
         392               0 :   } else if (strcmp(keyAlg, "rsa-nonrepudiation") == 0) {
         393               0 :     return rsaNonrepudiation;
         394               0 :   } else if (strcmp(keyAlg, "ec-ex") == 0) {
         395               0 :     return ecEnc;
         396               0 :   } else if (strcmp(keyAlg, "ec-dual-use") == 0) {
         397               0 :     return ecDualUse;
         398               0 :   } else if (strcmp(keyAlg, "ec-sign") == 0) {
         399               0 :     return ecSign;
         400               0 :   } else if (strcmp(keyAlg, "ec-sign-nonrepudiation") == 0) {
         401               0 :     return ecSignNonrepudiation;
         402               0 :   } else if (strcmp(keyAlg, "ec-nonrepudiation") == 0) {
         403               0 :     return ecNonrepudiation;
         404               0 :   } else if (strcmp(keyAlg, "dsa-sign-nonrepudiation") == 0) {
         405               0 :     return dsaSignNonrepudiation;
         406               0 :   } else if (strcmp(keyAlg, "dsa-sign") ==0 ){
         407               0 :     return dsaSign;
         408               0 :   } else if (strcmp(keyAlg, "dsa-nonrepudiation") == 0) {
         409               0 :     return dsaNonrepudiation;
         410               0 :   } else if (strcmp(keyAlg, "dh-ex") == 0) {
         411               0 :     return dhEx;
         412                 :   }
         413               0 :   return invalidKeyGen;
         414                 : }
         415                 :
         416                 : /*
         417                 :  * input: null terminated char* pointing to (the remainder of) an
         418                 :  * EC key param string.
         419                 :  *
         420                 :  * bool return value, false means "no more name=value pair found",
         421                 :  *                    true means "found, see out params"
         422                 :  *
         423                 :  * out param name: char * pointing to name (not zero terminated)
         424                 :  * out param name_len: length of found name
         425                 :  * out param value: char * pointing to value (not zero terminated)
         426                 :  * out param value_len: length of found value
         427                 :  * out param next_pair: to be used for a follow up call to this function
         428                 :  */
         429                 :
         430               0 : bool getNextNameValueFromECKeygenParamString(char *input,
         431                 :                                                char *&name,
         432                 :                                                int &name_len,
         433                 :                                                char *&value,
         434                 :                                                int &value_len,
         435                 :                                                char *&next_call)
         436                 : {
         437               0 :   if (!input || !*input)
         438               0 :     return false;
         439                 :
         440                 :   // we allow leading ; and leading space in front of each name value pair
         441                 :
         442               0 :   while (*input && *input == ';')
         443               0 :     ++input;
         444                 :
         445               0 :   while (*input && *input == ' ')
         446               0 :     ++input;
         447                 :
         448               0 :   name = input;
         449                 :
         450               0 :   while (*input && *input != '=')
         451               0 :     ++input;
         452                 :
         453               0 :   if (*input != '=')
         454               0 :     return false;
         455                 :
         456               0 :   name_len = input - name;
         457               0 :   ++input;
         458                 :
         459               0 :   value = input;
         460                 :
         461               0 :   while (*input && *input != ';')
         462               0 :     ++input;
         463                 :
         464               0 :   value_len = input - value;
         465               0 :   next_call = input;
         466                 :
         467               0 :   return true;
         468                 : }
         469                 :
         470                 : //Take the string passed into us via crypto.generateCRMFRequest
         471                 : //as the keygen type parameter and convert it to parameters
         472                 : //we can actually pass to the PKCS#11 layer.
         473                 : static void*
         474               0 : nsConvertToActualKeyGenParams(PRUint32 keyGenMech, char *params,
         475                 :                               PRUint32 paramLen, PRInt32 keySize,
         476                 :                               nsKeyPairInfo *keyPairInfo)
         477                 : {
         478               0 :   void *returnParams = nsnull;
         479                 :
         480                 :
         481               0 :   switch (keyGenMech) {
         482                 :   case CKM_RSA_PKCS_KEY_PAIR_GEN:
         483                 :   {
         484                 :     // For RSA, we don't support passing in key generation arguments from
         485                 :     // the JS code just yet.
         486               0 :     if (params)
         487               0 :       return nsnull;
         488                 :
         489                 :     PK11RSAGenParams *rsaParams;
         490                 :     rsaParams = static_cast<PK11RSAGenParams*>
         491               0 :                            (nsMemory::Alloc(sizeof(PK11RSAGenParams)));
         492                 :
         493               0 :     if (rsaParams == nsnull) {
         494               0 :       return nsnull;
         495                 :     }
         496                 :     /* I'm just taking the same parameters used in
         497                 :      * certdlgs.c:GenKey
         498                 :      */
         499               0 :     if (keySize > 0) {
         500               0 :       rsaParams->keySizeInBits = keySize;
         501                 :     } else {
         502               0 :       rsaParams->keySizeInBits = 1024;
         503                 :     }
         504               0 :     rsaParams->pe = DEFAULT_RSA_KEYGEN_PE;
         505               0 :     returnParams = rsaParams;
         506               0 :     break;
         507                 :   }
         508                 :   case CKM_EC_KEY_PAIR_GEN:
         509                 :   {
         510                 :     /*
         511                 :      * keygen params for generating EC keys must be composed of name=value pairs,
         512                 :      * multiple pairs allowed, separated using semicolon ;
         513                 :      *
         514                 :      * Either param "curve" or param "popcert" must be specified.
         515                 :      * curve=name-of-curve
         516                 :      * popcert=base64-encoded-cert
         517                 :      *
         518                 :      * When both params are specified, popcert will be used.
         519                 :      * If no popcert param is given, or if popcert can not be decoded,
         520                 :      * we will fall back to the curve param.
         521                 :      *
         522                 :      * Additional name=value pairs may be defined in the future.
         523                 :      *
         524                 :      * If param popcert is present and valid, the given certificate will be used
         525                 :      * to determine the key generation params. In addition the certificate
         526                 :      * will be used to produce a dhMac based Proof of Posession,
         527                 :      * using the cert's public key, subject and issuer names,
         528                 :      * as specified in RFC 2511 section 4.3 paragraph 2 and Appendix A.
         529                 :      *
         530                 :      * If neither param popcert nor param curve could be used,
         531                 :      * tse a curve based on the keysize param.
         532                 :      * NOTE: Here keysize is used only as an indication of
         533                 :      * High/Medium/Low strength; elliptic curve
         534                 :      * cryptography uses smaller keys than RSA to provide
         535                 :      * equivalent security.
         536                 :      */
         537                 :
         538               0 :     char *curve = nsnull;
         539                 :
         540                 :     {
         541                 :       // extract components of name=value list
         542                 :
         543               0 :       char *next_input = params;
         544               0 :       char *name = nsnull;
         545               0 :       char *value = nsnull;
         546               0 :       int name_len = 0;
         547               0 :       int value_len = 0;
         548                 :
         549               0 :       while (getNextNameValueFromECKeygenParamString(
         550                 :               next_input, name, name_len, value, value_len,
         551               0 :               next_input))
         552                 :       {
         553               0 :         if (PL_strncmp(name, "curve", NS_MIN(name_len, 5)) == 0)
         554                 :         {
         555               0 :           curve = PL_strndup(value, value_len);
         556                 :         }
         557               0 :         else if (PL_strncmp(name, "popcert", NS_MIN(name_len, 7)) == 0)
         558                 :         {
         559               0 :           char *certstr = PL_strndup(value, value_len);
         560               0 :           if (certstr) {
         561               0 :             keyPairInfo->ecPopCert = CERT_ConvertAndDecodeCertificate(certstr);
         562               0 :             PL_strfree(certstr);
         563                 :
         564               0 :             if (keyPairInfo->ecPopCert)
         565                 :             {
         566               0 :               keyPairInfo->ecPopPubKey = CERT_ExtractPublicKey(keyPairInfo->ecPopCert);
         567                 :             }
         568                 :           }
         569                 :         }
         570                 :       }
         571                 :     }
         572                 :
         573                 :     // first try to use the params of the provided CA cert
         574               0 :     if (keyPairInfo->ecPopPubKey)
         575                 :     {
         576               0 :       returnParams = SECITEM_DupItem(&keyPairInfo->ecPopPubKey->u.ec.DEREncodedParams);
         577                 :     }
         578                 :
         579                 :     // if we did not yet find good params, do we have a curve name?
         580               0 :     if (!returnParams && curve)
         581                 :     {
         582               0 :       returnParams = decode_ec_params(curve);
         583                 :     }
         584                 :
         585                 :     // if we did not yet find good params, do something based on keysize
         586               0 :     if (!returnParams)
         587                 :     {
         588               0 :       switch (keySize) {
         589                 :       case 512:
         590                 :       case 1024:
         591               0 :           returnParams = decode_ec_params("secp256r1");
         592               0 :           break;
         593                 :       case 2048:
         594                 :       default:
         595               0 :           returnParams = decode_ec_params("secp384r1");
         596               0 :           break;
         597                 :       }
         598                 :     }
         599                 :
         600               0 :     if (curve)
         601               0 :       PL_strfree(curve);
         602                 :
         603               0 :     break;
         604                 :   }
         605                 :   case CKM_DSA_KEY_PAIR_GEN:
         606                 :   {
         607                 :     // For DSA, we don't support passing in key generation arguments from
         608                 :     // the JS code just yet.
         609               0 :     if (params)
         610               0 :       return nsnull;
         611                 :
         612               0 :     PQGParams *pqgParams = nsnull;
         613               0 :     PQGVerify *vfy = nsnull;
         614                 :     SECStatus  rv;
         615                 :     int        index;
         616                 :
         617               0 :     index = PQG_PBITS_TO_INDEX(keySize);
         618               0 :     if (index == -1) {
         619               0 :       returnParams = nsnull;
         620               0 :       break;
         621                 :     }
         622               0 :     rv = PK11_PQG_ParamGen(0, &pqgParams, &vfy);
         623               0 :     if (vfy) {
         624               0 :       PK11_PQG_DestroyVerify(vfy);
         625                 :     }
         626               0 :     if (rv != SECSuccess) {
         627               0 :       if (pqgParams) {
         628               0 :         PK11_PQG_DestroyParams(pqgParams);
         629                 :       }
         630               0 :       return nsnull;
         631                 :     }
         632               0 :     returnParams = pqgParams;
         633               0 :     break;
         634                 :   }
         635                 :   default:
         636               0 :     returnParams = nsnull;
         637                 :   }
         638               0 :   return returnParams;
         639                 : }
         640                 :
         641                 : //We need to choose which PKCS11 slot we're going to generate
         642                 : //the key on.  Calls the default implementation provided by
         643                 : //nsKeygenHandler.cpp
         644                 : static PK11SlotInfo*
         645               0 : nsGetSlotForKeyGen(nsKeyGenType keyGenType, nsIInterfaceRequestor *ctx)
         646                 : {
         647               0 :   nsNSSShutDownPreventionLock locker;
         648               0 :   PRUint32 mechanism = cryptojs_convert_to_mechanism(keyGenType);
         649               0 :   PK11SlotInfo *slot = nsnull;
         650               0 :   nsresult rv = GetSlotWithMechanism(mechanism,ctx, &slot);
         651               0 :   if (NS_FAILED(rv)) {
         652               0 :     if (slot)
         653               0 :       PK11_FreeSlot(slot);
         654               0 :     slot = nsnull;
         655                 :   }
         656               0 :   return slot;
         657                 : }
         658                 :
         659                 : //Free the parameters that were passed into PK11_GenerateKeyPair
         660                 : //depending on the mechanism type used.
         661                 : static void
         662               0 : nsFreeKeyGenParams(CK_MECHANISM_TYPE keyGenMechanism, void *params)
         663                 : {
         664               0 :   switch (keyGenMechanism) {
         665                 :   case CKM_RSA_PKCS_KEY_PAIR_GEN:
         666               0 :     nsMemory::Free(params);
         667               0 :     break;
         668                 :   case CKM_EC_KEY_PAIR_GEN:
         669               0 :     SECITEM_FreeItem(reinterpret_cast<SECItem*>(params), true);
         670               0 :     break;
         671                 :   case CKM_DSA_KEY_PAIR_GEN:
         672               0 :     PK11_PQG_DestroyParams(static_cast<PQGParams*>(params));
         673               0 :     break;
         674                 :   }
         675               0 : }
         676                 :
         677                 : //Function that is used to generate a single key pair.
         678                 : //Once all the arguments have been parsed and processed, this
         679                 : //function gets called and takes care of actually generating
         680                 : //the key pair passing the appopriate parameters to the NSS
         681                 : //functions.
         682                 : static nsresult
         683               0 : cryptojs_generateOneKeyPair(JSContext *cx, nsKeyPairInfo *keyPairInfo,
         684                 :                             PRInt32 keySize, char *params,
         685                 :                             nsIInterfaceRequestor *uiCxt,
         686                 :                             PK11SlotInfo *slot, bool willEscrow)
         687                 :
         688                 : {
         689                 :   nsIGeneratingKeypairInfoDialogs * dialogs;
         690               0 :   nsKeygenThread *KeygenRunnable = 0;
         691               0 :   nsCOMPtr<nsIKeygenThread> runnable;
         692                 :
         693               0 :   PRUint32 mechanism = cryptojs_convert_to_mechanism(keyPairInfo->keyGenType);
         694                 :   void *keyGenParams = nsConvertToActualKeyGenParams(mechanism, params,
         695                 :                                                      (params) ? strlen(params):0,
         696               0 :                                                      keySize, keyPairInfo);
         697                 :
         698               0 :   if (!keyGenParams) {
         699               0 :     return NS_ERROR_INVALID_ARG;
         700                 :   }
         701                 :
         702                 :   // Make sure the token has password already set on it before trying
         703                 :   // to generate the key.
         704                 :
         705               0 :   nsresult rv = setPassword(slot, uiCxt);
         706               0 :   if (NS_FAILED(rv))
         707               0 :     return rv;
         708                 :
         709               0 :   if (PK11_Authenticate(slot, true, uiCxt) != SECSuccess)
         710               0 :     return NS_ERROR_FAILURE;
         711                 :
         712                 :
         713                 :   // Smart cards will not let you extract a private key once
         714                 :   // it is on the smart card.  If we've been told to escrow
         715                 :   // a private key that will ultimately wind up on a smart card,
         716                 :   // then we'll generate the private key on the internal slot
         717                 :   // as a temporary key, then move it to the destination slot.
         718                 :   // NOTE: We call PK11_GetInternalSlot instead of PK11_GetInternalKeySlot
         719                 :   //       so that the key has zero chance of being store in the
         720                 :   //       user's key3.db file.  Which the slot returned by
         721                 :   //       PK11_GetInternalKeySlot has access to and PK11_GetInternalSlot
         722                 :   //       does not.
         723               0 :   PK11SlotInfo *intSlot = nsnull;
         724               0 :   PK11SlotInfoCleaner siCleaner(intSlot);
         725                 :
         726               0 :   PK11SlotInfo *origSlot = nsnull;
         727                 :   bool isPerm;
         728                 :
         729               0 :   if (willEscrow && !PK11_IsInternal(slot)) {
         730               0 :     intSlot = PK11_GetInternalSlot();
         731               0 :     NS_ASSERTION(intSlot,"Couldn't get the internal slot");
         732               0 :     isPerm = false;
         733               0 :     origSlot = slot;
         734               0 :     slot = intSlot;
         735                 :   } else {
         736               0 :     isPerm = true;
         737                 :   }
         738                 :
         739                 :   rv = getNSSDialogs((void**)&dialogs,
         740                 :                      NS_GET_IID(nsIGeneratingKeypairInfoDialogs),
         741               0 :                      NS_GENERATINGKEYPAIRINFODIALOGS_CONTRACTID);
         742                 :
         743               0 :   if (NS_SUCCEEDED(rv)) {
         744               0 :     KeygenRunnable = new nsKeygenThread();
         745               0 :     if (KeygenRunnable) {
         746               0 :       NS_ADDREF(KeygenRunnable);
         747                 :     }
         748                 :   }
         749                 :
         750               0 :   if (NS_FAILED(rv) || !KeygenRunnable) {
         751               0 :     rv = NS_OK;
         752                 :     keyPairInfo->privKey = PK11_GenerateKeyPair(slot, mechanism, keyGenParams,
         753                 :                                                 &keyPairInfo->pubKey, isPerm,
         754               0 :                                                 isPerm, uiCxt);
         755                 :   } else {
         756               0 :     KeygenRunnable->SetParams( slot, mechanism, keyGenParams, isPerm, isPerm, uiCxt );
         757                 :
         758               0 :     runnable = do_QueryInterface(KeygenRunnable);
         759                 :
         760               0 :     if (runnable) {
         761                 :       {
         762               0 :         nsPSMUITracker tracker;
         763               0 :         if (tracker.isUIForbidden()) {
         764               0 :           rv = NS_ERROR_NOT_AVAILABLE;
         765                 :         }
         766                 :         else {
         767               0 :           rv = dialogs->DisplayGeneratingKeypairInfo(uiCxt, runnable);
         768                 :           // We call join on the thread,
         769                 :           // so we can be sure that no simultaneous access to the passed parameters will happen.
         770               0 :           KeygenRunnable->Join();
         771                 :         }
         772                 :       }
         773                 :
         774               0 :       NS_RELEASE(dialogs);
         775               0 :       if (NS_SUCCEEDED(rv)) {
         776               0 :         rv = KeygenRunnable->GetParams(&keyPairInfo->privKey, &keyPairInfo->pubKey);
         777                 :       }
         778                 :     }
         779                 :   }
         780                 :
         781               0 :   nsFreeKeyGenParams(mechanism, keyGenParams);
         782                 :
         783               0 :   if (KeygenRunnable) {
         784               0 :     NS_RELEASE(KeygenRunnable);
         785                 :   }
         786                 :
         787               0 :   if (!keyPairInfo->privKey || !keyPairInfo->pubKey) {
         788               0 :     return NS_ERROR_FAILURE;
         789                 :   }
         790                 :
         791                 :
         792                 :   //If we generated the key pair on the internal slot because the
         793                 :   // keys were going to be escrowed, move the keys over right now.
         794               0 :   if (willEscrow && intSlot) {
         795                 :     SECKEYPrivateKey *newPrivKey = PK11_LoadPrivKey(origSlot,
         796                 :                                                     keyPairInfo->privKey,
         797                 :                                                     keyPairInfo->pubKey,
         798               0 :                                                     true, true);
         799               0 :     SECKEYPrivateKeyCleaner pkCleaner(newPrivKey);
         800                 :
         801               0 :     if (!newPrivKey)
         802               0 :       return NS_ERROR_FAILURE;
         803                 :
         804                 :     // The private key is stored on the selected slot now, and the copy we
         805                 :     // ultimately use for escrowing when the time comes lives
         806                 :     // in the internal slot.  We will delete it from that slot
         807                 :     // after the requests are made.  This call only gives up
         808                 :     // our reference to the key object and does not actually
         809                 :     // physically remove it from the card itself.
         810                 :     // The actual delete calls are being made in the destructors
         811                 :     // of the cleaner helper instances.
         812                 :   }
         813                 :
         814               0 :   return NS_OK;
         815                 : }
         816                 :
         817                 : /*
         818                 :  * FUNCTION: cryptojs_ReadArgsAndGenerateKey
         819                 :  * -------------------------------------
         820                 :  * INPUTS:
         821                 :  *  cx
         822                 :  *    The JSContext associated with the execution of the corresponging
         823                 :  *    crypto.generateCRMFRequest call
         824                 :  *  argv
         825                 :  *    A pointer to an array of JavaScript parameters passed to the
         826                 :  *    method crypto.generateCRMFRequest.  The array should have the
         827                 :  *    3 arguments keySize, "keyParams", and "keyGenAlg" mentioned in
         828                 :  *    the definition of crypto.generateCRMFRequest at the following
         829                 :  *    document http://docs.iplanet.com/docs/manuals/psm/11/cmcjavascriptapi.html
         830                 :  *  keyGenType
         831                 :  *    A structure used to store the information about the newly created
         832                 :  *    key pair.
         833                 :  *  uiCxt
         834                 :  *    An interface requestor that would be used to get an nsIPrompt
         835                 :  *    if we need to ask the user for a password.
         836                 :  *  slotToUse
         837                 :  *    The PKCS11 slot to use for generating the key pair. If nsnull, then
         838                 :  *    this function should select a slot that can do the key generation
         839                 :  *    from the keytype associted with the keyPairInfo, and pass it back to
         840                 :  *    the caller so that subsequence key generations can use the same slot.
         841                 :  *  willEscrow
         842                 :  *    If true, then that means we will try to escrow the generated
         843                 :  *    private key when building the CRMF request.  If false, then
         844                 :  *    we will not try to escrow the private key.
         845                 :  *
         846                 :  * NOTES:
         847                 :  * This function takes care of reading a set of 3 parameters that define
         848                 :  * one key generation.  The argv pointer should be one that originates
         849                 :  * from the argv parameter passed in to the method nsCrypto::GenerateCRMFRequest.
         850                 :  * The function interprets the argument in the first index as an integer and
         851                 :  * passes that as the key size for the key generation-this parameter is
         852                 :  * mandatory.  The second parameter is read in as a string.  This value can
         853                 :  * be null in JavaScript world and everything will still work.  The third
         854                 :  * parameter is a mandatory string that indicates what kind of key to generate.
         855                 :  * There should always be 1-to-1 correspondence between the strings compared
         856                 :  * in the function cryptojs_interpret_key_gen_type and the strings listed in
         857                 :  * document at http://docs.iplanet.com/docs/manuals/psm/11/cmcjavascriptapi.html
         858                 :  * under the definition of the method generateCRMFRequest, for the parameter
         859                 :  * "keyGenAlgN".  After reading the parameters, the function then
         860                 :  * generates the key pairs passing the parameters parsed from the JavaScript i
         861                 :  * routine.
         862                 :  *
         863                 :  * RETURN:
         864                 :  * NS_OK if creating the Key was successful.  Any other return value
         865                 :  * indicates an error.
         866                 :  */
         867                 :
         868                 : static nsresult
         869               0 : cryptojs_ReadArgsAndGenerateKey(JSContext *cx,
         870                 :                                 jsval *argv,
         871                 :                                 nsKeyPairInfo *keyGenType,
         872                 :                                 nsIInterfaceRequestor *uiCxt,
         873                 :                                 PK11SlotInfo **slot, bool willEscrow)
         874                 : {
         875                 :   JSString  *jsString;
         876               0 :   JSAutoByteString params, keyGenAlg;
         877                 :   int    keySize;
         878                 :   nsresult  rv;
         879                 :
         880               0 :   if (!JSVAL_IS_INT(argv[0])) {
         881                 :     JS_ReportError(cx, "%s%s\n", JS_ERROR,
         882               0 :                    "passed in non-integer for key size");
         883               0 :     return NS_ERROR_FAILURE;
         884                 :   }
         885               0 :   keySize = JSVAL_TO_INT(argv[0]);
         886               0 :   if (!JSVAL_IS_NULL(argv[1])) {
         887               0 :     jsString = JS_ValueToString(cx,argv[1]);
         888               0 :     NS_ENSURE_TRUE(jsString, NS_ERROR_OUT_OF_MEMORY);
         889               0 :     argv[1] = STRING_TO_JSVAL(jsString);
         890               0 :     params.encode(cx, jsString);
         891               0 :     NS_ENSURE_TRUE(!!params, NS_ERROR_OUT_OF_MEMORY);
         892                 :   }
         893                 :
         894               0 :   if (JSVAL_IS_NULL(argv[2])) {
         895                 :     JS_ReportError(cx,"%s%s\n", JS_ERROR,
         896               0 :              "key generation type not specified");
         897               0 :     return NS_ERROR_FAILURE;
         898                 :   }
         899               0 :   jsString = JS_ValueToString(cx, argv[2]);
         900               0 :   NS_ENSURE_TRUE(jsString, NS_ERROR_OUT_OF_MEMORY);
         901               0 :   argv[2] = STRING_TO_JSVAL(jsString);
         902               0 :   keyGenAlg.encode(cx, jsString);
         903               0 :   NS_ENSURE_TRUE(!!keyGenAlg, NS_ERROR_OUT_OF_MEMORY);
         904               0 :   keyGenType->keyGenType = cryptojs_interpret_key_gen_type(keyGenAlg.ptr());
         905               0 :   if (keyGenType->keyGenType == invalidKeyGen) {
         906                 :     JS_ReportError(cx, "%s%s%s", JS_ERROR,
         907                 :                    "invalid key generation argument:",
         908               0 :                    keyGenAlg.ptr());
         909               0 :     goto loser;
         910                 :   }
         911               0 :   if (*slot == nsnull) {
         912               0 :     *slot = nsGetSlotForKeyGen(keyGenType->keyGenType, uiCxt);
         913               0 :     if (*slot == nsnull)
         914               0 :       goto loser;
         915                 :   }
         916                 :
         917                 :   rv = cryptojs_generateOneKeyPair(cx,keyGenType,keySize,params.ptr(),uiCxt,
         918               0 :                                    *slot,willEscrow);
         919                 :
         920               0 :   if (rv != NS_OK) {
         921                 :     JS_ReportError(cx,"%s%s%s", JS_ERROR,
         922                 :                    "could not generate the key for algorithm ",
         923               0 :                    keyGenAlg.ptr());
         924               0 :     goto loser;
         925                 :   }
         926               0 :   return NS_OK;
         927                 : loser:
         928               0 :   return NS_ERROR_FAILURE;
         929                 : }
         930                 :
         931                 : //Utility funciton to free up the memory used by nsKeyPairInfo
         932                 : //arrays.
         933                 : static void
         934               0 : nsFreeKeyPairInfo(nsKeyPairInfo *keyids, int numIDs)
         935                 : {
         936               0 :   NS_ASSERTION(keyids, "NULL pointer passed to nsFreeKeyPairInfo");
         937               0 :   if (!keyids)
         938               0 :     return;
         939                 :   int i;
         940               0 :   for (i=0; i<numIDs; i++) {
         941               0 :     if (keyids[i].pubKey)
         942               0 :       SECKEY_DestroyPublicKey(keyids[i].pubKey);
         943               0 :     if (keyids[i].privKey)
         944               0 :       SECKEY_DestroyPrivateKey(keyids[i].privKey);
         945               0 :     if (keyids[i].ecPopCert)
         946               0 :       CERT_DestroyCertificate(keyids[i].ecPopCert);
         947               0 :     if (keyids[i].ecPopPubKey)
         948               0 :       SECKEY_DestroyPublicKey(keyids[i].ecPopPubKey);
         949                 :   }
         950               0 :   delete []keyids;
         951                 : }
         952                 :
         953                 : //Utility funciton used to free the genertaed cert request messages
         954                 : static void
         955               0 : nsFreeCertReqMessages(CRMFCertReqMsg **certReqMsgs, PRInt32 numMessages)
         956                 : {
         957                 :   PRInt32 i;
         958               0 :   for (i=0; i<numMessages && certReqMsgs[i]; i++) {
         959               0 :     CRMF_DestroyCertReqMsg(certReqMsgs[i]);
         960                 :   }
         961               0 :   delete []certReqMsgs;
         962               0 : }
         963                 :
         964                 : //If the form called for escrowing the private key we just generated,
         965                 : //this function adds all the correct elements to the request.
         966                 : //That consists of adding CRMFEncryptedKey to the reques as part
         967                 : //of the CRMFPKIArchiveOptions Control.
         968                 : static nsresult
         969               0 : nsSetEscrowAuthority(CRMFCertRequest *certReq, nsKeyPairInfo *keyInfo,
         970                 :                      nsNSSCertificate *wrappingCert)
         971                 : {
         972               0 :   if (!wrappingCert ||
         973               0 :       CRMF_CertRequestIsControlPresent(certReq, crmfPKIArchiveOptionsControl)){
         974               0 :     return NS_ERROR_FAILURE;
         975                 :   }
         976               0 :   CERTCertificate *cert = wrappingCert->GetCert();
         977               0 :   if (!cert)
         978               0 :     return NS_ERROR_FAILURE;
         979                 :
         980                 :   CRMFEncryptedKey *encrKey =
         981               0 :       CRMF_CreateEncryptedKeyWithEncryptedValue(keyInfo->privKey, cert);
         982               0 :   CERT_DestroyCertificate(cert);
         983               0 :   if (!encrKey)
         984               0 :     return NS_ERROR_FAILURE;
         985                 :
         986                 :   CRMFPKIArchiveOptions *archOpt =
         987               0 :       CRMF_CreatePKIArchiveOptions(crmfEncryptedPrivateKey, encrKey);
         988               0 :   if (!archOpt) {
         989               0 :     CRMF_DestroyEncryptedKey(encrKey);
         990               0 :     return NS_ERROR_FAILURE;
         991                 :   }
         992               0 :   SECStatus srv = CRMF_CertRequestSetPKIArchiveOptions(certReq, archOpt);
         993               0 :   CRMF_DestroyEncryptedKey(encrKey);
         994               0 :   CRMF_DestroyPKIArchiveOptions(archOpt);
         995               0 :   if (srv != SECSuccess)
         996               0 :     return NS_ERROR_FAILURE;
         997                 :
         998               0 :   return NS_OK;
         999                 : }
        1000                 :
        1001                 : //Set the Distinguished Name (Subject Name) for the cert
        1002                 : //being requested.
        1003                 : static nsresult
        1004               0 : nsSetDNForRequest(CRMFCertRequest *certReq, char *reqDN)
        1005                 : {
        1006               0 :   if (!reqDN || CRMF_CertRequestIsFieldPresent(certReq, crmfSubject)) {
        1007               0 :     return NS_ERROR_FAILURE;
        1008                 :   }
        1009               0 :   CERTName *subjectName = CERT_AsciiToName(reqDN);
        1010               0 :   if (!subjectName) {
        1011               0 :     return NS_ERROR_FAILURE;
        1012                 :   }
        1013                 :   SECStatus srv = CRMF_CertRequestSetTemplateField(certReq, crmfSubject,
        1014                 :                                                    static_cast<void*>
        1015               0 :                                                               (subjectName));
        1016               0 :   CERT_DestroyName(subjectName);
        1017               0 :   return (srv == SECSuccess) ? NS_OK : NS_ERROR_FAILURE;
        1018                 : }
        1019                 :
        1020                 : //Set Registration Token Control on the request.
        1021                 : static nsresult
        1022               0 : nsSetRegToken(CRMFCertRequest *certReq, char *regToken)
        1023                 : {
        1024                 :   // this should never happen, but might as well add this.
        1025               0 :   NS_ASSERTION(certReq, "A bogus certReq passed to nsSetRegToken");
        1026               0 :   if (regToken){
        1027               0 :     if (CRMF_CertRequestIsControlPresent(certReq, crmfRegTokenControl))
        1028               0 :       return NS_ERROR_FAILURE;
        1029                 :
        1030                 :     SECItem src;
        1031               0 :     src.data = (unsigned char*)regToken;
        1032               0 :     src.len  = strlen(regToken);
        1033                 :     SECItem *derEncoded = SEC_ASN1EncodeItem(nsnull, nsnull, &src,
        1034               0 :                                         SEC_ASN1_GET(SEC_UTF8StringTemplate));
        1035                 :
        1036               0 :     if (!derEncoded)
        1037               0 :       return NS_ERROR_FAILURE;
        1038                 :
        1039               0 :     SECStatus srv = CRMF_CertRequestSetRegTokenControl(certReq, derEncoded);
        1040               0 :     SECITEM_FreeItem(derEncoded,true);
        1041               0 :     if (srv != SECSuccess)
        1042               0 :       return NS_ERROR_FAILURE;
        1043                 :   }
        1044               0 :   return NS_OK;
        1045                 : }
        1046                 :
        1047                 : //Set the Authenticator control on the cert reuest.  It's just
        1048                 : //a string that gets passed along.
        1049                 : static nsresult
        1050               0 : nsSetAuthenticator(CRMFCertRequest *certReq, char *authenticator)
        1051                 : {
        1052                 :   //This should never happen, but might as well check.
        1053               0 :   NS_ASSERTION(certReq, "Bogus certReq passed to nsSetAuthenticator");
        1054               0 :   if (authenticator) {
        1055               0 :     if (CRMF_CertRequestIsControlPresent(certReq, crmfAuthenticatorControl))
        1056               0 :       return NS_ERROR_FAILURE;
        1057                 :
        1058                 :     SECItem src;
        1059               0 :     src.data = (unsigned char*)authenticator;
        1060               0 :     src.len  = strlen(authenticator);
        1061                 :     SECItem *derEncoded = SEC_ASN1EncodeItem(nsnull, nsnull, &src,
        1062               0 :                                      SEC_ASN1_GET(SEC_UTF8StringTemplate));
        1063               0 :     if (!derEncoded)
        1064               0 :       return NS_ERROR_FAILURE;
        1065                 :
        1066                 :     SECStatus srv = CRMF_CertRequestSetAuthenticatorControl(certReq,
        1067               0 :                                                             derEncoded);
        1068               0 :     SECITEM_FreeItem(derEncoded, true);
        1069               0 :     if (srv != SECSuccess)
        1070               0 :       return NS_ERROR_FAILURE;
        1071                 :   }
        1072               0 :   return NS_OK;
        1073                 : }
        1074                 :
        1075                 : // ASN1 DER encoding rules say that when encoding a BIT string,
        1076                 : // the length in the header for the bit string is the number
        1077                 : // of "useful" bits in the BIT STRING.  So the function finds
        1078                 : // it and sets accordingly for the returned item.
        1079                 : static void
        1080               0 : nsPrepareBitStringForEncoding (SECItem *bitsmap, SECItem *value)
        1081                 : {
        1082                 :   unsigned char onebyte;
        1083               0 :   unsigned int i, len = 0;
        1084                 :
        1085                 :   /* to prevent warning on some platform at compile time */
        1086               0 :   onebyte = '\0';
        1087                 :   /* Get the position of the right-most turn-on bit */
        1088               0 :   for (i = 0; i < (value->len ) * 8; ++i) {
        1089               0 :     if (i % 8 == 0)
        1090               0 :       onebyte = value->data[i/8];
        1091               0 :     if (onebyte & 0x80)
        1092               0 :       len = i;
        1093               0 :     onebyte <<= 1;
        1094                 :   }
        1095                 :
        1096               0 :   bitsmap->data = value->data;
        1097                 :   /* Add one here since we work with base 1 */
        1098               0 :   bitsmap->len = len + 1;
        1099               0 : }
        1100                 :
        1101                 : //This next section defines all the functions that sets the
        1102                 : //keyUsageExtension for all the different types of key gens
        1103                 : //we handle.  The keyUsageExtension is just a bit flag extension
        1104                 : //that we set in wrapper functions that call straight into
        1105                 : //nsSetKeyUsageExtension.  There is one wrapper funciton for each
        1106                 : //keyGenType.  The correct function will eventually be called
        1107                 : //by going through a switch statement based on the nsKeyGenType
        1108                 : //in the nsKeyPairInfo struct.
        1109                 : static nsresult
        1110               0 : nsSetKeyUsageExtension(CRMFCertRequest *crmfReq,
        1111                 :                        unsigned char   keyUsage)
        1112                 : {
        1113               0 :   SECItem                 *encodedExt= nsnull;
        1114               0 :   SECItem                  keyUsageValue = { (SECItemType) 0, nsnull, 0 };
        1115               0 :   SECItem                  bitsmap = { (SECItemType) 0, nsnull, 0 };
        1116                 :   SECStatus                srv;
        1117               0 :   CRMFCertExtension       *ext = nsnull;
        1118                 :   CRMFCertExtCreationInfo  extAddParams;
        1119                 :   SEC_ASN1Template         bitStrTemplate = {SEC_ASN1_BIT_STRING, 0, nsnull,
        1120               0 :                                              sizeof(SECItem)};
        1121                 :
        1122               0 :   keyUsageValue.data = &keyUsage;
        1123               0 :   keyUsageValue.len  = 1;
        1124               0 :   nsPrepareBitStringForEncoding(&bitsmap, &keyUsageValue);
        1125                 :
        1126               0 :   encodedExt = SEC_ASN1EncodeItem(nsnull, nsnull, &bitsmap,&bitStrTemplate);
        1127               0 :   if (encodedExt == nsnull) {
        1128               0 :     goto loser;
        1129                 :   }
        1130               0 :   ext = CRMF_CreateCertExtension(SEC_OID_X509_KEY_USAGE, true, encodedExt);
        1131               0 :   if (ext == nsnull) {
        1132               0 :       goto loser;
        1133                 :   }
        1134               0 :   extAddParams.numExtensions = 1;
        1135               0 :   extAddParams.extensions = &ext;
        1136                 :   srv = CRMF_CertRequestSetTemplateField(crmfReq, crmfExtension,
        1137               0 :                                          &extAddParams);
        1138               0 :   if (srv != SECSuccess) {
        1139               0 :       goto loser;
        1140                 :   }
        1141               0 :   CRMF_DestroyCertExtension(ext);
        1142               0 :   SECITEM_FreeItem(encodedExt, true);
        1143               0 :   return NS_OK;
        1144                 :  loser:
        1145               0 :   if (ext) {
        1146               0 :     CRMF_DestroyCertExtension(ext);
        1147                 :   }
        1148               0 :   if (encodedExt) {
        1149               0 :       SECITEM_FreeItem(encodedExt, true);
        1150                 :   }
        1151               0 :   return NS_ERROR_FAILURE;
        1152                 : }
        1153                 :
        1154                 : static nsresult
        1155               0 : nsSetRSADualUse(CRMFCertRequest *crmfReq)
        1156                 : {
        1157                 :   unsigned char keyUsage =   KU_DIGITAL_SIGNATURE
        1158                 :                            | KU_NON_REPUDIATION
        1159               0 :                            | KU_KEY_ENCIPHERMENT;
        1160                 :
        1161               0 :   return nsSetKeyUsageExtension(crmfReq, keyUsage);
        1162                 : }
        1163                 :
        1164                 : static nsresult
        1165               0 : nsSetRSAKeyEx(CRMFCertRequest *crmfReq)
        1166                 : {
        1167               0 :   unsigned char keyUsage = KU_KEY_ENCIPHERMENT;
        1168                 :
        1169               0 :   return nsSetKeyUsageExtension(crmfReq, keyUsage);
        1170                 : }
        1171                 :
        1172                 : static nsresult
        1173               0 : nsSetRSASign(CRMFCertRequest *crmfReq)
        1174                 : {
        1175               0 :   unsigned char keyUsage = KU_DIGITAL_SIGNATURE;
        1176                 :
        1177                 :
        1178               0 :   return nsSetKeyUsageExtension(crmfReq, keyUsage);
        1179                 : }
        1180                 :
        1181                 : static nsresult
        1182               0 : nsSetRSANonRepudiation(CRMFCertRequest *crmfReq)
        1183                 : {
        1184               0 :   unsigned char keyUsage = KU_NON_REPUDIATION;
        1185                 :
        1186               0 :   return nsSetKeyUsageExtension(crmfReq, keyUsage);
        1187                 : }
        1188                 :
        1189                 : static nsresult
        1190               0 : nsSetRSASignNonRepudiation(CRMFCertRequest *crmfReq)
        1191                 : {
        1192                 :   unsigned char keyUsage = KU_DIGITAL_SIGNATURE |
        1193               0 :                            KU_NON_REPUDIATION;
        1194                 :
        1195               0 :   return nsSetKeyUsageExtension(crmfReq, keyUsage);
        1196                 : }
        1197                 :
        1198                 : static nsresult
        1199               0 : nsSetECDualUse(CRMFCertRequest *crmfReq)
        1200                 : {
        1201                 :   unsigned char keyUsage =   KU_DIGITAL_SIGNATURE
        1202                 :                            | KU_NON_REPUDIATION
        1203               0 :                            | KU_KEY_AGREEMENT;
        1204                 :
        1205               0 :   return nsSetKeyUsageExtension(crmfReq, keyUsage);
        1206                 : }
        1207                 :
        1208                 : static nsresult
        1209               0 : nsSetECKeyEx(CRMFCertRequest *crmfReq)
        1210                 : {
        1211               0 :   unsigned char keyUsage = KU_KEY_AGREEMENT;
        1212                 :
        1213               0 :   return nsSetKeyUsageExtension(crmfReq, keyUsage);
        1214                 : }
        1215                 :
        1216                 : static nsresult
        1217               0 : nsSetECSign(CRMFCertRequest *crmfReq)
        1218                 : {
        1219               0 :   unsigned char keyUsage = KU_DIGITAL_SIGNATURE;
        1220                 :
        1221                 :
        1222               0 :   return nsSetKeyUsageExtension(crmfReq, keyUsage);
        1223                 : }
        1224                 :
        1225                 : static nsresult
        1226               0 : nsSetECNonRepudiation(CRMFCertRequest *crmfReq)
        1227                 : {
        1228               0 :   unsigned char keyUsage = KU_NON_REPUDIATION;
        1229                 :
        1230               0 :   return nsSetKeyUsageExtension(crmfReq, keyUsage);
        1231                 : }
        1232                 :
        1233                 : static nsresult
        1234               0 : nsSetECSignNonRepudiation(CRMFCertRequest *crmfReq)
        1235                 : {
        1236                 :   unsigned char keyUsage = KU_DIGITAL_SIGNATURE |
        1237               0 :                            KU_NON_REPUDIATION;
        1238                 :
        1239               0 :   return nsSetKeyUsageExtension(crmfReq, keyUsage);
        1240                 : }
        1241                 :
        1242                 : static nsresult
        1243               0 : nsSetDH(CRMFCertRequest *crmfReq)
        1244                 : {
        1245               0 :   unsigned char keyUsage = KU_KEY_AGREEMENT;
        1246                 :
        1247               0 :   return nsSetKeyUsageExtension(crmfReq, keyUsage);
        1248                 : }
        1249                 :
        1250                 : static nsresult
        1251               0 : nsSetDSASign(CRMFCertRequest *crmfReq)
        1252                 : {
        1253               0 :   unsigned char keyUsage = KU_DIGITAL_SIGNATURE;
        1254                 :
        1255               0 :   return nsSetKeyUsageExtension(crmfReq, keyUsage);
        1256                 : }
        1257                 :
        1258                 : static nsresult
        1259               0 : nsSetDSANonRepudiation(CRMFCertRequest *crmfReq)
        1260                 : {
        1261               0 :   unsigned char keyUsage = KU_NON_REPUDIATION;
        1262                 :
        1263               0 :   return nsSetKeyUsageExtension(crmfReq, keyUsage);
        1264                 : }
        1265                 :
        1266                 : static nsresult
        1267               0 : nsSetDSASignNonRepudiation(CRMFCertRequest *crmfReq)
        1268                 : {
        1269                 :   unsigned char keyUsage = KU_DIGITAL_SIGNATURE |
        1270               0 :                            KU_NON_REPUDIATION;
        1271                 :
        1272               0 :   return nsSetKeyUsageExtension(crmfReq, keyUsage);
        1273                 : }
        1274                 :
        1275                 : static nsresult
        1276               0 : nsSetKeyUsageExtension(CRMFCertRequest *crmfReq, nsKeyGenType keyGenType)
        1277                 : {
        1278                 :   nsresult rv;
        1279                 :
        1280               0 :   switch (keyGenType) {
        1281                 :   case rsaDualUse:
        1282               0 :     rv = nsSetRSADualUse(crmfReq);
        1283               0 :     break;
        1284                 :   case rsaEnc:
        1285               0 :     rv = nsSetRSAKeyEx(crmfReq);
        1286               0 :     break;
        1287                 :   case rsaSign:
        1288               0 :     rv = nsSetRSASign(crmfReq);
        1289               0 :     break;
        1290                 :   case rsaNonrepudiation:
        1291               0 :     rv = nsSetRSANonRepudiation(crmfReq);
        1292               0 :     break;
        1293                 :   case rsaSignNonrepudiation:
        1294               0 :     rv = nsSetRSASignNonRepudiation(crmfReq);
        1295               0 :     break;
        1296                 :   case ecDualUse:
        1297               0 :     rv = nsSetECDualUse(crmfReq);
        1298               0 :     break;
        1299                 :   case ecEnc:
        1300               0 :     rv = nsSetECKeyEx(crmfReq);
        1301               0 :     break;
        1302                 :   case ecSign:
        1303               0 :     rv = nsSetECSign(crmfReq);
        1304               0 :     break;
        1305                 :   case ecNonrepudiation:
        1306               0 :     rv = nsSetECNonRepudiation(crmfReq);
        1307               0 :     break;
        1308                 :   case ecSignNonrepudiation:
        1309               0 :     rv = nsSetECSignNonRepudiation(crmfReq);
        1310               0 :     break;
        1311                 :   case dhEx:
        1312               0 :     rv = nsSetDH(crmfReq);
        1313               0 :     break;
        1314                 :   case dsaSign:
        1315               0 :     rv = nsSetDSASign(crmfReq);
        1316               0 :     break;
        1317                 :   case dsaNonrepudiation:
        1318               0 :     rv = nsSetDSANonRepudiation(crmfReq);
        1319               0 :     break;
        1320                 :   case dsaSignNonrepudiation:
        1321               0 :     rv = nsSetDSASignNonRepudiation(crmfReq);
        1322               0 :     break;
        1323                 :   default:
        1324               0 :     rv = NS_ERROR_FAILURE;
        1325               0 :     break;
        1326                 :   }
        1327               0 :   return rv;
        1328                 : }
        1329                 :
        1330                 : //Create a single CRMFCertRequest with all of the necessary parts
        1331                 : //already installed.  The request returned by this function will
        1332                 : //have all the parts necessary and can just be added to a
        1333                 : //Certificate Request Message.
        1334                 : static CRMFCertRequest*
        1335               0 : nsCreateSingleCertReq(nsKeyPairInfo *keyInfo, char *reqDN, char *regToken,
        1336                 :                       char *authenticator, nsNSSCertificate *wrappingCert)
        1337                 : {
        1338                 :   PRUint32 reqID;
        1339                 :   nsresult rv;
        1340                 :
        1341                 :   //The draft says the ID of the request should be a random
        1342                 :   //number.  We don't have a way of tracking this number
        1343                 :   //to compare when the reply actually comes back,though.
        1344               0 :   PK11_GenerateRandom((unsigned char*)&reqID, sizeof(reqID));
        1345               0 :   CRMFCertRequest *certReq = CRMF_CreateCertRequest(reqID);
        1346               0 :   if (!certReq)
        1347               0 :     return nsnull;
        1348                 :
        1349               0 :   long version = SEC_CERTIFICATE_VERSION_3;
        1350                 :   SECStatus srv;
        1351               0 :   CERTSubjectPublicKeyInfo *spki = nsnull;
        1352               0 :   srv = CRMF_CertRequestSetTemplateField(certReq, crmfVersion, &version);
        1353               0 :   if (srv != SECSuccess)
        1354               0 :     goto loser;
        1355                 :
        1356               0 :   spki = SECKEY_CreateSubjectPublicKeyInfo(keyInfo->pubKey);
        1357               0 :   if (!spki)
        1358               0 :     goto loser;
        1359                 :
        1360               0 :   srv = CRMF_CertRequestSetTemplateField(certReq, crmfPublicKey, spki);
        1361               0 :   SECKEY_DestroySubjectPublicKeyInfo(spki);
        1362               0 :   if (srv != SECSuccess)
        1363               0 :     goto loser;
        1364                 :
        1365               0 :   if (wrappingCert && ns_can_escrow(keyInfo->keyGenType)) {
        1366               0 :     rv = nsSetEscrowAuthority(certReq, keyInfo, wrappingCert);
        1367               0 :     if (NS_FAILED(rv))
        1368               0 :       goto loser;
        1369                 :   }
        1370               0 :   rv = nsSetDNForRequest(certReq, reqDN);
        1371               0 :   if (NS_FAILED(rv))
        1372               0 :     goto loser;
        1373                 :
        1374               0 :   rv = nsSetRegToken(certReq, regToken);
        1375               0 :   if (NS_FAILED(rv))
        1376               0 :     goto loser;
        1377                 :
        1378               0 :   rv = nsSetAuthenticator(certReq, authenticator);
        1379               0 :   if (NS_FAILED(rv))
        1380               0 :     goto loser;
        1381                 :
        1382               0 :  rv = nsSetKeyUsageExtension(certReq, keyInfo->keyGenType);
        1383               0 :   if (NS_FAILED(rv))
        1384               0 :     goto loser;
        1385                 :
        1386               0 :   return certReq;
        1387                 : loser:
        1388               0 :   if (certReq) {
        1389               0 :     CRMF_DestroyCertRequest(certReq);
        1390                 :   }
        1391               0 :   return nsnull;
        1392                 : }
        1393                 :
        1394                 : /*
        1395                 :  * This function will set the Proof Of Possession (POP) for a request
        1396                 :  * associated with a key pair intended to do Key Encipherment.  Currently
        1397                 :  * this means encryption only keys.
        1398                 :  */
        1399                 : static nsresult
        1400               0 : nsSetKeyEnciphermentPOP(CRMFCertReqMsg *certReqMsg, bool isEscrowed)
        1401                 : {
        1402                 :   SECItem       bitString;
        1403                 :   unsigned char der[2];
        1404                 :   SECStatus     srv;
        1405                 :
        1406               0 :   if (isEscrowed) {
        1407                 :     /* For proof of possession on escrowed keys, we use the
        1408                 :      * this Message option of POPOPrivKey and include a zero
        1409                 :      * length bit string in the POP field.  This is OK because the encrypted
        1410                 :      * private key already exists as part of the PKIArchiveOptions
        1411                 :      * Control and that for all intents and purposes proves that
        1412                 :      * we do own the private key.
        1413                 :      */
        1414               0 :     der[0] = 0x03; /*We've got a bit string          */
        1415               0 :     der[1] = 0x00; /*We've got a 0 length bit string */
        1416               0 :     bitString.data = der;
        1417               0 :     bitString.len  = 2;
        1418                 :     srv = CRMF_CertReqMsgSetKeyEnciphermentPOP(certReqMsg, crmfThisMessage,
        1419               0 :                                               crmfNoSubseqMess, &bitString);
        1420                 :   } else {
        1421                 :     /* If the encryption key is not being escrowed, then we set the
        1422                 :      * Proof Of Possession to be a Challenge Response mechanism.
        1423                 :      */
        1424                 :     srv = CRMF_CertReqMsgSetKeyEnciphermentPOP(certReqMsg,
        1425                 :                                               crmfSubsequentMessage,
        1426               0 :                                               crmfChallengeResp, nsnull);
        1427                 :   }
        1428               0 :   return (srv == SECSuccess) ? NS_OK : NS_ERROR_FAILURE;
        1429                 : }
        1430                 :
        1431                 : static void PR_CALLBACK
        1432                 : nsCRMFEncoderItemCount(void *arg, const char *buf, unsigned long len);
        1433                 :
        1434                 : static void PR_CALLBACK
        1435                 : nsCRMFEncoderItemStore(void *arg, const char *buf, unsigned long len);
        1436                 :
        1437                 : static nsresult
        1438               0 : nsSet_EC_DHMAC_ProofOfPossession(CRMFCertReqMsg *certReqMsg,
        1439                 :                                  nsKeyPairInfo  *keyInfo,
        1440                 :                                  CRMFCertRequest *certReq)
        1441                 : {
        1442                 :   // RFC 2511 Appendix A section 2 a) defines,
        1443                 :   // the "text" input for HMAC shall be the DER encoded version of
        1444                 :   // of the single cert request.
        1445                 :   // We'll produce that encoding and destroy it afterwards,
        1446                 :   // because when sending the complete package to the CA,
        1447                 :   // we'll use a different encoding, one that includes POP and
        1448                 :   // allows multiple requests to be sent in one step.
        1449                 :
        1450               0 :   unsigned long der_request_len = 0;
        1451               0 :   SECItem *der_request = NULL;
        1452               0 :   SECItemCleanerTrueParam der_request_cleaner(der_request);
        1453                 :
        1454               0 :   if (SECSuccess != CRMF_EncodeCertRequest(certReq,
        1455                 :                                            nsCRMFEncoderItemCount,
        1456               0 :                                            &der_request_len))
        1457               0 :     return NS_ERROR_FAILURE;
        1458                 :
        1459               0 :   der_request = SECITEM_AllocItem(nsnull, nsnull, der_request_len);
        1460               0 :   if (!der_request)
        1461               0 :     return NS_ERROR_FAILURE;
        1462                 :
        1463                 :   // set len in returned SECItem back to zero, because it will
        1464                 :   // be used as the destination offset inside the
        1465                 :   // nsCRMFEncoderItemStore callback.
        1466                 :
        1467               0 :   der_request->len = 0;
        1468                 :
        1469               0 :   if (SECSuccess != CRMF_EncodeCertRequest(certReq,
        1470                 :                                            nsCRMFEncoderItemStore,
        1471               0 :                                            der_request))
        1472               0 :     return NS_ERROR_FAILURE;
        1473                 :
        1474                 :   // RFC 2511 Appendix A section 2 c):
        1475                 :   // "A key K is derived from the shared secret Kec and the subject and
        1476                 :   //  issuer names in the CA's certificate as follows:
        1477                 :   //  K = SHA1(DER-encoded-subjectName | Kec | DER-encoded-issuerName)"
        1478                 :
        1479               0 :   PK11SymKey *shared_secret = NULL;
        1480               0 :   PK11SymKeyCleaner shared_secret_cleaner(shared_secret);
        1481                 :
        1482               0 :   PK11SymKey *subject_and_secret = NULL;
        1483               0 :   PK11SymKeyCleaner subject_and_secret_cleaner(subject_and_secret);
        1484                 :
        1485               0 :   PK11SymKey *subject_and_secret_and_issuer = NULL;
        1486               0 :   PK11SymKeyCleaner subject_and_secret_and_issuer_cleaner(subject_and_secret_and_issuer);
        1487                 :
        1488               0 :   PK11SymKey *sha1_of_subject_and_secret_and_issuer = NULL;
        1489               0 :   PK11SymKeyCleaner sha1_of_subject_and_secret_and_issuer_cleaner(sha1_of_subject_and_secret_and_issuer);
        1490                 :
        1491                 :   shared_secret =
        1492                 :     PK11_PubDeriveWithKDF(keyInfo->privKey, // SECKEYPrivateKey *privKey
        1493                 :                           keyInfo->ecPopPubKey,  // SECKEYPublicKey *pubKey
        1494                 :                           false, // bool isSender
        1495                 :                           NULL, // SECItem *randomA
        1496                 :                           NULL, // SECItem *randomB
        1497                 :                           CKM_ECDH1_DERIVE, // CK_MECHANISM_TYPE derive
        1498                 :                           CKM_CONCATENATE_DATA_AND_BASE, // CK_MECHANISM_TYPE target
        1499                 :                           CKA_DERIVE, // CK_ATTRIBUTE_TYPE operation
        1500                 :                           0, // int keySize
        1501                 :                           CKD_NULL, // CK_ULONG kdf
        1502                 :                           NULL, // SECItem *sharedData
        1503               0 :                           NULL); // void *wincx
        1504                 :
        1505               0 :   if (!shared_secret)
        1506               0 :     return NS_ERROR_FAILURE;
        1507                 :
        1508                 :   CK_KEY_DERIVATION_STRING_DATA concat_data_base;
        1509               0 :   concat_data_base.pData = keyInfo->ecPopCert->derSubject.data;
        1510               0 :   concat_data_base.ulLen = keyInfo->ecPopCert->derSubject.len;
        1511                 :   SECItem concat_data_base_item;
        1512               0 :   concat_data_base_item.data = (unsigned char*)&concat_data_base;
        1513               0 :   concat_data_base_item.len = sizeof(CK_KEY_DERIVATION_STRING_DATA);
        1514                 :
        1515                 :   subject_and_secret =
        1516                 :     PK11_Derive(shared_secret, // PK11SymKey *baseKey
        1517                 :                 CKM_CONCATENATE_DATA_AND_BASE, // CK_MECHANISM_TYPE mechanism
        1518                 :                 &concat_data_base_item, // SECItem *param
        1519                 :                 CKM_CONCATENATE_BASE_AND_DATA, // CK_MECHANISM_TYPE target
        1520                 :                 CKA_DERIVE, // CK_ATTRIBUTE_TYPE operation
        1521               0 :                 0); // int keySize
        1522                 :
        1523               0 :   if (!subject_and_secret)
        1524               0 :     return NS_ERROR_FAILURE;
        1525                 :
        1526                 :   CK_KEY_DERIVATION_STRING_DATA concat_base_data;
        1527               0 :   concat_base_data.pData = keyInfo->ecPopCert->derSubject.data;
        1528               0 :   concat_base_data.ulLen = keyInfo->ecPopCert->derSubject.len;
        1529                 :   SECItem concat_base_data_item;
        1530               0 :   concat_base_data_item.data = (unsigned char*)&concat_base_data;
        1531               0 :   concat_base_data_item.len = sizeof(CK_KEY_DERIVATION_STRING_DATA);
        1532                 :
        1533                 :   subject_and_secret_and_issuer =
        1534                 :     PK11_Derive(subject_and_secret, // PK11SymKey *baseKey
        1535                 :                 CKM_CONCATENATE_BASE_AND_DATA, // CK_MECHANISM_TYPE mechanism
        1536                 :                 &concat_base_data_item, // SECItem *param
        1537                 :                 CKM_SHA1_KEY_DERIVATION, // CK_MECHANISM_TYPE target
        1538                 :                 CKA_DERIVE, // CK_ATTRIBUTE_TYPE operation
        1539               0 :                 0); // int keySize
        1540                 :
        1541               0 :   if (!subject_and_secret_and_issuer)
        1542               0 :     return NS_ERROR_FAILURE;
        1543                 :
        1544                 :   sha1_of_subject_and_secret_and_issuer =
        1545                 :     PK11_Derive(subject_and_secret_and_issuer, // PK11SymKey *baseKey
        1546                 :                 CKM_SHA1_KEY_DERIVATION, // CK_MECHANISM_TYPE mechanism
        1547                 :                 NULL, // SECItem *param
        1548                 :                 CKM_SHA_1_HMAC, // CK_MECHANISM_TYPE target
        1549                 :                 CKA_SIGN, // CK_ATTRIBUTE_TYPE operation
        1550               0 :                 0); // int keySize
        1551                 :
        1552               0 :   if (!sha1_of_subject_and_secret_and_issuer)
        1553               0 :     return NS_ERROR_FAILURE;
        1554                 :
        1555               0 :   PK11Context *context = NULL;
        1556               0 :   PK11ContextCleanerTrueParam context_cleaner(context);
        1557                 :
        1558                 :   SECItem ignore;
        1559               0 :   ignore.data = 0;
        1560               0 :   ignore.len = 0;
        1561                 :
        1562                 :   context =
        1563                 :     PK11_CreateContextBySymKey(CKM_SHA_1_HMAC, // CK_MECHANISM_TYPE type
        1564                 :                                CKA_SIGN, // CK_ATTRIBUTE_TYPE operation
        1565                 :                                sha1_of_subject_and_secret_and_issuer, // PK11SymKey *symKey
        1566               0 :                                &ignore); // SECItem *param
        1567                 :
        1568               0 :   if (!context)
        1569               0 :     return NS_ERROR_FAILURE;
        1570                 :
        1571               0 :   if (SECSuccess != PK11_DigestBegin(context))
        1572               0 :     return NS_ERROR_FAILURE;
        1573                 :
        1574               0 :   if (SECSuccess !=
        1575               0 :       PK11_DigestOp(context, der_request->data, der_request->len))
        1576               0 :     return NS_ERROR_FAILURE;
        1577                 :
        1578               0 :   SECItem *result_hmac_sha1_item = NULL;
        1579               0 :   SECItemCleanerTrueParam result_hmac_sha1_item_cleaner(result_hmac_sha1_item);
        1580                 :
        1581               0 :   result_hmac_sha1_item = SECITEM_AllocItem(nsnull, nsnull, SHA1_LENGTH);
        1582               0 :   if (!result_hmac_sha1_item)
        1583               0 :     return NS_ERROR_FAILURE;
        1584                 :
        1585               0 :   if (SECSuccess !=
        1586                 :       PK11_DigestFinal(context,
        1587                 :                        result_hmac_sha1_item->data,
        1588                 :                        &result_hmac_sha1_item->len,
        1589               0 :                        SHA1_LENGTH))
        1590               0 :     return NS_ERROR_FAILURE;
        1591                 :
        1592               0 :   if (SECSuccess !=
        1593                 :       CRMF_CertReqMsgSetKeyAgreementPOP(certReqMsg, crmfDHMAC,
        1594               0 :                                         crmfNoSubseqMess, result_hmac_sha1_item))
        1595               0 :     return NS_ERROR_FAILURE;
        1596                 :
        1597               0 :   return NS_OK;
        1598                 : }
        1599                 :
        1600                 : static nsresult
        1601               0 : nsSetProofOfPossession(CRMFCertReqMsg *certReqMsg,
        1602                 :                        nsKeyPairInfo  *keyInfo,
        1603                 :                        CRMFCertRequest *certReq)
        1604                 : {
        1605                 :   // Depending on the type of cert request we'll try
        1606                 :   // POP mechanisms in different order,
        1607                 :   // and add the result to the cert request message.
        1608                 :   //
        1609                 :   // For any signing or dual use cert,
        1610                 :   //   try signing first,
        1611                 :   //   fall back to DHMAC if we can
        1612                 :   //     (EC cert requests that provide keygen param "popcert"),
        1613                 :   //   otherwise fail.
        1614                 :   //
        1615                 :   // For encryption only certs that get escrowed, this is sufficient.
        1616                 :   //
        1617                 :   // For encryption only certs, that are not being escrowed,
        1618                 :   //   try DHMAC if we can
        1619                 :   //     (EC cert requests that provide keygen param "popcert"),
        1620                 :   //   otherwise we'll indicate challenge response should be used.
        1621                 :
        1622               0 :   bool isEncryptionOnlyCertRequest = false;
        1623               0 :   bool escrowEncryptionOnlyCert = false;
        1624                 :
        1625               0 :   switch (keyInfo->keyGenType)
        1626                 :   {
        1627                 :     case rsaEnc:
        1628                 :     case ecEnc:
        1629               0 :       isEncryptionOnlyCertRequest = true;
        1630               0 :       break;
        1631                 :
        1632                 :     case rsaSign:
        1633                 :     case rsaDualUse:
        1634                 :     case rsaNonrepudiation:
        1635                 :     case rsaSignNonrepudiation:
        1636                 :     case ecSign:
        1637                 :     case ecDualUse:
        1638                 :     case ecNonrepudiation:
        1639                 :     case ecSignNonrepudiation:
        1640                 :     case dsaSign:
        1641                 :     case dsaNonrepudiation:
        1642                 :     case dsaSignNonrepudiation:
        1643               0 :       break;
        1644                 :
        1645                 :     case dhEx:
        1646                 :     /* This case may be supported in the future, but for now, we just fall
        1647                 :       * though to the default case and return an error for diffie-hellman keys.
        1648                 :     */
        1649                 :     default:
        1650               0 :       return NS_ERROR_FAILURE;
        1651                 :   };
        1652                 :
        1653               0 :   if (isEncryptionOnlyCertRequest)
        1654                 :   {
        1655                 :     escrowEncryptionOnlyCert =
        1656               0 :       CRMF_CertRequestIsControlPresent(certReq,crmfPKIArchiveOptionsControl);
        1657                 :   }
        1658                 :
        1659               0 :   bool gotDHMACParameters = false;
        1660                 :
        1661               0 :   if (isECKeyGenType(keyInfo->keyGenType) &&
        1662                 :       keyInfo->ecPopCert &&
        1663                 :       keyInfo->ecPopPubKey)
        1664                 :   {
        1665               0 :     gotDHMACParameters = true;
        1666                 :   }
        1667                 :
        1668               0 :   if (isEncryptionOnlyCertRequest)
        1669                 :   {
        1670               0 :     if (escrowEncryptionOnlyCert)
        1671               0 :       return nsSetKeyEnciphermentPOP(certReqMsg, true); // escrowed
        1672                 :
        1673               0 :     if (gotDHMACParameters)
        1674               0 :       return nsSet_EC_DHMAC_ProofOfPossession(certReqMsg, keyInfo, certReq);
        1675                 :
        1676               0 :     return nsSetKeyEnciphermentPOP(certReqMsg, false); // not escrowed
        1677                 :   }
        1678                 :
        1679                 :   // !isEncryptionOnlyCertRequest
        1680                 :
        1681                 :   SECStatus srv = CRMF_CertReqMsgSetSignaturePOP(certReqMsg,
        1682                 :                                                  keyInfo->privKey,
        1683                 :                                                  keyInfo->pubKey, nsnull,
        1684               0 :                                                  nsnull, nsnull);
        1685                 :
        1686               0 :   if (srv == SECSuccess)
        1687               0 :     return NS_OK;
        1688                 :
        1689               0 :   if (!gotDHMACParameters)
        1690               0 :     return NS_ERROR_FAILURE;
        1691                 :
        1692               0 :   return nsSet_EC_DHMAC_ProofOfPossession(certReqMsg, keyInfo, certReq);
        1693                 : }
        1694                 :
        1695                 : static void PR_CALLBACK
        1696               0 : nsCRMFEncoderItemCount(void *arg, const char *buf, unsigned long len)
        1697                 : {
        1698               0 :   unsigned long *count = (unsigned long *)arg;
        1699               0 :   *count += len;
        1700               0 : }
        1701                 :
        1702                 : static void PR_CALLBACK
        1703               0 : nsCRMFEncoderItemStore(void *arg, const char *buf, unsigned long len)
        1704                 : {
        1705               0 :   SECItem *dest = (SECItem *)arg;
        1706               0 :   memcpy(dest->data + dest->len, buf, len);
        1707               0 :   dest->len += len;
        1708               0 : }
        1709                 :
        1710                 : static SECItem*
        1711               0 : nsEncodeCertReqMessages(CRMFCertReqMsg **certReqMsgs)
        1712                 : {
        1713               0 :   unsigned long len = 0;
        1714               0 :   if (CRMF_EncodeCertReqMessages(certReqMsgs, nsCRMFEncoderItemCount, &len)
        1715                 :       != SECSuccess) {
        1716               0 :     return nsnull;
        1717                 :   }
        1718               0 :   SECItem *dest = (SECItem *)PORT_Alloc(sizeof(SECItem));
        1719               0 :   if (dest == nsnull) {
        1720               0 :     return nsnull;
        1721                 :   }
        1722               0 :   dest->type = siBuffer;
        1723               0 :   dest->data = (unsigned char *)PORT_Alloc(len);
        1724               0 :   if (dest->data == nsnull) {
        1725               0 :     PORT_Free(dest);
        1726               0 :     return nsnull;
        1727                 :   }
        1728               0 :   dest->len = 0;
        1729                 :
        1730               0 :   if (CRMF_EncodeCertReqMessages(certReqMsgs, nsCRMFEncoderItemStore, dest)
        1731                 :       != SECSuccess) {
        1732               0 :     SECITEM_FreeItem(dest, true);
        1733               0 :     return nsnull;
        1734                 :   }
        1735               0 :   return dest;
        1736                 : }
        1737                 :
        1738                 : //Create a Base64 encoded CRMFCertReqMsg that can be sent to a CA
        1739                 : //requesting one or more certificates to be issued.  This function
        1740                 : //creates a single cert request per key pair and then appends it to
        1741                 : //a message that is ultimately sent off to a CA.
        1742                 : static char*
        1743               0 : nsCreateReqFromKeyPairs(nsKeyPairInfo *keyids, PRInt32 numRequests,
        1744                 :                         char *reqDN, char *regToken, char *authenticator,
        1745                 :                         nsNSSCertificate *wrappingCert)
        1746                 : {
        1747                 :   // We'use the goto notation for clean-up purposes in this function
        1748                 :   // that calls the C API of NSS.
        1749                 :   PRInt32 i;
        1750                 :   // The ASN1 encoder in NSS wants the last entry in the array to be
        1751                 :   // NULL so that it knows when the last element is.
        1752               0 :   CRMFCertReqMsg **certReqMsgs = new CRMFCertReqMsg*[numRequests+1];
        1753                 :   CRMFCertRequest *certReq;
        1754               0 :   if (!certReqMsgs)
        1755               0 :     return nsnull;
        1756               0 :   memset(certReqMsgs, 0, sizeof(CRMFCertReqMsg*)*(1+numRequests));
        1757                 :   SECStatus srv;
        1758                 :   nsresult rv;
        1759                 :   SECItem *encodedReq;
        1760                 :   char *retString;
        1761               0 :   for (i=0; i<numRequests; i++) {
        1762                 :     certReq = nsCreateSingleCertReq(&keyids[i], reqDN, regToken, authenticator,
        1763               0 :                                     wrappingCert);
        1764               0 :     if (!certReq)
        1765               0 :       goto loser;
        1766                 :
        1767               0 :     certReqMsgs[i] = CRMF_CreateCertReqMsg();
        1768               0 :     if (!certReqMsgs[i])
        1769               0 :       goto loser;
        1770               0 :     srv = CRMF_CertReqMsgSetCertRequest(certReqMsgs[i], certReq);
        1771               0 :     if (srv != SECSuccess)
        1772               0 :       goto loser;
        1773                 :
        1774               0 :     rv = nsSetProofOfPossession(certReqMsgs[i], &keyids[i], certReq);
        1775               0 :     if (NS_FAILED(rv))
        1776               0 :       goto loser;
        1777               0 :     CRMF_DestroyCertRequest(certReq);
        1778                 :   }
        1779               0 :   encodedReq = nsEncodeCertReqMessages(certReqMsgs);
        1780               0 :   nsFreeCertReqMessages(certReqMsgs, numRequests);
        1781                 :
        1782               0 :   retString = NSSBase64_EncodeItem (nsnull, nsnull, 0, encodedReq);
        1783               0 :   SECITEM_FreeItem(encodedReq, true);
        1784               0 :   return retString;
        1785                 : loser:
        1786               0 :   nsFreeCertReqMessages(certReqMsgs,numRequests);
        1787               0 :   return nsnull;;
        1788                 : }
        1789                 :
        1790                 : static nsISupports *
        1791               0 : GetISupportsFromContext(JSContext *cx)
        1792                 : {
        1793               0 :     if (JS_GetOptions(cx) & JSOPTION_PRIVATE_IS_NSISUPPORTS)
        1794               0 :         return static_cast<nsISupports *>(JS_GetContextPrivate(cx));
        1795                 :
        1796               0 :     return nsnull;
        1797                 : }
        1798                 :
        1799                 : //The top level method which is a member of nsIDOMCrypto
        1800                 : //for generate a base64 encoded CRMF request.
        1801                 : NS_IMETHODIMP
        1802               0 : nsCrypto::GenerateCRMFRequest(nsIDOMCRMFObject** aReturn)
        1803                 : {
        1804               0 :   nsNSSShutDownPreventionLock locker;
        1805               0 :   *aReturn = nsnull;
        1806                 :   nsresult nrv;
        1807               0 :   nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &nrv));
        1808               0 :   NS_ENSURE_SUCCESS(nrv, nrv);
        1809                 :
        1810               0 :   nsAXPCNativeCallContext *ncc = nsnull;
        1811                 :
        1812               0 :   nrv = xpc->GetCurrentNativeCallContext(&ncc);
        1813               0 :   NS_ENSURE_SUCCESS(nrv, nrv);
        1814                 :
        1815               0 :   if (!ncc)
        1816               0 :     return NS_ERROR_NOT_AVAILABLE;
        1817                 :
        1818                 :   PRUint32 argc;
        1819                 :
        1820               0 :   ncc->GetArgc(&argc);
        1821                 :
        1822               0 :   jsval *argv = nsnull;
        1823                 :
        1824               0 :   nrv = ncc->GetArgvPtr(&argv);
        1825               0 :   NS_ENSURE_SUCCESS(nrv, nrv);
        1826                 :
        1827                 :   JSContext *cx;
        1828                 :
        1829               0 :   nrv = ncc->GetJSContext(&cx);
        1830               0 :   NS_ENSURE_SUCCESS(nrv, nrv);
        1831                 :
        1832               0 :   JSObject* script_obj = nsnull;
        1833               0 :   nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
        1834                 :
        1835               0 :   JSAutoRequest ar(cx);
        1836                 :
        1837                 :   /*
        1838                 :    * Get all of the parameters.
        1839                 :    */
        1840               0 :   if (argc < 5 || ((argc-5) % 3) != 0) {
        1841                 :     JS_ReportError(cx, "%s", "%s%s\n", JS_ERROR,
        1842               0 :                   "incorrect number of parameters");
        1843               0 :     return NS_ERROR_FAILURE;
        1844                 :   }
        1845                 :
        1846               0 :   if (JSVAL_IS_NULL(argv[0])) {
        1847               0 :     JS_ReportError(cx, "%s%s\n", JS_ERROR, "no DN specified");
        1848               0 :     return NS_ERROR_FAILURE;
        1849                 :   }
        1850                 :
        1851               0 :   JSString *jsString = JS_ValueToString(cx,argv[0]);
        1852               0 :   NS_ENSURE_TRUE(jsString, NS_ERROR_OUT_OF_MEMORY);
        1853               0 :   argv[0] = STRING_TO_JSVAL(jsString);
        1854               0 :   JSAutoByteString reqDN(cx,jsString);
        1855               0 :   NS_ENSURE_TRUE(!!reqDN, NS_ERROR_OUT_OF_MEMORY);
        1856                 :
        1857               0 :   JSAutoByteString regToken;
        1858               0 :   if (!JSVAL_IS_NULL(argv[1])) {
        1859               0 :     jsString = JS_ValueToString(cx, argv[1]);
        1860               0 :     NS_ENSURE_TRUE(jsString, NS_ERROR_OUT_OF_MEMORY);
        1861               0 :     argv[1] = STRING_TO_JSVAL(jsString);
        1862               0 :     regToken.encode(cx, jsString);
        1863               0 :     NS_ENSURE_TRUE(!!regToken, NS_ERROR_OUT_OF_MEMORY);
        1864                 :   }
        1865               0 :   JSAutoByteString authenticator;
        1866               0 :   if (!JSVAL_IS_NULL(argv[2])) {
        1867               0 :     jsString      = JS_ValueToString(cx, argv[2]);
        1868               0 :     NS_ENSURE_TRUE(jsString, NS_ERROR_OUT_OF_MEMORY);
        1869               0 :     argv[2] = STRING_TO_JSVAL(jsString);
        1870               0 :     authenticator.encode(cx, jsString);
        1871               0 :     NS_ENSURE_TRUE(!!authenticator, NS_ERROR_OUT_OF_MEMORY);
        1872                 :   }
        1873               0 :   JSAutoByteString eaCert;
        1874               0 :   if (!JSVAL_IS_NULL(argv[3])) {
        1875               0 :     jsString     = JS_ValueToString(cx, argv[3]);
        1876               0 :     NS_ENSURE_TRUE(jsString, NS_ERROR_OUT_OF_MEMORY);
        1877               0 :     argv[3] = STRING_TO_JSVAL(jsString);
        1878               0 :     eaCert.encode(cx, jsString);
        1879               0 :     NS_ENSURE_TRUE(!!eaCert, NS_ERROR_OUT_OF_MEMORY);
        1880                 :   }
        1881               0 :   if (JSVAL_IS_NULL(argv[4])) {
        1882                 :     JS_ReportError(cx, "%s%s\n", JS_ERROR, "no completion "
        1883               0 :                    "function specified");
        1884               0 :     return NS_ERROR_FAILURE;
        1885                 :   }
        1886               0 :   jsString = JS_ValueToString(cx, argv[4]);
        1887               0 :   NS_ENSURE_TRUE(jsString, NS_ERROR_OUT_OF_MEMORY);
        1888               0 :   argv[4] = STRING_TO_JSVAL(jsString);
        1889               0 :   JSAutoByteString jsCallback(cx, jsString);
        1890               0 :   NS_ENSURE_TRUE(!!jsCallback, NS_ERROR_OUT_OF_MEMORY);
        1891                 :
        1892               0 :   nrv = xpc->WrapNative(cx, ::JS_GetGlobalObject(cx),
        1893                 :                         static_cast<nsIDOMCrypto *>(this),
        1894               0 :                         NS_GET_IID(nsIDOMCrypto), getter_AddRefs(holder));
        1895               0 :   NS_ENSURE_SUCCESS(nrv, nrv);
        1896                 :
        1897               0 :   nrv = holder->GetJSObject(&script_obj);
        1898               0 :   NS_ENSURE_SUCCESS(nrv, nrv);
        1899                 :
        1900                 :   //Put up some UI warning that someone is trying to
        1901                 :   //escrow the private key.
        1902                 :   //Don't addref this copy.  That way ths reference goes away
        1903                 :   //at the same the nsIX09Cert ref goes away.
        1904               0 :   nsNSSCertificate *escrowCert = nsnull;
        1905               0 :   nsCOMPtr<nsIX509Cert> nssCert;
        1906               0 :   bool willEscrow = false;
        1907               0 :   if (!!eaCert) {
        1908               0 :     SECItem certDer = {siBuffer, nsnull, 0};
        1909               0 :     SECStatus srv = ATOB_ConvertAsciiToItem(&certDer, eaCert.ptr());
        1910               0 :     if (srv != SECSuccess) {
        1911               0 :       return NS_ERROR_FAILURE;
        1912                 :     }
        1913                 :     CERTCertificate *cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
        1914                 :                                                     &certDer, nsnull, false,
        1915               0 :                                                     true);
        1916               0 :     if (!cert)
        1917               0 :       return NS_ERROR_FAILURE;
        1918                 :
        1919               0 :     escrowCert = nsNSSCertificate::Create(cert);
        1920               0 :     CERT_DestroyCertificate(cert);
        1921               0 :     nssCert = escrowCert;
        1922               0 :     if (!nssCert)
        1923               0 :       return NS_ERROR_OUT_OF_MEMORY;
        1924                 :
        1925               0 :     nsCOMPtr<nsIDOMCryptoDialogs> dialogs;
        1926               0 :     nsresult rv = getNSSDialogs(getter_AddRefs(dialogs),
        1927                 :                                 NS_GET_IID(nsIDOMCryptoDialogs),
        1928               0 :                                 NS_DOMCRYPTODIALOGS_CONTRACTID);
        1929               0 :     if (NS_FAILED(rv))
        1930               0 :       return rv;
        1931                 :
        1932               0 :     bool okay=false;
        1933                 :     {
        1934               0 :       nsPSMUITracker tracker;
        1935               0 :       if (tracker.isUIForbidden()) {
        1936               0 :         okay = false;
        1937                 :       }
        1938                 :       else {
        1939               0 :         dialogs->ConfirmKeyEscrow(nssCert, &okay);
        1940                 :       }
        1941                 :     }
        1942               0 :     if (!okay)
        1943               0 :       return NS_OK;
        1944               0 :     willEscrow = true;
        1945                 :   }
        1946               0 :   nsCOMPtr<nsIInterfaceRequestor> uiCxt = new PipUIContext;
        1947               0 :   PRInt32 numRequests = (argc - 5)/3;
        1948               0 :   nsKeyPairInfo *keyids = new nsKeyPairInfo[numRequests];
        1949               0 :   if (keyids == nsnull) {
        1950               0 :     JS_ReportError(cx, "%s\n", JS_ERROR_INTERNAL);
        1951               0 :     return NS_ERROR_OUT_OF_MEMORY;
        1952                 :   }
        1953               0 :   memset(keyids, 0, sizeof(nsKeyPairInfo)*numRequests);
        1954                 :   int keyInfoIndex;
        1955                 :   PRUint32 i;
        1956               0 :   PK11SlotInfo *slot = nsnull;
        1957                 :   // Go through all of the arguments and generate the appropriate key pairs.
        1958               0 :   for (i=5,keyInfoIndex=0; i<argc; i+=3,keyInfoIndex++) {
        1959                 :     nrv = cryptojs_ReadArgsAndGenerateKey(cx, &argv[i], &keyids[keyInfoIndex],
        1960               0 :                                          uiCxt, &slot, willEscrow);
        1961                 :
        1962               0 :     if (NS_FAILED(nrv)) {
        1963               0 :       if (slot)
        1964               0 :         PK11_FreeSlot(slot);
        1965               0 :       nsFreeKeyPairInfo(keyids,numRequests);
        1966               0 :       return nrv;
        1967                 :     }
        1968                 :   }
        1969                 :   // By this time we'd better have a slot for the key gen.
        1970               0 :   NS_ASSERTION(slot, "There was no slot selected for key generation");
        1971               0 :   if (slot)
        1972               0 :     PK11_FreeSlot(slot);
        1973                 :
        1974                 :   char *encodedRequest = nsCreateReqFromKeyPairs(keyids,numRequests,
        1975                 :                                                  reqDN.ptr(),regToken.ptr(),
        1976                 :                                                  authenticator.ptr(),
        1977               0 :                                                  escrowCert);
        1978                 : #ifdef DEBUG_javi
        1979                 :   printf ("Created the folloing CRMF request:\n%s\n", encodedRequest);
        1980                 : #endif
        1981               0 :   if (!encodedRequest) {
        1982               0 :     nsFreeKeyPairInfo(keyids, numRequests);
        1983               0 :     return NS_ERROR_FAILURE;
        1984                 :   }
        1985               0 :   nsCRMFObject *newObject = new nsCRMFObject();
        1986               0 :   if (newObject == nsnull) {
        1987               0 :     JS_ReportError(cx, "%s%s\n", JS_ERROR, "could not create crmf JS object");
        1988                 :
        1989               0 :     nsFreeKeyPairInfo(keyids,numRequests);
        1990               0 :     return NS_ERROR_OUT_OF_MEMORY;
        1991                 :   }
        1992               0 :   newObject->SetCRMFRequest(encodedRequest);
        1993               0 :   *aReturn = newObject;
        1994                 :   //Give a reference to the returnee.
        1995               0 :   NS_ADDREF(*aReturn);
        1996               0 :   nsFreeKeyPairInfo(keyids, numRequests);
        1997                 :
        1998                 :   //
        1999                 :   // Post an event on the UI queue so that the JS gets called after
        2000                 :   // we return control to the JS layer.  Why do we have to this?
        2001                 :   // Because when this API was implemented for PSM 1.x w/ Communicator,
        2002                 :   // the only way to make this method work was to have a callback
        2003                 :   // in the JS layer that got called after key generation had happened.
        2004                 :   // So for backwards compatibility, we return control and then just post
        2005                 :   // an event to call the JS the script provides as the code to execute
        2006                 :   // when the request has been generated.
        2007                 :   //
        2008                 :
        2009                 :
        2010                 :   nsCOMPtr<nsIScriptSecurityManager> secMan =
        2011               0 :     do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
        2012               0 :   NS_ENSURE_TRUE(secMan, NS_ERROR_UNEXPECTED);
        2013                 :
        2014               0 :   nsCOMPtr<nsIPrincipal> principals;
        2015               0 :   nsresult rv = secMan->GetSubjectPrincipal(getter_AddRefs(principals));
        2016               0 :   NS_ENSURE_SUCCESS(rv, rv);
        2017               0 :   NS_ENSURE_TRUE(principals, NS_ERROR_UNEXPECTED);
        2018                 :
        2019               0 :   nsCryptoRunArgs *args = new nsCryptoRunArgs();
        2020               0 :   if (!args)
        2021               0 :     return NS_ERROR_OUT_OF_MEMORY;
        2022                 :
        2023               0 :   args->m_cx         = cx;
        2024               0 :   args->m_kungFuDeathGrip = GetISupportsFromContext(cx);
        2025               0 :   args->m_scope      = JS_GetParent(script_obj);
        2026                 :
        2027               0 :   args->m_jsCallback.Adopt(!!jsCallback ? nsCRT::strdup(jsCallback.ptr()) : 0);
        2028               0 :   args->m_principals = principals;
        2029                 :
        2030               0 :   nsCryptoRunnable *cryptoRunnable = new nsCryptoRunnable(args);
        2031               0 :   if (!cryptoRunnable)
        2032               0 :     return NS_ERROR_OUT_OF_MEMORY;
        2033                 :
        2034               0 :   rv = NS_DispatchToMainThread(cryptoRunnable);
        2035               0 :   if (NS_FAILED(rv))
        2036               0 :     delete cryptoRunnable;
        2037                 :
        2038               0 :   return rv;
        2039                 : }
        2040                 :
        2041                 :
        2042                 : // Reminder that we inherit the memory passed into us here.
        2043                 : // An implementation to let us back up certs as an event.
        2044               0 : nsP12Runnable::nsP12Runnable(nsIX509Cert **certArr, PRInt32 numCerts,
        2045               0 :                              nsIPK11Token *token)
        2046                 : {
        2047               0 :   mCertArr  = certArr;
        2048               0 :   mNumCerts = numCerts;
        2049               0 :   mToken = token;
        2050               0 : }
        2051                 :
        2052               0 : nsP12Runnable::~nsP12Runnable()
        2053                 : {
        2054                 :   PRInt32 i;
        2055               0 :   for (i=0; i<mNumCerts; i++) {
        2056               0 :       NS_IF_RELEASE(mCertArr[i]);
        2057                 :   }
        2058               0 :   delete []mCertArr;
        2059               0 : }
        2060                 :
        2061                 :
        2062                 : //Implementation that backs cert(s) into a PKCS12 file
        2063                 : NS_IMETHODIMP
        2064               0 : nsP12Runnable::Run()
        2065                 : {
        2066               0 :   NS_ASSERTION(NS_IsMainThread(), "nsP12Runnable dispatched to the wrong thread");
        2067                 :
        2068               0 :   nsNSSShutDownPreventionLock locker;
        2069               0 :   NS_ASSERTION(mCertArr, "certArr is NULL while trying to back up");
        2070                 :
        2071               0 :   nsString final;
        2072               0 :   nsString temp;
        2073                 :   nsresult rv;
        2074                 :
        2075               0 :   nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
        2076               0 :   if (NS_FAILED(rv))
        2077               0 :     return rv;
        2078                 :
        2079                 :   //Build up the message that let's the user know we're trying to
        2080                 :   //make PKCS12 backups of the new certs.
        2081               0 :   nssComponent->GetPIPNSSBundleString("ForcedBackup1", final);
        2082               0 :   final.Append(NS_LITERAL_STRING("\n\n").get());
        2083               0 :   nssComponent->GetPIPNSSBundleString("ForcedBackup2", temp);
        2084               0 :   final.Append(temp.get());
        2085               0 :   final.Append(NS_LITERAL_STRING("\n\n").get());
        2086                 :
        2087               0 :   nssComponent->GetPIPNSSBundleString("ForcedBackup3", temp);
        2088                 :
        2089               0 :   final.Append(temp.get());
        2090               0 :   nsNSSComponent::ShowAlertWithConstructedString(final);
        2091                 :
        2092                 :   nsCOMPtr<nsIFilePicker> filePicker =
        2093               0 :                         do_CreateInstance("@mozilla.org/filepicker;1", &rv);
        2094               0 :   if (!filePicker) {
        2095               0 :     NS_ERROR("Could not create a file picker when backing up certs.");
        2096               0 :     return rv;
        2097                 :   }
        2098                 :
        2099                 :   nsCOMPtr<nsIWindowWatcher> wwatch =
        2100               0 :     (do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv));
        2101               0 :   NS_ENSURE_SUCCESS(rv, rv);
        2102                 :
        2103               0 :   nsCOMPtr<nsIDOMWindow> window;
        2104               0 :   wwatch->GetActiveWindow(getter_AddRefs(window));
        2105                 :
        2106               0 :   nsString filePickMessage;
        2107               0 :   nssComponent->GetPIPNSSBundleString("chooseP12BackupFileDialog",
        2108               0 :                                       filePickMessage);
        2109               0 :   rv = filePicker->Init(window, filePickMessage, nsIFilePicker::modeSave);
        2110               0 :   NS_ENSURE_SUCCESS(rv, rv);
        2111                 :
        2112               0 :   filePicker->AppendFilter(NS_LITERAL_STRING("PKCS12"),
        2113               0 :                            NS_LITERAL_STRING("*.p12"));
        2114               0 :   filePicker->AppendFilters(nsIFilePicker::filterAll);
        2115                 :
        2116                 :   PRInt16 dialogReturn;
        2117               0 :   filePicker->Show(&dialogReturn);
        2118               0 :   if (dialogReturn == nsIFilePicker::returnCancel)
        2119               0 :     return NS_OK;  //User canceled.  It'd be nice if they couldn't,
        2120                 :                    //but oh well.
        2121                 :
        2122               0 :   nsCOMPtr<nsILocalFile> localFile;
        2123               0 :   rv = filePicker->GetFile(getter_AddRefs(localFile));
        2124               0 :   if (NS_FAILED(rv))
        2125               0 :     return NS_ERROR_FAILURE;
        2126                 :
        2127               0 :   nsPKCS12Blob p12Cxt;
        2128                 :
        2129               0 :   p12Cxt.SetToken(mToken);
        2130               0 :   p12Cxt.ExportToFile(localFile, mCertArr, mNumCerts);
        2131               0 :   return NS_OK;
        2132                 : }
        2133                 :
        2134               0 : nsCryptoRunArgs::nsCryptoRunArgs()
        2135                 : {
        2136               0 : }
        2137               0 : nsCryptoRunArgs::~nsCryptoRunArgs() {}
        2138                 :
        2139                 :
        2140               0 : nsCryptoRunnable::nsCryptoRunnable(nsCryptoRunArgs *args)
        2141                 : {
        2142               0 :   nsNSSShutDownPreventionLock locker;
        2143               0 :   NS_ASSERTION(args,"Passed nsnull to nsCryptoRunnable constructor.");
        2144               0 :   m_args = args;
        2145               0 :   NS_IF_ADDREF(m_args);
        2146               0 :   JS_AddNamedObjectRoot(args->m_cx, &args->m_scope,"nsCryptoRunnable::mScope");
        2147               0 : }
        2148                 :
        2149               0 : nsCryptoRunnable::~nsCryptoRunnable()
        2150                 : {
        2151               0 :   nsNSSShutDownPreventionLock locker;
        2152                 :
        2153                 :   {
        2154               0 :     JSAutoRequest ar(m_args->m_cx);
        2155               0 :     JS_RemoveObjectRoot(m_args->m_cx, &m_args->m_scope);
        2156                 :   }
        2157                 :
        2158               0 :   NS_IF_RELEASE(m_args);
        2159               0 : }
        2160                 :
        2161                 : //Implementation that runs the callback passed to
        2162                 : //crypto.generateCRMFRequest as an event.
        2163                 : NS_IMETHODIMP
        2164               0 : nsCryptoRunnable::Run()
        2165                 : {
        2166               0 :   nsNSSShutDownPreventionLock locker;
        2167               0 :   JSContext *cx = m_args->m_cx;
        2168                 :
        2169               0 :   JSAutoRequest ar(cx);
        2170               0 :   JSAutoEnterCompartment ac;
        2171                 :
        2172               0 :   if (!ac.enter(cx, m_args->m_scope)) {
        2173               0 :     return NS_ERROR_FAILURE;
        2174                 :   }
        2175                 :
        2176                 :   // make sure the right context is on the stack. must not return w/out popping
        2177               0 :   nsCOMPtr<nsIJSContextStack> stack(do_GetService("@mozilla.org/js/xpc/ContextStack;1"));
        2178               0 :   if (!stack || NS_FAILED(stack->Push(cx))) {
        2179               0 :     return NS_ERROR_FAILURE;
        2180                 :   }
        2181                 :
        2182                 :   JSBool ok =
        2183                 :     JS_EvaluateScriptForPrincipals(cx, m_args->m_scope,
        2184               0 :                                    nsJSPrincipals::get(m_args->m_principals),
        2185                 :                                    m_args->m_jsCallback,
        2186                 :                                    strlen(m_args->m_jsCallback),
        2187               0 :                                    nsnull, 0, nsnull);
        2188               0 :   stack->Pop(nsnull);
        2189               0 :   return ok ? NS_OK : NS_ERROR_FAILURE;
        2190                 : }
        2191                 :
        2192                 : //Quick helper function to check if a newly issued cert
        2193                 : //already exists in the user's database.
        2194                 : static bool
        2195               0 : nsCertAlreadyExists(SECItem *derCert)
        2196                 : {
        2197               0 :   CERTCertDBHandle *handle = CERT_GetDefaultCertDB();
        2198                 :   CERTCertificate *cert;
        2199               0 :   bool retVal = false;
        2200                 :
        2201               0 :   cert = CERT_FindCertByDERCert(handle, derCert);
        2202               0 :   if (cert) {
        2203               0 :     if (cert->isperm && !cert->nickname && !cert->emailAddr) {
        2204                 :       //If the cert doesn't have a nickname or email addr, it is
        2205                 :       //bogus cruft, so delete it.
        2206               0 :       SEC_DeletePermCertificate(cert);
        2207               0 :     } else if (cert->isperm) {
        2208               0 :       retVal = true;
        2209                 :     }
        2210               0 :     CERT_DestroyCertificate(cert);
        2211                 :   }
        2212               0 :   return retVal;
        2213                 : }
        2214                 :
        2215                 : static PRInt32
        2216               0 : nsCertListCount(CERTCertList *certList)
        2217                 : {
        2218               0 :   PRInt32 numCerts = 0;
        2219                 :   CERTCertListNode *node;
        2220                 :
        2221               0 :   node = CERT_LIST_HEAD(certList);
        2222               0 :   while (!CERT_LIST_END(node, certList)) {
        2223               0 :     numCerts++;
        2224               0 :     node = CERT_LIST_NEXT(node);
        2225                 :   }
        2226               0 :   return numCerts;
        2227                 : }
        2228                 :
        2229                 :
        2230                 : //Import user certificates that arrive as a CMMF base64 encoded
        2231                 : //string.
        2232                 : NS_IMETHODIMP
        2233               0 : nsCrypto::ImportUserCertificates(const nsAString& aNickname,
        2234                 :                                  const nsAString& aCmmfResponse,
        2235                 :                                  bool aDoForcedBackup,
        2236                 :                                  nsAString& aReturn)
        2237                 : {
        2238               0 :   nsNSSShutDownPreventionLock locker;
        2239               0 :   char *nickname=nsnull, *cmmfResponse=nsnull;
        2240               0 :   CMMFCertRepContent *certRepContent = nsnull;
        2241               0 :   int numResponses = 0;
        2242               0 :   nsIX509Cert **certArr = nsnull;
        2243                 :   int i;
        2244                 :   CMMFCertResponse *currResponse;
        2245                 :   CMMFPKIStatus reqStatus;
        2246                 :   CERTCertificate *currCert;
        2247                 :   PK11SlotInfo *slot;
        2248               0 :   nsCAutoString localNick;
        2249               0 :   nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext();
        2250               0 :   nsresult rv = NS_OK;
        2251               0 :   CERTCertList *caPubs = nsnull;
        2252               0 :   nsCOMPtr<nsIPK11Token> token;
        2253                 :
        2254               0 :   nickname = ToNewCString(aNickname);
        2255               0 :   cmmfResponse = ToNewCString(aCmmfResponse);
        2256               0 :   if (nsCRT::strcmp("null", nickname) == 0) {
        2257               0 :     nsMemory::Free(nickname);
        2258               0 :     nickname = nsnull;
        2259                 :   }
        2260                 :
        2261               0 :   SECItem cmmfDer = {siBuffer, nsnull, 0};
        2262               0 :   SECStatus srv = ATOB_ConvertAsciiToItem(&cmmfDer, cmmfResponse);
        2263                 :
        2264               0 :   if (srv != SECSuccess) {
        2265               0 :     rv = NS_ERROR_FAILURE;
        2266               0 :     goto loser;
        2267                 :   }
        2268                 :
        2269                 :   certRepContent = CMMF_CreateCertRepContentFromDER(CERT_GetDefaultCertDB(),
        2270                 :                                                     (const char*)cmmfDer.data,
        2271               0 :                                                     cmmfDer.len);
        2272               0 :   if (!certRepContent) {
        2273               0 :     rv = NS_ERROR_FAILURE;
        2274               0 :     goto loser;
        2275                 :   }
        2276                 :
        2277               0 :   numResponses = CMMF_CertRepContentGetNumResponses(certRepContent);
        2278                 :
        2279               0 :   if (aDoForcedBackup) {
        2280                 :     //We've been asked to force the user to back up these
        2281                 :     //certificates.  Let's keep an array of them around which
        2282                 :     //we pass along to the nsP12Runnable to use.
        2283               0 :     certArr = new nsIX509Cert*[numResponses];
        2284                 :     // If this is NULL, chances are we're gonna fail really soon,
        2285                 :     // but let's try to keep going just in case.
        2286               0 :     if (!certArr)
        2287               0 :       aDoForcedBackup = false;
        2288                 :
        2289               0 :     memset(certArr, 0, sizeof(nsIX509Cert*)*numResponses);
        2290                 :   }
        2291               0 :   for (i=0; i<numResponses; i++) {
        2292               0 :     currResponse = CMMF_CertRepContentGetResponseAtIndex(certRepContent,i);
        2293               0 :     if (!currResponse) {
        2294               0 :       rv = NS_ERROR_FAILURE;
        2295               0 :       goto loser;
        2296                 :     }
        2297               0 :     reqStatus = CMMF_CertResponseGetPKIStatusInfoStatus(currResponse);
        2298               0 :     if (!(reqStatus == cmmfGranted || reqStatus == cmmfGrantedWithMods)) {
        2299                 :       // The CA didn't give us the cert we requested.
        2300               0 :       rv = NS_ERROR_FAILURE;
        2301               0 :       goto loser;
        2302                 :     }
        2303                 :     currCert = CMMF_CertResponseGetCertificate(currResponse,
        2304               0 :                                                CERT_GetDefaultCertDB());
        2305               0 :     if (!currCert) {
        2306               0 :       rv = NS_ERROR_FAILURE;
        2307               0 :       goto loser;
        2308                 :     }
        2309                 :
        2310               0 :     if (nsCertAlreadyExists(&currCert->derCert)) {
        2311               0 :       if (aDoForcedBackup) {
        2312               0 :         certArr[i] = nsNSSCertificate::Create(currCert);
        2313               0 :         if (!certArr[i])
        2314               0 :           goto loser;
        2315               0 :         NS_ADDREF(certArr[i]);
        2316                 :       }
        2317               0 :       CERT_DestroyCertificate(currCert);
        2318               0 :       CMMF_DestroyCertResponse(currResponse);
        2319               0 :       continue;
        2320                 :     }
        2321                 :     // Let's figure out which nickname to give the cert.  If
        2322                 :     // a certificate with the same subject name already exists,
        2323                 :     // then just use that one, otherwise, get the default nickname.
        2324               0 :     if (currCert->nickname) {
        2325               0 :       localNick = currCert->nickname;
        2326                 :     }
        2327               0 :     else if (nickname == nsnull || nickname[0] == '\0') {
        2328               0 :       nsNSSCertificateDB::get_default_nickname(currCert, ctx, localNick);
        2329                 :     } else {
        2330                 :       //This is the case where we're getting a brand new
        2331                 :       //cert that doesn't have the same subjectName as a cert
        2332                 :       //that already exists in our db and the CA page has
        2333                 :       //designated a nickname to use for the newly issued cert.
        2334               0 :       localNick = nickname;
        2335                 :     }
        2336                 :     {
        2337               0 :       char *cast_const_away = const_cast<char*>(localNick.get());
        2338               0 :       slot = PK11_ImportCertForKey(currCert, cast_const_away, ctx);
        2339                 :     }
        2340               0 :     if (slot == nsnull) {
        2341               0 :       rv = NS_ERROR_FAILURE;
        2342               0 :       goto loser;
        2343                 :     }
        2344               0 :     if (aDoForcedBackup) {
        2345               0 :       certArr[i] = nsNSSCertificate::Create(currCert);
        2346               0 :       if (!certArr[i])
        2347               0 :         goto loser;
        2348               0 :       NS_ADDREF(certArr[i]);
        2349                 :     }
        2350               0 :     CERT_DestroyCertificate(currCert);
        2351                 :
        2352               0 :     if (!token)
        2353               0 :       token = new nsPK11Token(slot);
        2354                 :
        2355               0 :     PK11_FreeSlot(slot);
        2356               0 :     CMMF_DestroyCertResponse(currResponse);
        2357                 :   }
        2358                 :   //Let the loser: label take care of freeing up our reference to
        2359                 :   //nickname (This way we don't free it twice and avoid crashing.
        2360                 :   //That would be a good thing.
        2361                 :
        2362                 :   //Import the root chain into the cert db.
        2363               0 :   caPubs = CMMF_CertRepContentGetCAPubs(certRepContent);
        2364               0 :   if (caPubs) {
        2365               0 :     PRInt32 numCAs = nsCertListCount(caPubs);
        2366                 :
        2367               0 :     NS_ASSERTION(numCAs > 0, "Invalid number of CA's");
        2368               0 :     if (numCAs > 0) {
        2369                 :       CERTCertListNode *node;
        2370                 :       SECItem *derCerts;
        2371                 :
        2372                 :       derCerts = static_cast<SECItem*>
        2373               0 :                             (nsMemory::Alloc(sizeof(SECItem)*numCAs));
        2374               0 :       if (!derCerts) {
        2375               0 :         rv = NS_ERROR_OUT_OF_MEMORY;
        2376               0 :         goto loser;
        2377                 :       }
        2378               0 :       for (node = CERT_LIST_HEAD(caPubs), i=0;
        2379               0 :            !CERT_LIST_END(node, caPubs);
        2380                 :            node = CERT_LIST_NEXT(node), i++) {
        2381               0 :         derCerts[i] = node->cert->derCert;
        2382                 :       }
        2383               0 :       nsNSSCertificateDB::ImportValidCACerts(numCAs, derCerts, ctx);
        2384               0 :       nsMemory::Free(derCerts);
        2385                 :     }
        2386                 :
        2387               0 :     CERT_DestroyCertList(caPubs);
        2388                 :   }
        2389                 :
        2390               0 :   if (aDoForcedBackup) {
        2391                 :     // I can't pop up a file picker from the depths of JavaScript,
        2392                 :     // so I'll just post an event on the UI queue to do the backups
        2393                 :     // later.
        2394                 :     nsCOMPtr<nsIRunnable> p12Runnable = new nsP12Runnable(certArr, numResponses,
        2395               0 :                                                           token);
        2396               0 :     if (!p12Runnable) {
        2397               0 :       rv = NS_ERROR_FAILURE;
        2398                 :       goto loser;
        2399                 :     }
        2400                 :
        2401                 :     // null out the certArr pointer which has now been inherited by
        2402                 :     // the nsP12Runnable instance so that we don't free up the
        2403                 :     // memory on the way out.
        2404               0 :     certArr = nsnull;
        2405                 :
        2406               0 :     rv = NS_DispatchToMainThread(p12Runnable);
        2407               0 :     if (NS_FAILED(rv))
        2408                 :       goto loser;
        2409                 :   }
        2410                 :
        2411                 :  loser:
        2412               0 :   if (certArr) {
        2413               0 :     for (i=0; i<numResponses; i++) {
        2414               0 :       NS_IF_RELEASE(certArr[i]);
        2415                 :     }
        2416               0 :     delete []certArr;
        2417                 :   }
        2418               0 :   aReturn.Assign(EmptyString());
        2419               0 :   if (nickname) {
        2420               0 :     NS_Free(nickname);
        2421                 :   }
        2422               0 :   if (cmmfResponse) {
        2423               0 :     NS_Free(cmmfResponse);
        2424                 :   }
        2425               0 :   if (certRepContent) {
        2426               0 :     CMMF_DestroyCertRepContent(certRepContent);
        2427                 :   }
        2428               0 :   return rv;
        2429                 : }
        2430                 :
        2431                 : NS_IMETHODIMP
        2432               0 : nsCrypto::PopChallengeResponse(const nsAString& aChallenge,
        2433                 :                                nsAString& aReturn)
        2434                 : {
        2435               0 :   return NS_ERROR_NOT_IMPLEMENTED;
        2436                 : }
        2437                 :
        2438                 : NS_IMETHODIMP
        2439               0 : nsCrypto::Random(PRInt32 aNumBytes, nsAString& aReturn)
        2440                 : {
        2441               0 :   return NS_ERROR_NOT_IMPLEMENTED;
        2442                 : }
        2443                 :
        2444                 : static void
        2445               0 : GetDocumentFromContext(JSContext *cx, nsIDocument **aDocument)
        2446                 : {
        2447                 :   // Get the script context.
        2448               0 :   nsIScriptContext* scriptContext = GetScriptContextFromJSContext(cx);
        2449               0 :   if (!scriptContext) {
        2450               0 :     return;
        2451                 :   }
        2452                 :
        2453                 :   nsCOMPtr<nsIDOMWindow> domWindow =
        2454               0 :     do_QueryInterface(scriptContext->GetGlobalObject());
        2455               0 :   if (!domWindow) {
        2456                 :     return;
        2457                 :   }
        2458                 :
        2459               0 :   nsCOMPtr<nsIDOMDocument> domDocument;
        2460               0 :   domWindow->GetDocument(getter_AddRefs(domDocument));
        2461               0 :   if (!domDocument) {
        2462                 :     return;
        2463                 :   }
        2464                 :
        2465               0 :   CallQueryInterface(domDocument, aDocument);
        2466                 :
        2467                 :   return;
        2468                 : }
        2469                 :
        2470               0 : void signTextOutputCallback(void *arg, const char *buf, unsigned long len)
        2471                 : {
        2472               0 :   ((nsCString*)arg)->Append(buf, len);
        2473               0 : }
        2474                 :
        2475                 : NS_IMETHODIMP
        2476               0 : nsCrypto::SignText(const nsAString& aStringToSign, const nsAString& aCaOption,
        2477                 :                    nsAString& aResult)
        2478                 : {
        2479                 :   // XXX This code should return error codes, but we're keeping this
        2480                 :   //     backwards compatible with NS4.x and so we can't throw exceptions.
        2481               0 :   NS_NAMED_LITERAL_STRING(internalError, "error:internalError");
        2482                 :
        2483               0 :   aResult.Truncate();
        2484                 :
        2485               0 :   nsAXPCNativeCallContext* ncc = nsnull;
        2486               0 :   nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID()));
        2487               0 :   if (xpc) {
        2488               0 :     xpc->GetCurrentNativeCallContext(&ncc);
        2489                 :   }
        2490                 :
        2491               0 :   if (!ncc) {
        2492               0 :     aResult.Append(internalError);
        2493                 :
        2494               0 :     return NS_OK;
        2495                 :   }
        2496                 :
        2497                 :   PRUint32 argc;
        2498               0 :   ncc->GetArgc(&argc);
        2499                 :
        2500                 :   JSContext *cx;
        2501               0 :   ncc->GetJSContext(&cx);
        2502               0 :   if (!cx) {
        2503               0 :     aResult.Append(internalError);
        2504                 :
        2505               0 :     return NS_OK;
        2506                 :   }
        2507                 :
        2508               0 :   if (!aCaOption.EqualsLiteral("auto") &&
        2509               0 :       !aCaOption.EqualsLiteral("ask")) {
        2510               0 :     JS_ReportError(cx, "%s%s\n", JS_ERROR, "caOption argument must be ask or auto");
        2511                 :
        2512               0 :     aResult.Append(internalError);
        2513                 :
        2514               0 :     return NS_OK;
        2515                 :   }
        2516                 :
        2517                 :   // It was decided to always behave as if "ask" were specified.
        2518                 :   // XXX Should we warn in the JS Console for auto?
        2519                 :
        2520               0 :   nsCOMPtr<nsIInterfaceRequestor> uiContext = new PipUIContext;
        2521               0 :   if (!uiContext) {
        2522               0 :     aResult.Append(internalError);
        2523                 :
        2524               0 :     return NS_OK;
        2525                 :   }
        2526                 :
        2527               0 :   bool bestOnly = true;
        2528               0 :   bool validOnly = true;
        2529                 :   CERTCertList* certList =
        2530                 :     CERT_FindUserCertsByUsage(CERT_GetDefaultCertDB(), certUsageEmailSigner,
        2531               0 :                               bestOnly, validOnly, uiContext);
        2532                 :
        2533               0 :   PRUint32 numCAs = argc - 2;
        2534               0 :   if (numCAs > 0) {
        2535               0 :     jsval *argv = nsnull;
        2536               0 :     ncc->GetArgvPtr(&argv);
        2537                 :
        2538               0 :     nsAutoArrayPtr<JSAutoByteString> caNameBytes(new JSAutoByteString[numCAs]);
        2539               0 :     if (!caNameBytes) {
        2540               0 :       aResult.Append(internalError);
        2541               0 :       return NS_OK;
        2542                 :     }
        2543                 :
        2544               0 :     JSAutoRequest ar(cx);
        2545                 :
        2546                 :     PRUint32 i;
        2547               0 :     for (i = 2; i < argc; ++i) {
        2548               0 :       JSString *caName = JS_ValueToString(cx, argv[i]);
        2549               0 :       NS_ENSURE_TRUE(caName, NS_ERROR_OUT_OF_MEMORY);
        2550               0 :       argv[i] = STRING_TO_JSVAL(caName);
        2551               0 :       caNameBytes[i - 2].encode(cx, caName);
        2552               0 :       NS_ENSURE_TRUE(!!caNameBytes[i - 2], NS_ERROR_OUT_OF_MEMORY);
        2553                 :     }
        2554                 :
        2555               0 :     nsAutoArrayPtr<char*> caNames(new char*[numCAs]);
        2556               0 :     if (!caNames) {
        2557               0 :       aResult.Append(internalError);
        2558               0 :       return NS_OK;
        2559                 :     }
        2560                 :
        2561               0 :     for (i = 0; i < numCAs; ++i)
        2562               0 :       caNames[i] = caNameBytes[i].ptr();
        2563                 :
        2564               0 :     if (certList &&
        2565                 :         CERT_FilterCertListByCANames(certList, numCAs, caNames,
        2566               0 :                                      certUsageEmailSigner) != SECSuccess) {
        2567               0 :       aResult.Append(internalError);
        2568                 :
        2569               0 :       return NS_OK;
        2570                 :     }
        2571                 :   }
        2572                 :
        2573               0 :   if (!certList || CERT_LIST_EMPTY(certList)) {
        2574               0 :     aResult.AppendLiteral("error:noMatchingCert");
        2575                 :
        2576               0 :     return NS_OK;
        2577                 :   }
        2578                 :
        2579                 :   nsCOMPtr<nsIFormSigningDialog> fsd =
        2580               0 :     do_CreateInstance(NS_FORMSIGNINGDIALOG_CONTRACTID);
        2581               0 :   if (!fsd) {
        2582               0 :     aResult.Append(internalError);
        2583                 :
        2584               0 :     return NS_OK;
        2585                 :   }
        2586                 :
        2587               0 :   nsCOMPtr<nsIDocument> document;
        2588               0 :   GetDocumentFromContext(cx, getter_AddRefs(document));
        2589               0 :   if (!document) {
        2590               0 :     aResult.Append(internalError);
        2591                 :
        2592               0 :     return NS_OK;
        2593                 :   }
        2594                 :
        2595                 :   // Get the hostname from the URL of the document.
        2596               0 :   nsIURI* uri = document->GetDocumentURI();
        2597               0 :   if (!uri) {
        2598               0 :     aResult.Append(internalError);
        2599                 :
        2600               0 :     return NS_OK;
        2601                 :   }
        2602                 :
        2603                 :   nsresult rv;
        2604                 :
        2605               0 :   nsCString host;
        2606               0 :   rv = uri->GetHost(host);
        2607               0 :   if (NS_FAILED(rv)) {
        2608               0 :     aResult.Append(internalError);
        2609                 :
        2610               0 :     return NS_OK;
        2611                 :   }
        2612                 :
        2613               0 :   PRInt32 numberOfCerts = 0;
        2614                 :   CERTCertListNode* node;
        2615               0 :   for (node = CERT_LIST_HEAD(certList); !CERT_LIST_END(node, certList);
        2616                 :        node = CERT_LIST_NEXT(node)) {
        2617               0 :     ++numberOfCerts;
        2618                 :   }
        2619                 :
        2620               0 :   CERTCertNicknames* nicknames = getNSSCertNicknamesFromCertList(certList);
        2621                 :
        2622               0 :   if (!nicknames) {
        2623               0 :     aResult.Append(internalError);
        2624                 :
        2625               0 :     return NS_OK;
        2626                 :   }
        2627                 :
        2628               0 :   CERTCertNicknamesCleaner cnc(nicknames);
        2629                 :
        2630               0 :   NS_ASSERTION(nicknames->numnicknames == numberOfCerts,
        2631                 :                "nicknames->numnicknames != numberOfCerts");
        2632                 :
        2633               0 :   nsAutoArrayPtr<PRUnichar*> certNicknameList(new PRUnichar*[nicknames->numnicknames * 2]);
        2634               0 :   if (!certNicknameList) {
        2635               0 :     aResult.Append(internalError);
        2636                 :
        2637               0 :     return NS_OK;
        2638                 :   }
        2639                 :
        2640               0 :   PRUnichar** certDetailsList = certNicknameList.get() + nicknames->numnicknames;
        2641                 :
        2642                 :   PRInt32 certsToUse;
        2643               0 :   for (node = CERT_LIST_HEAD(certList), certsToUse = 0;
        2644               0 :        !CERT_LIST_END(node, certList) && certsToUse < nicknames->numnicknames;
        2645                 :        node = CERT_LIST_NEXT(node)) {
        2646               0 :     nsRefPtr<nsNSSCertificate> tempCert = nsNSSCertificate::Create(node->cert);
        2647               0 :     if (tempCert) {
        2648               0 :       nsAutoString nickWithSerial, details;
        2649               0 :       rv = tempCert->FormatUIStrings(NS_ConvertUTF8toUTF16(nicknames->nicknames[certsToUse]),
        2650               0 :                                      nickWithSerial, details);
        2651               0 :       if (NS_SUCCEEDED(rv)) {
        2652               0 :         certNicknameList[certsToUse] = ToNewUnicode(nickWithSerial);
        2653               0 :         if (certNicknameList[certsToUse]) {
        2654               0 :           certDetailsList[certsToUse] = ToNewUnicode(details);
        2655               0 :           if (!certDetailsList[certsToUse]) {
        2656               0 :             nsMemory::Free(certNicknameList[certsToUse]);
        2657               0 :             continue;
        2658                 :           }
        2659               0 :           ++certsToUse;
        2660                 :         }
        2661                 :       }
        2662                 :     }
        2663                 :   }
        2664                 :
        2665               0 :   if (certsToUse == 0) {
        2666               0 :     aResult.Append(internalError);
        2667                 :
        2668               0 :     return NS_OK;
        2669                 :   }
        2670                 :
        2671               0 :   NS_ConvertUTF8toUTF16 utf16Host(host);
        2672                 :
        2673               0 :   CERTCertificate *signingCert = nsnull;
        2674                 :   bool tryAgain, canceled;
        2675               0 :   nsAutoString password;
        2676               0 :   do {
        2677                 :     // Throw up the form signing confirmation dialog and get back the index
        2678                 :     // of the selected cert.
        2679               0 :     PRInt32 selectedIndex = -1;
        2680               0 :     rv = fsd->ConfirmSignText(uiContext, utf16Host, aStringToSign,
        2681               0 :                               const_cast<const PRUnichar**>(certNicknameList.get()),
        2682                 :                               const_cast<const PRUnichar**>(certDetailsList),
        2683                 :                               certsToUse, &selectedIndex, password,
        2684               0 :                               &canceled);
        2685               0 :     if (NS_FAILED(rv) || canceled) {
        2686               0 :       break; // out of tryAgain loop
        2687                 :     }
        2688                 :
        2689               0 :     PRInt32 j = 0;
        2690               0 :     for (node = CERT_LIST_HEAD(certList); !CERT_LIST_END(node, certList);
        2691                 :          node = CERT_LIST_NEXT(node)) {
        2692               0 :       if (j == selectedIndex) {
        2693               0 :         signingCert = CERT_DupCertificate(node->cert);
        2694               0 :         break; // out of cert list iteration loop
        2695                 :       }
        2696               0 :       ++j;
        2697                 :     }
        2698                 :
        2699               0 :     if (!signingCert) {
        2700               0 :       rv = NS_ERROR_FAILURE;
        2701               0 :       break; // out of tryAgain loop
        2702                 :     }
        2703                 :
        2704               0 :     NS_ConvertUTF16toUTF8 pwUtf8(password);
        2705                 :
        2706                 :     tryAgain =
        2707                 :       PK11_CheckUserPassword(signingCert->slot,
        2708               0 :                              const_cast<char *>(pwUtf8.get())) != SECSuccess;
        2709                 :     // XXX we should show an error dialog before retrying
        2710                 :   } while (tryAgain);
        2711                 :
        2712                 :   PRInt32 k;
        2713               0 :   for (k = 0; k < certsToUse; ++k) {
        2714               0 :     nsMemory::Free(certNicknameList[k]);
        2715               0 :     nsMemory::Free(certDetailsList[k]);
        2716                 :   }
        2717                 :
        2718               0 :   if (NS_FAILED(rv)) { // something went wrong inside the tryAgain loop
        2719               0 :     aResult.Append(internalError);
        2720                 :
        2721               0 :     return NS_OK;
        2722                 :   }
        2723                 :
        2724               0 :   if (canceled) {
        2725               0 :     aResult.AppendLiteral("error:userCancel");
        2726                 :
        2727               0 :     return NS_OK;
        2728                 :   }
        2729                 :
        2730               0 :   SECKEYPrivateKey* privKey = PK11_FindKeyByAnyCert(signingCert, uiContext);
        2731               0 :   if (!privKey) {
        2732               0 :     aResult.Append(internalError);
        2733                 :
        2734               0 :     return NS_OK;
        2735                 :   }
        2736                 :
        2737               0 :   nsCAutoString charset(document->GetDocumentCharacterSet());
        2738                 :
        2739                 :   // XXX Doing what nsFormSubmission::GetEncoder does (see
        2740                 :   //     http://bugzilla.mozilla.org/show_bug.cgi?id=81203).
        2741               0 :   if (charset.EqualsLiteral("ISO-8859-1")) {
        2742               0 :     charset.AssignLiteral("windows-1252");
        2743                 :   }
        2744                 :
        2745                 :   nsCOMPtr<nsISaveAsCharset> encoder =
        2746               0 :     do_CreateInstance(NS_SAVEASCHARSET_CONTRACTID);
        2747               0 :   if (encoder) {
        2748               0 :     rv = encoder->Init(charset.get(),
        2749                 :                        (nsISaveAsCharset::attr_EntityAfterCharsetConv +
        2750                 :                        nsISaveAsCharset::attr_FallbackDecimalNCR),
        2751               0 :                        0);
        2752                 :   }
        2753                 :
        2754               0 :   nsXPIDLCString buffer;
        2755               0 :   if (aStringToSign.Length() > 0) {
        2756               0 :     if (encoder && NS_SUCCEEDED(rv)) {
        2757               0 :       rv = encoder->Convert(PromiseFlatString(aStringToSign).get(),
        2758               0 :                             getter_Copies(buffer));
        2759               0 :       if (NS_FAILED(rv)) {
        2760               0 :         aResult.Append(internalError);
        2761                 :
        2762               0 :         return NS_OK;
        2763                 :       }
        2764                 :     }
        2765                 :     else {
        2766               0 :       AppendUTF16toUTF8(aStringToSign, buffer);
        2767                 :     }
        2768                 :   }
        2769                 :
        2770               0 :   HASHContext *hc = HASH_Create(HASH_AlgSHA1);
        2771               0 :   if (!hc) {
        2772               0 :     aResult.Append(internalError);
        2773                 :
        2774               0 :     return NS_OK;
        2775                 :   }
        2776                 :
        2777                 :   unsigned char hash[SHA1_LENGTH];
        2778                 :
        2779                 :   SECItem digest;
        2780               0 :   digest.data = hash;
        2781                 :
        2782               0 :   HASH_Begin(hc);
        2783               0 :   HASH_Update(hc, reinterpret_cast<const unsigned char*>(buffer.get()),
        2784               0 :               buffer.Length());
        2785               0 :   HASH_End(hc, digest.data, &digest.len, SHA1_LENGTH);
        2786               0 :   HASH_Destroy(hc);
        2787                 :
        2788               0 :   nsCString p7;
        2789               0 :   SECStatus srv = SECFailure;
        2790                 :
        2791                 :   SEC_PKCS7ContentInfo *ci = SEC_PKCS7CreateSignedData(signingCert,
        2792                 :                                                        certUsageEmailSigner,
        2793                 :                                                        nsnull, SEC_OID_SHA1,
        2794               0 :                                                        &digest, nsnull, uiContext);
        2795               0 :   if (ci) {
        2796               0 :     srv = SEC_PKCS7IncludeCertChain(ci, nsnull);
        2797               0 :     if (srv == SECSuccess) {
        2798               0 :       srv = SEC_PKCS7AddSigningTime(ci);
        2799               0 :       if (srv == SECSuccess) {
        2800                 :         srv = SEC_PKCS7Encode(ci, signTextOutputCallback, &p7, nsnull, nsnull,
        2801               0 :                               uiContext);
        2802                 :       }
        2803                 :     }
        2804                 :
        2805               0 :     SEC_PKCS7DestroyContentInfo(ci);
        2806                 :   }
        2807                 :
        2808               0 :   if (srv != SECSuccess) {
        2809               0 :     aResult.Append(internalError);
        2810                 :
        2811               0 :     return NS_OK;
        2812                 :   }
        2813                 :
        2814                 :   SECItem binary_item;
        2815                 :   binary_item.data = reinterpret_cast<unsigned char*>
        2816               0 :                                      (const_cast<char*>(p7.get()));
        2817               0 :   binary_item.len = p7.Length();
        2818                 :
        2819               0 :   char *result = NSSBase64_EncodeItem(nsnull, nsnull, 0, &binary_item);
        2820               0 :   if (result) {
        2821               0 :     AppendASCIItoUTF16(result, aResult);
        2822                 :   }
        2823                 :   else {
        2824               0 :     aResult.Append(internalError);
        2825                 :   }
        2826                 :
        2827               0 :   PORT_Free(result);
        2828                 :
        2829               0 :   return NS_OK;
        2830                 : }
        2831                 :
        2832                 : //Logout out of all installed PKCS11 tokens.
        2833                 : NS_IMETHODIMP
        2834               0 : nsCrypto::Logout()
        2835                 : {
        2836                 :   nsresult rv;
        2837               0 :   nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
        2838               0 :   if (NS_FAILED(rv))
        2839               0 :     return rv;
        2840                 :
        2841                 :   {
        2842               0 :     nsNSSShutDownPreventionLock locker;
        2843               0 :     PK11_LogoutAll();
        2844               0 :     SSL_ClearSessionCache();
        2845                 :   }
        2846                 :
        2847               0 :   return nssComponent->LogoutAuthenticatedPK11();
        2848                 : }
        2849                 :
        2850                 : NS_IMETHODIMP
        2851               0 : nsCrypto::DisableRightClick()
        2852                 : {
        2853               0 :   return NS_ERROR_NOT_IMPLEMENTED;
        2854                 : }
        2855                 :
        2856               0 : nsCRMFObject::nsCRMFObject()
        2857                 : {
        2858               0 : }
        2859                 :
        2860               0 : nsCRMFObject::~nsCRMFObject()
        2861                 : {
        2862               0 : }
        2863                 :
        2864                 : nsresult
        2865               0 : nsCRMFObject::init()
        2866                 : {
        2867               0 :   return NS_OK;
        2868                 : }
        2869                 :
        2870                 : NS_IMETHODIMP
        2871               0 : nsCRMFObject::GetRequest(nsAString& aRequest)
        2872                 : {
        2873               0 :   aRequest.Assign(mBase64Request);
        2874               0 :   return NS_OK;
        2875                 : }
        2876                 :
        2877                 : nsresult
        2878               0 : nsCRMFObject::SetCRMFRequest(char *inRequest)
        2879                 : {
        2880               0 :   mBase64Request.AssignWithConversion(inRequest);
        2881               0 :   return NS_OK;
        2882                 : }
        2883                 :
        2884               0 : nsPkcs11::nsPkcs11()
        2885                 : {
        2886               0 : }
        2887                 :
        2888               0 : nsPkcs11::~nsPkcs11()
        2889                 : {
        2890               0 : }
        2891                 :
        2892                 : //Quick function to confirm with the user.
        2893                 : bool
        2894               0 : confirm_user(const PRUnichar *message)
        2895                 : {
        2896               0 :   PRInt32 buttonPressed = 1; // If the user exits by clicking the close box, assume No (button 1)
        2897                 :
        2898               0 :   nsCOMPtr<nsIPrompt> prompter;
        2899               0 :   (void) nsNSSComponent::GetNewPrompter(getter_AddRefs(prompter));
        2900                 :
        2901               0 :   if (prompter) {
        2902               0 :     nsPSMUITracker tracker;
        2903               0 :     if (!tracker.isUIForbidden()) {
        2904                 :       // The actual value is irrelevant but we shouldn't be handing out
        2905                 :       // malformed JSBools to XPConnect.
        2906               0 :       bool checkState = false;
        2907               0 :       prompter->ConfirmEx(0, message,
        2908                 :                           (nsIPrompt::BUTTON_DELAY_ENABLE) +
        2909                 :                           (nsIPrompt::BUTTON_POS_1_DEFAULT) +
        2910                 :                           (nsIPrompt::BUTTON_TITLE_OK * nsIPrompt::BUTTON_POS_0) +
        2911                 :                           (nsIPrompt::BUTTON_TITLE_CANCEL * nsIPrompt::BUTTON_POS_1),
        2912               0 :                           nsnull, nsnull, nsnull, nsnull, &checkState, &buttonPressed);
        2913                 :     }
        2914                 :   }
        2915                 :
        2916               0 :   return (buttonPressed == 0);
        2917                 : }
        2918                 :
        2919                 : //Delete a PKCS11 module from the user's profile.
        2920                 : NS_IMETHODIMP
        2921               0 : nsPkcs11::DeleteModule(const nsAString& aModuleName)
        2922                 : {
        2923               0 :   nsNSSShutDownPreventionLock locker;
        2924                 :   nsresult rv;
        2925               0 :   nsString errorMessage;
        2926                 :
        2927               0 :   nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
        2928               0 :   if (NS_FAILED(rv))
        2929               0 :     return rv;
        2930                 :
        2931               0 :   if (aModuleName.IsEmpty()) {
        2932               0 :     return NS_ERROR_ILLEGAL_VALUE;
        2933                 :   }
        2934                 :
        2935               0 :   char *modName = ToNewCString(aModuleName);
        2936                 :   PRInt32 modType;
        2937               0 :   SECStatus srv = SECMOD_DeleteModule(modName, &modType);
        2938               0 :   if (srv == SECSuccess) {
        2939               0 :     SECMODModule *module = SECMOD_FindModule(modName);
        2940               0 :     if (module) {
        2941               0 :       nssComponent->ShutdownSmartCardThread(module);
        2942               0 :       SECMOD_DestroyModule(module);
        2943                 :     }
        2944               0 :     rv = NS_OK;
        2945                 :   } else {
        2946               0 :     rv = NS_ERROR_FAILURE;
        2947                 :   }
        2948               0 :   NS_Free(modName);
        2949               0 :   return rv;
        2950                 : }
        2951                 :
        2952                 : //Add a new PKCS11 module to the user's profile.
        2953                 : NS_IMETHODIMP
        2954               0 : nsPkcs11::AddModule(const nsAString& aModuleName,
        2955                 :                     const nsAString& aLibraryFullPath,
        2956                 :                     PRInt32 aCryptoMechanismFlags,
        2957                 :                     PRInt32 aCipherFlags)
        2958                 : {
        2959               0 :   nsNSSShutDownPreventionLock locker;
        2960                 :   nsresult rv;
        2961               0 :   nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
        2962                 :
        2963               0 :   char *moduleName = ToNewCString(aModuleName);
        2964               0 :   char *fullPath   = ToNewCString(aLibraryFullPath);
        2965               0 :   PRUint32 mechFlags = SECMOD_PubMechFlagstoInternal(aCryptoMechanismFlags);
        2966               0 :   PRUint32 cipherFlags = SECMOD_PubCipherFlagstoInternal(aCipherFlags);
        2967                 :   SECStatus srv = SECMOD_AddNewModule(moduleName, fullPath,
        2968               0 :                                       mechFlags, cipherFlags);
        2969               0 :   if (srv == SECSuccess) {
        2970               0 :     SECMODModule *module = SECMOD_FindModule(moduleName);
        2971               0 :     if (module) {
        2972               0 :       nssComponent->LaunchSmartCardThread(module);
        2973               0 :       SECMOD_DestroyModule(module);
        2974                 :     }
        2975                 :   }
        2976                 :
        2977               0 :   nsMemory::Free(moduleName);
        2978               0 :   nsMemory::Free(fullPath);
        2979                 :
        2980                 :   // The error message we report to the user depends directly on
        2981                 :   // what the return value for SEDMOD_AddNewModule is
        2982               0 :   switch (srv) {
        2983                 :   case SECSuccess:
        2984               0 :     return NS_OK;
        2985                 :   case SECFailure:
        2986               0 :     return NS_ERROR_FAILURE;
        2987                 :   case -2:
        2988               0 :     return NS_ERROR_ILLEGAL_VALUE;
        2989                 :   }
        2990               0 :   NS_ERROR("Bogus return value, this should never happen");
        2991               0 :   return NS_ERROR_FAILURE;
        2992                 : }
        2993                 :

Generated by: LCOV version 1.7