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

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
       2             :  *
       3             :  * This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "nsKeygenThread.h"
       8             : 
       9             : #include "mozilla/Assertions.h"
      10             : #include "mozilla/DebugOnly.h"
      11             : 
      12             : #include "GeckoProfiler.h"
      13             : #include "PSMRunnable.h"
      14             : #include "nsCOMPtr.h"
      15             : #include "nsIObserver.h"
      16             : #include "nsNSSShutDown.h"
      17             : #include "nsThreadUtils.h"
      18             : #include "pk11func.h"
      19             : 
      20             : using namespace mozilla;
      21             : using namespace mozilla::psm;
      22             : 
      23           0 : NS_IMPL_ISUPPORTS(nsKeygenThread, nsIKeygenThread)
      24             : 
      25             : 
      26           0 : nsKeygenThread::nsKeygenThread()
      27             : :mutex("nsKeygenThread.mutex"),
      28             :  iAmRunning(false),
      29             :  keygenReady(false),
      30             :  statusDialogClosed(false),
      31             :  alreadyReceivedParams(false),
      32             :  privateKey(nullptr),
      33             :  publicKey(nullptr),
      34             :  slot(nullptr),
      35             :  flags(0),
      36             :  altSlot(nullptr),
      37             :  altFlags(0),
      38             :  usedSlot(nullptr),
      39             :  keyGenMechanism(0),
      40             :  params(nullptr),
      41             :  wincx(nullptr),
      42           0 :  threadHandle(nullptr)
      43             : {
      44           0 : }
      45             : 
      46           0 : nsKeygenThread::~nsKeygenThread()
      47             : {
      48             :   // clean up in the unlikely case that nobody consumed our results
      49             : 
      50           0 :   if (privateKey)
      51           0 :     SECKEY_DestroyPrivateKey(privateKey);
      52             : 
      53           0 :   if (publicKey)
      54           0 :     SECKEY_DestroyPublicKey(publicKey);
      55             : 
      56           0 :   if (usedSlot)
      57           0 :     PK11_FreeSlot(usedSlot);
      58           0 : }
      59             : 
      60           0 : void nsKeygenThread::SetParams(
      61             :     PK11SlotInfo *a_slot,
      62             :     PK11AttrFlags a_flags,
      63             :     PK11SlotInfo *a_alternative_slot,
      64             :     PK11AttrFlags a_alternative_flags,
      65             :     uint32_t a_keyGenMechanism,
      66             :     void *a_params,
      67             :     void *a_wincx )
      68             : {
      69           0 :   nsNSSShutDownPreventionLock locker;
      70           0 :   MutexAutoLock lock(mutex);
      71             : 
      72           0 :     if (!alreadyReceivedParams) {
      73           0 :       alreadyReceivedParams = true;
      74           0 :       slot = (a_slot) ? PK11_ReferenceSlot(a_slot) : nullptr;
      75           0 :       flags = a_flags;
      76           0 :       altSlot = (a_alternative_slot) ? PK11_ReferenceSlot(a_alternative_slot) : nullptr;
      77           0 :       altFlags = a_alternative_flags;
      78           0 :       keyGenMechanism = a_keyGenMechanism;
      79           0 :       params = a_params;
      80           0 :       wincx = a_wincx;
      81             :     }
      82           0 : }
      83             : 
      84           0 : nsresult nsKeygenThread::ConsumeResult(
      85             :     PK11SlotInfo **a_used_slot,
      86             :     SECKEYPrivateKey **a_privateKey,
      87             :     SECKEYPublicKey **a_publicKey)
      88             : {
      89           0 :   if (!a_used_slot || !a_privateKey || !a_publicKey) {
      90           0 :     return NS_ERROR_FAILURE;
      91             :   }
      92             : 
      93             :   nsresult rv;
      94             : 
      95           0 :   MutexAutoLock lock(mutex);
      96             : 
      97             :     // GetParams must not be called until thread creator called
      98             :     // Join on this thread.
      99           0 :     MOZ_ASSERT(keygenReady, "Logic error in nsKeygenThread::GetParams");
     100             : 
     101           0 :     if (keygenReady) {
     102           0 :       *a_privateKey = privateKey;
     103           0 :       *a_publicKey = publicKey;
     104           0 :       *a_used_slot = usedSlot;
     105             : 
     106           0 :       privateKey = 0;
     107           0 :       publicKey = 0;
     108           0 :       usedSlot = 0;
     109             : 
     110           0 :       rv = NS_OK;
     111             :     }
     112             :     else {
     113           0 :       rv = NS_ERROR_FAILURE;
     114             :     }
     115             : 
     116           0 :   return rv;
     117             : }
     118             : 
     119           0 : static void nsKeygenThreadRunner(void *arg)
     120             : {
     121           0 :   AutoProfilerRegisterThread registerThread("Keygen");
     122           0 :   NS_SetCurrentThreadName("Keygen");
     123           0 :   nsKeygenThread *self = static_cast<nsKeygenThread *>(arg);
     124           0 :   self->Run();
     125           0 : }
     126             : 
     127           0 : nsresult nsKeygenThread::StartKeyGeneration(nsIObserver* aObserver)
     128             : {
     129           0 :   if (!NS_IsMainThread()) {
     130           0 :     NS_ERROR("nsKeygenThread::StartKeyGeneration called off the main thread");
     131           0 :     return NS_ERROR_NOT_SAME_THREAD;
     132             :   }
     133             : 
     134           0 :   if (!aObserver)
     135           0 :     return NS_OK;
     136             : 
     137           0 :   MutexAutoLock lock(mutex);
     138             : 
     139           0 :     if (iAmRunning || keygenReady) {
     140           0 :       return NS_OK;
     141             :     }
     142             : 
     143             :     // We must AddRef aObserver only here on the main thread, because it
     144             :     // probably does not implement a thread-safe AddRef.
     145           0 :     mNotifyObserver = new NotifyObserverRunnable(aObserver, "keygen-finished");
     146             : 
     147           0 :     iAmRunning = true;
     148             : 
     149           0 :     threadHandle = PR_CreateThread(PR_USER_THREAD, nsKeygenThreadRunner, static_cast<void*>(this),
     150             :       PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
     151             : 
     152             :     // bool thread_started_ok = (threadHandle != nullptr);
     153             :     // we might want to return "thread started ok" to caller in the future
     154           0 :     MOZ_ASSERT(threadHandle, "Could not create nsKeygenThreadRunner thread");
     155           0 :   return NS_OK;
     156             : }
     157             : 
     158           0 : nsresult nsKeygenThread::UserCanceled(bool *threadAlreadyClosedDialog)
     159             : {
     160           0 :   if (!threadAlreadyClosedDialog)
     161           0 :     return NS_OK;
     162             : 
     163           0 :   *threadAlreadyClosedDialog = false;
     164             : 
     165           0 :   MutexAutoLock lock(mutex);
     166             : 
     167           0 :     if (keygenReady)
     168           0 :       *threadAlreadyClosedDialog = statusDialogClosed;
     169             : 
     170             :     // User somehow closed the dialog, but we will not cancel.
     171             :     // Bad luck, we told him not do, and user still has to wait.
     172             :     // However, we remember that it's closed and will not close
     173             :     // it again to avoid problems.
     174           0 :     statusDialogClosed = true;
     175             : 
     176           0 :   return NS_OK;
     177             : }
     178             : 
     179           0 : void nsKeygenThread::Run(void)
     180             : {
     181           0 :   nsNSSShutDownPreventionLock locker;
     182           0 :   bool canGenerate = false;
     183             : 
     184             :   {
     185           0 :     MutexAutoLock lock(mutex);
     186           0 :     if (alreadyReceivedParams) {
     187           0 :       canGenerate = true;
     188           0 :       keygenReady = false;
     189             :     }
     190             :   }
     191             : 
     192           0 :   if (canGenerate) {
     193           0 :     privateKey = PK11_GenerateKeyPairWithFlags(slot, keyGenMechanism,
     194             :                                                params, &publicKey,
     195             :                                                flags, wincx);
     196             : 
     197           0 :     if (privateKey) {
     198           0 :       usedSlot = PK11_ReferenceSlot(slot);
     199             :     }
     200           0 :     else if (altSlot) {
     201           0 :       privateKey = PK11_GenerateKeyPairWithFlags(altSlot, keyGenMechanism,
     202             :                                                  params, &publicKey,
     203             :                                                  altFlags, wincx);
     204           0 :       if (privateKey) {
     205           0 :         usedSlot = PK11_ReferenceSlot(altSlot);
     206             :       }
     207             :     }
     208             :   }
     209             : 
     210             :   // This call gave us ownership over privateKey and publicKey.
     211             :   // But as the params structure is owner by our caller,
     212             :   // we effectively transferred ownership to the caller.
     213             :   // As long as key generation can't be canceled, we don't need
     214             :   // to care for cleaning this up.
     215             : 
     216           0 :   nsCOMPtr<nsIRunnable> notifyObserver;
     217             :   {
     218           0 :     MutexAutoLock lock(mutex);
     219             : 
     220           0 :     keygenReady = true;
     221           0 :     iAmRunning = false;
     222             : 
     223             :     // forget our parameters
     224           0 :     if (slot) {
     225           0 :       PK11_FreeSlot(slot);
     226           0 :       slot = 0;
     227             :     }
     228           0 :     if (altSlot) {
     229           0 :       PK11_FreeSlot(altSlot);
     230           0 :       altSlot = 0;
     231             :     }
     232           0 :     keyGenMechanism = 0;
     233           0 :     params = 0;
     234           0 :     wincx = 0;
     235             : 
     236           0 :     if (!statusDialogClosed && mNotifyObserver)
     237           0 :       notifyObserver = mNotifyObserver;
     238             : 
     239           0 :     mNotifyObserver = nullptr;
     240             :   }
     241             : 
     242           0 :   if (notifyObserver) {
     243           0 :     DebugOnly<nsresult> rv = NS_DispatchToMainThread(notifyObserver);
     244           0 :     MOZ_ASSERT(NS_SUCCEEDED(rv),
     245             :                "Failed to dispatch keygen thread observer to main thread");
     246             :   }
     247           0 : }
     248             : 
     249           0 : void nsKeygenThread::Join()
     250             : {
     251           0 :   if (!threadHandle)
     252           0 :     return;
     253             : 
     254           0 :   PR_JoinThread(threadHandle);
     255           0 :   threadHandle = nullptr;
     256             : 
     257           0 :   return;
     258             : }

Generated by: LCOV version 1.13