kgenctxt.c
来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 1,252 行 · 第 1/3 页
C
1,252 行
SSMStatusSSMKeyGenContext_FinishGeneratingKeyPair(SSMKeyGenContext *ct, SSMKeyGenParams *kg){ SSMKeyPair *kp = NULL; void *actualParams = NULL; PK11SlotInfo *slot = NULL, *intSlot = NULL, *origSlot = NULL; SSMStatus rv = PR_SUCCESS; PRUint32 keyGenMechanism; SECKEYPublicKey *pubKey = NULL; SECKEYPrivateKey *privKey = NULL; PRBool isPerm; SSM_DEBUG("Inside FinishGeneratingKeyPair.\n"); PR_ASSERT((kg != NULL) && (ct != NULL)); /* If the context is already exiting due to an error, abort the key generation. */ rv = SSMRESOURCE(ct)->m_status; if (rv != PR_SUCCESS) goto loser; /* Restore parameters from the message. */ keyGenMechanism = kg->keyGenMechanism; kp = kg->kp; actualParams = kg->actualParams; /* Finish key generation. */ if (ct->mech != kg->keyGenMechanism) { goto loser; } slot = ct->slot; if (!slot) goto loser; if (ssmkeygencontext_can_escrow(kp->m_KeyGenType) && ct->m_eaCert != NULL && !PK11_IsInternal(slot)) { intSlot = PK11_GetInternalSlot(); origSlot = slot; slot = intSlot; isPerm = PR_FALSE; } else { isPerm = PR_TRUE; } SSM_DEBUG("Creating key pair.\n"); privKey = PK11_GenerateKeyPair(slot, keyGenMechanism, actualParams, &pubKey, isPerm, isPerm, NULL); if ((!privKey) || (!pubKey)) { rv = PR_FAILURE; goto loser; } /* * If we generated the key pair on the internal slot because the * keys were going to be escrowed, move the keys over right now. */ if (intSlot != NULL) { SECKEYPrivateKey *newPrivKey; newPrivKey = pk11_loadPrivKey(origSlot, privKey, pubKey, PR_TRUE, PR_TRUE); if (newPrivKey == NULL) { rv = PR_FAILURE; goto loser; } /* * The key is stored away on the final slot now, and the * the copy we keep around is on the internal slot so we * can escrow it if we have to. */ SECKEY_DestroyPrivateKey(newPrivKey); PK11_FreeSlot(intSlot); intSlot = NULL; } /* Put the newly generated keys into the key pair object. */ kp->m_PubKey = pubKey; kp->m_PrivKey = privKey; /* Set the wincx of the private key so that crypto operations * that use the signing key as the source for the wincx pass * a non NULL value to the authentication functions. */ kp->m_PrivKey->wincx = kp->super.m_connection; goto done; loser: if (rv == PR_SUCCESS) rv = PR_FAILURE; /* Destroy keys if we've generated them. */ if (pubKey) SECKEY_DestroyPublicKey(pubKey); if (privKey) SECKEY_DestroyPrivateKey(privKey); done: /* Free the PKCS11 key gen params. */ if (actualParams != NULL) ssm_FreeKeyGenParams(keyGenMechanism, actualParams); SSM_DEBUG("FinishGeneratingKeyPair returned rv = %d.\n", rv); return rv;}voidSSMKeyGenContext_SendCompleteEvent(SSMKeyGenContext *ct){ SSMStatus rv = PR_SUCCESS; PR_ASSERT(ct->m_parent); if (ct->m_parent) { SECItem msg; TaskCompletedEvent event; /* Assemble the event. */ SSM_DEBUG("Task completed event: id %ld, count %ld, status %d\n", SSMRESOURCE(ct)->m_id, ct->m_count, SSMRESOURCE(ct)->m_status); event.resourceID = SSMRESOURCE(ct)->m_id; event.numTasks = ct->m_count; event.result = SSMRESOURCE(ct)->m_status; if (CMT_EncodeMessage(TaskCompletedEventTemplate, (CMTItem*)&msg, (CMTItem*)&event) != CMTSuccess) { return; } if (msg.data) { /* Send the event to the control queue. */ rv = SSM_SendQMessage(ct->m_parent->m_controlOutQ, SSM_PRIORITY_NORMAL, SSM_EVENT_MESSAGE | SSM_TASK_COMPLETED_EVENT, (int) msg.len, (char *) msg.data, PR_FALSE); SSM_DEBUG("Sent message, rv = %d.\n", rv); } }}SSMStatusSSMKeyGenContext_SendEscrowWarning(SSMKeyGenContext *ct, SSMEscrowWarnParam *escrowParam){ SSMStatus rv; rv = SSMControlConnection_SendUIEvent(SSMRESOURCE(ct)->m_connection, "get", "escrow_warning", SSMRESOURCE(ct), NULL, &SSMRESOURCE(ct)->m_clientContext, PR_FALSE); if (rv != SSM_SUCCESS) { goto loser; } PR_ASSERT(SSMRESOURCE(ct)->m_buttonType == SSM_BUTTON_NONE); while (SSMRESOURCE(ct)->m_buttonType == SSM_BUTTON_NONE) { SSM_WaitForOKCancelEvent(SSMRESOURCE(ct), PR_INTERVAL_NO_TIMEOUT); } /* ### sjlee: this unfortunate hack is due to the fact that bad things * happen if we do not finish closing the window before * another window pops up: this will be supplanted by a * more complete fix later */ PR_Sleep(PR_TicksPerSecond()*2); return (SSMRESOURCE(ct)->m_buttonType == SSM_BUTTON_OK) ? PR_SUCCESS : PR_FAILURE; loser: return PR_FAILURE;}static PRBoolssmkeygencontext_can_escrow(SSMKeyGenType keyGenType){ /* For now, we only escrow rsa-encryption keys. */ return (PRBool)(keyGenType == rsaEnc);}static SSMStatusssmkg_DoKeyEscrowWarning(SSMKeyGenContext *ct){ int i; SSMStatus rv = PR_SUCCESS; if (ct->m_eaCert == NULL || ct->m_disableEscrowWarning) { /* No Escrow Authority Certificate, return Success so that * key generation continues. */ return PR_SUCCESS; } for (i=0; i < ct->m_numKeyGens; i++) { if (ssmkeygencontext_can_escrow(ct->m_keyGens[i]->kp->m_KeyGenType)) { rv = SSMKeyGenContext_SendEscrowWarning(ct, NULL); break; } } return rv;}SSMStatusSSMKeyGenContext_GenerateAllKeys(SSMKeyGenContext *ct){ SSMStatus rv = PR_FAILURE; int i; /* Make sure the UI is up before we start. */ PR_Sleep(PR_TicksPerSecond()*2); /* First figure out if we are going to try and escrow, * pop up UI if we are */ rv = ssmkg_DoKeyEscrowWarning(ct); if (rv != PR_SUCCESS) { /* Tell the service thread to shut itself down. */ SSM_SendQMessage(ct->m_incomingQ, SSM_PRIORITY_SHUTDOWN, SSM_DATA_PROVIDER_SHUTDOWN, 0, NULL, PR_TRUE); goto loser; } /* * We'll force all key gens to use the same mechanism so that when * we create dual keys, we won't prompt the user multiple times for * a slot to create the keys on. */ PR_ASSERT(ct->m_numKeyGens > 0); ct->mech = ct->m_keyGens[0]->keyGenMechanism; rv = SSMKeyGenContext_GetSlot(ct, ct->mech); if (rv != SSM_SUCCESS) goto loser; for (i=0; i<ct->m_numKeyGens; i++) { /* Lock so that we can finish a keygen without the state changing underneath us. */ SSM_DEBUG("Waiting for lock in order to start new keygen.\n", rv); SSM_LockResource(SSMRESOURCE(ct)); /* Do key generation. */ rv = SSMKeyGenContext_FinishGeneratingKeyPair(ct, ct->m_keyGens[i]); if (ct->super.m_status == PR_SUCCESS) { ct->super.m_status = rv; } /* No matter what, update the completed count. */ ct->m_count++; /* Having finished the request, send back a Context Completed event describing our results. */ SSM_DEBUG("Sending Task Completed event to client.\n", rv); SSMKeyGenContext_SendCompleteEvent(ct); /* Unlock the object so that the canceller can work. */ SSM_UnlockResource(SSMRESOURCE(ct)); if (rv != PR_SUCCESS) { break; } } loser: if (ct != NULL) { if (SSMRESOURCE(ct)->m_status != PR_SUCCESS) { rv = SSMRESOURCE(ct)->m_status; } } return rv;}voidSSMKeyGenContext_ServiceThread(void *arg){ SSMKeyGenContext *ct = (SSMKeyGenContext *) arg; SSMResource *res = SSMRESOURCE(ct); PRInt32 type, len; char *url = NULL; char *data = NULL; char *tmp = NULL; SSMStatus rv = PR_SUCCESS; PRBool processingKeys = PR_FALSE; SECItem msg; CreateResourceReply reply; PR_ASSERT(ct); PR_ASSERT(SSM_IsAKindOf(SSMRESOURCE(ct), SSM_RESTYPE_KEYGEN_CONTEXT)); SSM_RegisterNewThread("keygen", (SSMResource*)arg); SSM_DEBUG("Sending Create Resource response to client.\n"); reply.result = PR_SUCCESS; reply.resID = SSMRESOURCE(ct)->m_id; if (CMT_EncodeMessage(CreateResourceReplyTemplate, (CMTItem*)&msg, &reply) != CMTSuccess) { goto loser; } if (!msg.data || !msg.len) { rv = PR_OUT_OF_MEMORY_ERROR; goto loser; } /* Post the message on the outgoing control channel. */ PR_ASSERT(SSM_IsAKindOf(&(ct->m_parent->super.super), SSM_RESTYPE_CONTROL_CONNECTION)); rv = SSM_SendQMessage(ct->m_parent->m_controlOutQ, SSM_PRIORITY_NORMAL, SSM_REPLY_OK_MESSAGE | SSM_RESOURCE_ACTION | SSM_CREATE_RESOURCE, (int) msg.len, (char *) msg.data, PR_FALSE); if (rv != PR_SUCCESS) goto loser; /* Start serving key gen requests. */ while(1) { /* Get the next request from the queue. If we've been cancelled or if there's an error, drain what we have but don't wait around. */ SSM_DEBUG("Reading message from queue.\n");#if 1 if (processingKeys) {#endif SSM_DEBUG("Looking for keygen requests (and anything else).\n"); rv = SSM_RecvQMessage(ct->m_incomingQ, SSM_PRIORITY_ANY, &type, &len, &data, (SSMRESOURCE(ct)->m_status == PR_SUCCESS));#if 1 } else { SSM_DEBUG("Looking only for open/shutdown messages.\n"); rv = SSM_RecvQMessage(ct->m_incomingQ, SSM_PRIORITY_SHUTDOWN, &type, &len, &data, PR_TRUE); }#endif SSM_DEBUG("rv = %d reading from queue.\n", rv); if (rv != SSM_SUCCESS) goto loser; /* If it's a keygen request, then attend to it. */ switch (type) { case SSM_KEYGEN_CXT_MESSAGE_DATA_PROVIDER_OPEN: processingKeys = PR_TRUE; break; case SSM_KEYGEN_CXT_MESSAGE_DATA_PROVIDER_SHUTDOWN: goto loser; /*destroy object */ case SSM_KEYGEN_CXT_MESSAGE_GEN_KEY: if (!processingKeys) { SSM_DEBUG("**** Dropping keygen request on the floor ****\n"); break; } rv = SSMKeyGenContext_GenerateAllKeys(ct); /* * We're done generating keys, so let's bail out of this thread. */ goto loser; default: SSM_DEBUG("Don't understand this request.\n"); /* ### mwelch Don't know what to do with this request */ rv = (SSMStatus) SSM_ERR_BAD_REQUEST; break; } } loser: SSM_LockResource(res); /* De-register ourselves from the resource thread count. */ if (PR_GetCurrentThread() == ct->m_serviceThread) { ct->m_serviceThread = NULL; } res->m_threadCount--; SSM_UnlockResource(res); PR_FREEIF(tmp); PR_FREEIF(url); SSM_DEBUG("Shutting down keygen context.\n"); SSM_ShutdownResource(SSMRESOURCE(ct), rv); SSM_FreeResource(SSMRESOURCE(ct)); SSM_DEBUG("Exiting, status %d.\n", rv);}voidSSMKeyGenContext_CancelKeyGen(SSMKeyGenContext *ct){ /* set the status so that subsequent keygen attempts will drop out */ SSM_ShutdownResource(SSMRESOURCE(ct), SSM_ERR_USER_CANCEL); ct->m_userCancel = PR_TRUE; SSMRESOURCE(ct)->m_status = SSM_ERR_USER_CANCEL;}SSMStatusSSMKeyGenContext_FinishGeneratingAllKeyPairs(SSMControlConnection *ctrl, SECItem *msg){ SSMStatus rv; SSMKeyGenContext *ct; SingleNumMessage request; SSM_DEBUG("SSMKeyGenContext_FinishGeneratingAllKeyPairs...\n"); if (CMT_DecodeMessage(SingleNumMessageTemplate, &request, (CMTItem*)msg) != CMTSuccess) { goto loser; } rv = SSMControlConnection_GetResource(ctrl, request.value, (SSMResource **) &ct); if (rv != PR_SUCCESS) { goto loser; } if (!ct || !SSM_IsAKindOf(SSMRESOURCE(ct), SSM_RESTYPE_KEYGEN_CONTEXT)) { rv = PR_INVALID_ARGUMENT_ERROR; goto loser; } if (ct->m_userCancel) { rv = (SSMStatus)SSM_ERR_USER_CANCEL; goto loser; } rv = SSM_SendQMessage(ct->m_incomingQ, SSM_PRIORITY_NORMAL, SSM_KEYGEN_CXT_MESSAGE_GEN_KEY, 0, NULL, PR_FALSE); loser: if (ct != NULL) { SSM_FreeResource(&ct->super); } return rv;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?