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 + -
显示快捷键?