зеркало из https://github.com/mozilla/pjs.git
b=79153 r=javi sr=blizzard
Crypto key generation feedback, prevent crash, cleanup code, add a call from second code path.
This commit is contained in:
Родитель
a9e3165363
Коммит
f2dd5922e1
|
@ -23,6 +23,8 @@
|
|||
#include "nsNSSComponent.h"
|
||||
#include "nsCrypto.h"
|
||||
#include "nsKeygenHandler.h"
|
||||
#include "nsKeygenThread.h"
|
||||
#include "nsINSSDialogs.h"
|
||||
#include "nsNSSCertificate.h"
|
||||
#include "nsPKCS12Blob.h"
|
||||
#include "nsPK11TokenDB.h"
|
||||
|
@ -595,6 +597,10 @@ cryptojs_generateOneKeyPair(JSContext *cx, nsKeyPairInfo *keyPairInfo,
|
|||
PK11SlotInfo *slot, PRBool willEscrow)
|
||||
|
||||
{
|
||||
nsIGeneratingKeypairInfoDialogs * dialogs;
|
||||
nsKeygenThread *KeygenRunnable = 0;
|
||||
nsCOMPtr<nsIKeygenThread> runnable;
|
||||
|
||||
PRUint32 mechanism = cryptojs_convert_to_mechanism(keyPairInfo->keyGenType);
|
||||
void *keyGenParams = nsConvertToActualKeyGenParams(mechanism, params,
|
||||
(params) ? nsCRT::strlen(params):0,
|
||||
|
@ -634,11 +640,46 @@ cryptojs_generateOneKeyPair(JSContext *cx, nsKeyPairInfo *keyPairInfo,
|
|||
isPerm = PR_TRUE;
|
||||
}
|
||||
|
||||
keyPairInfo->privKey = PK11_GenerateKeyPair(slot, mechanism, keyGenParams,
|
||||
&keyPairInfo->pubKey, isPerm,
|
||||
isPerm, uiCxt);
|
||||
rv = getNSSDialogs((void**)&dialogs,
|
||||
NS_GET_IID(nsIGeneratingKeypairInfoDialogs));
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
KeygenRunnable = new nsKeygenThread();
|
||||
if (KeygenRunnable) {
|
||||
NS_ADDREF(KeygenRunnable);
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv) || !KeygenRunnable) {
|
||||
rv = NS_OK;
|
||||
keyPairInfo->privKey = PK11_GenerateKeyPair(slot, mechanism, keyGenParams,
|
||||
&keyPairInfo->pubKey, isPerm,
|
||||
isPerm, uiCxt);
|
||||
} else {
|
||||
KeygenRunnable->SetParams( slot, mechanism, keyGenParams, isPerm, isPerm, uiCxt );
|
||||
|
||||
runnable = do_QueryInterface(KeygenRunnable);
|
||||
|
||||
if (runnable) {
|
||||
rv = dialogs->DisplayGeneratingKeypairInfo(uiCxt, runnable);
|
||||
|
||||
// We call join on the thread,
|
||||
// so we can be sure that no simultaneous access to the passed parameters will happen.
|
||||
KeygenRunnable->Join();
|
||||
|
||||
NS_RELEASE(dialogs);
|
||||
if (!NS_FAILED(rv)) {
|
||||
rv = KeygenRunnable->GetParams(&keyPairInfo->privKey, &keyPairInfo->pubKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsFreeKeyGenParams(mechanism, keyGenParams);
|
||||
|
||||
if (KeygenRunnable) {
|
||||
NS_RELEASE(KeygenRunnable);
|
||||
}
|
||||
|
||||
if (!keyPairInfo->privKey || !keyPairInfo->pubKey) {
|
||||
if (intSlot)
|
||||
PK11_FreeSlot(intSlot);
|
||||
|
|
|
@ -358,7 +358,7 @@ nsKeygenFormProcessor::GetPublicKey(nsString& aValue, nsString& aChallenge,
|
|||
CERTPublicKeyAndChallenge pkac;
|
||||
SECKeySizeChoiceInfo *choice = SECKeySizeChoiceList;
|
||||
nsIGeneratingKeypairInfoDialogs * dialogs;
|
||||
nsKeygenThread KeygenRunnable;
|
||||
nsKeygenThread *KeygenRunnable = 0;
|
||||
nsCOMPtr<nsIKeygenThread> runnable;
|
||||
|
||||
// Get the key size //
|
||||
|
@ -440,40 +440,37 @@ found_match:
|
|||
rv = getNSSDialogs((void**)&dialogs,
|
||||
NS_GET_IID(nsIGeneratingKeypairInfoDialogs));
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
KeygenRunnable = new nsKeygenThread();
|
||||
if (KeygenRunnable) {
|
||||
NS_ADDREF(KeygenRunnable);
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv) || !KeygenRunnable) {
|
||||
rv = NS_OK;
|
||||
privateKey = PK11_GenerateKeyPair(slot, keyGenMechanism, params,
|
||||
&publicKey, PR_TRUE, PR_TRUE, nsnull);
|
||||
} else {
|
||||
GenerateKeypairParameters gkp;
|
||||
gkp.privateKey = nsnull;
|
||||
gkp.publicKey = nsnull;
|
||||
gkp.slot = slot;
|
||||
gkp.keyGenMechanism = keyGenMechanism;
|
||||
gkp.params = params;
|
||||
KeygenRunnable.SetParams(&gkp);
|
||||
// Our parameters instance will be modified by the thread.
|
||||
KeygenRunnable->SetParams( slot, keyGenMechanism, params, PR_TRUE, PR_TRUE, nsnull );
|
||||
|
||||
runnable = do_QueryInterface(&KeygenRunnable);
|
||||
runnable = do_QueryInterface(KeygenRunnable);
|
||||
|
||||
if (runnable) {
|
||||
rv = dialogs->DisplayGeneratingKeypairInfo(m_ctx, runnable);
|
||||
|
||||
// We call join on the thread,
|
||||
// so we can be sure that no simultaneous access will happen.
|
||||
KeygenRunnable.Join();
|
||||
// We call join on the thread,
|
||||
// so we can be sure that no simultaneous access to the passed parameters will happen.
|
||||
KeygenRunnable->Join();
|
||||
|
||||
NS_RELEASE(dialogs);
|
||||
if (!NS_FAILED(rv)) {
|
||||
privateKey = gkp.privateKey;
|
||||
publicKey = gkp.publicKey;
|
||||
slot = gkp.slot;
|
||||
keyGenMechanism = gkp.keyGenMechanism;
|
||||
params = gkp.params;
|
||||
rv = KeygenRunnable->GetParams(&privateKey, &publicKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!privateKey) {
|
||||
if (NS_FAILED(rv) || !privateKey) {
|
||||
goto loser;
|
||||
}
|
||||
// just in case we'll need to authenticate to the db -jp //
|
||||
|
@ -547,6 +544,9 @@ loser:
|
|||
if (slot != nsnull) {
|
||||
PK11_FreeSlot(slot);
|
||||
}
|
||||
if (KeygenRunnable) {
|
||||
NS_RELEASE(KeygenRunnable);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
|
|
@ -32,25 +32,94 @@ nsKeygenThread::nsKeygenThread()
|
|||
iAmRunning(PR_FALSE),
|
||||
keygenReady(PR_FALSE),
|
||||
statusDialogClosed(PR_FALSE),
|
||||
threadHandle(nsnull),
|
||||
params(nsnull)
|
||||
alreadyReceivedParams(PR_FALSE),
|
||||
privateKey(nsnull),
|
||||
publicKey(nsnull),
|
||||
slot(nsnull),
|
||||
keyGenMechanism(0),
|
||||
params(nsnull),
|
||||
isPerm(PR_FALSE),
|
||||
isSensitive(PR_FALSE),
|
||||
wincx(nsnull),
|
||||
threadHandle(nsnull)
|
||||
{
|
||||
NS_INIT_ISUPPORTS();
|
||||
mutex = PR_NewLock();
|
||||
}
|
||||
|
||||
nsKeygenThread::~nsKeygenThread()
|
||||
{
|
||||
if (mutex)
|
||||
if (mutex) {
|
||||
PR_DestroyLock(mutex);
|
||||
}
|
||||
|
||||
if (statusDialogPtr) {
|
||||
NS_RELEASE(statusDialogPtr);
|
||||
}
|
||||
}
|
||||
|
||||
void nsKeygenThread::SetParams(GenerateKeypairParameters *p)
|
||||
void nsKeygenThread::SetParams(
|
||||
PK11SlotInfo *a_slot,
|
||||
PRUint32 a_keyGenMechanism,
|
||||
void *a_params,
|
||||
PRBool a_isPerm,
|
||||
PRBool a_isSensitive,
|
||||
void *a_wincx )
|
||||
{
|
||||
PR_Lock(mutex);
|
||||
params = p;
|
||||
|
||||
if (!alreadyReceivedParams) {
|
||||
alreadyReceivedParams = PR_TRUE;
|
||||
if (a_slot) {
|
||||
slot = PK11_ReferenceSlot(a_slot);
|
||||
}
|
||||
else {
|
||||
slot = nsnull;
|
||||
}
|
||||
keyGenMechanism = a_keyGenMechanism;
|
||||
params = a_params;
|
||||
isPerm = a_isPerm;
|
||||
isSensitive = a_isSensitive;
|
||||
wincx = a_wincx;
|
||||
}
|
||||
|
||||
PR_Unlock(mutex);
|
||||
}
|
||||
|
||||
nsresult nsKeygenThread::GetParams(
|
||||
SECKEYPrivateKey **a_privateKey,
|
||||
SECKEYPublicKey **a_publicKey)
|
||||
{
|
||||
if (!a_privateKey || !a_publicKey) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
|
||||
PR_Lock(mutex);
|
||||
|
||||
// GetParams must not be called until thread creator called
|
||||
// Join on this thread.
|
||||
NS_ASSERTION(keygenReady, "logic error in nsKeygenThread::GetParams");
|
||||
|
||||
if (keygenReady) {
|
||||
*a_privateKey = privateKey;
|
||||
*a_publicKey = publicKey;
|
||||
|
||||
privateKey = 0;
|
||||
publicKey = 0;
|
||||
|
||||
rv = NS_OK;
|
||||
}
|
||||
else {
|
||||
rv = NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
PR_Unlock(mutex);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void PR_CALLBACK nsKeygenThreadRunner(void *arg)
|
||||
{
|
||||
nsKeygenThread *self = NS_STATIC_CAST(nsKeygenThread *, arg);
|
||||
|
@ -78,15 +147,15 @@ nsresult nsKeygenThread::StartKeyGeneration(nsIDOMWindowInternal *statusDialog)
|
|||
|
||||
PR_Lock(mutex);
|
||||
|
||||
statusDialogPtr = wi;
|
||||
NS_ADDREF(statusDialogPtr);
|
||||
wi = 0;
|
||||
|
||||
if (iAmRunning || keygenReady) {
|
||||
PR_Unlock(mutex);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
statusDialogPtr = wi;
|
||||
NS_ADDREF(statusDialogPtr);
|
||||
wi = 0;
|
||||
|
||||
iAmRunning = PR_TRUE;
|
||||
|
||||
threadHandle = PR_CreateThread(PR_USER_THREAD, nsKeygenThreadRunner, NS_STATIC_CAST(void*, this),
|
||||
|
@ -119,8 +188,6 @@ nsresult nsKeygenThread::UserCanceled(PRBool *threadAlreadyClosedDialog)
|
|||
// it again to avoid problems.
|
||||
statusDialogClosed = PR_TRUE;
|
||||
|
||||
NS_RELEASE(statusDialogPtr);
|
||||
|
||||
PR_Unlock(mutex);
|
||||
|
||||
return NS_OK;
|
||||
|
@ -128,22 +195,21 @@ nsresult nsKeygenThread::UserCanceled(PRBool *threadAlreadyClosedDialog)
|
|||
|
||||
void nsKeygenThread::Run(void)
|
||||
{
|
||||
GenerateKeypairParameters *p = 0;
|
||||
PRBool canGenerate = PR_FALSE;
|
||||
|
||||
PR_Lock(mutex);
|
||||
|
||||
if (params) {
|
||||
p = params;
|
||||
// Make sure it's impossible that will use the same parameters again.
|
||||
params = 0;
|
||||
if (alreadyReceivedParams) {
|
||||
canGenerate = PR_TRUE;
|
||||
keygenReady = PR_FALSE;
|
||||
}
|
||||
|
||||
PR_Unlock(mutex);
|
||||
|
||||
if (p)
|
||||
p->privateKey = PK11_GenerateKeyPair(p->slot, p->keyGenMechanism,
|
||||
p->params, &p->publicKey,
|
||||
PR_TRUE, PR_TRUE, nsnull);
|
||||
if (canGenerate)
|
||||
privateKey = PK11_GenerateKeyPair(slot, keyGenMechanism,
|
||||
params, &publicKey,
|
||||
isPerm, isSensitive, wincx);
|
||||
|
||||
// This call gave us ownership over privateKey and publicKey.
|
||||
// But as the params structure is owner by our caller,
|
||||
|
@ -158,6 +224,15 @@ void nsKeygenThread::Run(void)
|
|||
keygenReady = PR_TRUE;
|
||||
iAmRunning = PR_FALSE;
|
||||
|
||||
// forget our parameters
|
||||
if (slot) {
|
||||
PK11_FreeSlot(slot);
|
||||
slot = 0;
|
||||
}
|
||||
keyGenMechanism = 0;
|
||||
params = 0;
|
||||
wincx = 0;
|
||||
|
||||
if (!statusDialogClosed)
|
||||
windowToClose = statusDialogPtr;
|
||||
|
||||
|
|
|
@ -26,15 +26,6 @@
|
|||
|
||||
#include "nsIKeygenThread.h"
|
||||
|
||||
struct GenerateKeypairParameters
|
||||
{
|
||||
SECKEYPrivateKey *privateKey;
|
||||
SECKEYPublicKey *publicKey;
|
||||
PK11SlotInfo *slot;
|
||||
PRUint32 keyGenMechanism;
|
||||
void *params;
|
||||
};
|
||||
|
||||
class nsKeygenThread : public nsIKeygenThread
|
||||
{
|
||||
private:
|
||||
|
@ -45,11 +36,19 @@ private:
|
|||
PRBool iAmRunning;
|
||||
PRBool keygenReady;
|
||||
PRBool statusDialogClosed;
|
||||
|
||||
PRBool alreadyReceivedParams;
|
||||
|
||||
SECKEYPrivateKey *privateKey;
|
||||
SECKEYPublicKey *publicKey;
|
||||
PK11SlotInfo *slot;
|
||||
PRUint32 keyGenMechanism;
|
||||
void *params;
|
||||
PRBool isPerm;
|
||||
PRBool isSensitive;
|
||||
void *wincx;
|
||||
|
||||
PRThread *threadHandle;
|
||||
|
||||
GenerateKeypairParameters *params;
|
||||
|
||||
public:
|
||||
nsKeygenThread();
|
||||
virtual ~nsKeygenThread();
|
||||
|
@ -57,10 +56,17 @@ public:
|
|||
NS_DECL_NSIKEYGENTHREAD
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// This transfers a reference of parameters to the thread
|
||||
// The parameters will not be copied, the caller keeps ownership.
|
||||
// Once the thread is finished, the original instance will be accessed
|
||||
void SetParams(GenerateKeypairParameters *p);
|
||||
void SetParams(
|
||||
PK11SlotInfo *a_slot,
|
||||
PRUint32 a_keyGenMechanism,
|
||||
void *a_params,
|
||||
PRBool a_isPerm,
|
||||
PRBool a_isSensitive,
|
||||
void *a_wincx );
|
||||
|
||||
nsresult GetParams(
|
||||
SECKEYPrivateKey **a_privateKey,
|
||||
SECKEYPublicKey **a_publicKey);
|
||||
|
||||
void Join(void);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче