michael@0: /* -*- Mode: C; tab-width: 8 -*-*/ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: michael@0: #include "crmf.h" michael@0: #include "crmfi.h" michael@0: #include "secasn1.h" michael@0: #include "keyhi.h" michael@0: #include "cryptohi.h" michael@0: michael@0: #define CRMF_DEFAULT_ALLOC_SIZE 1024 michael@0: michael@0: SECStatus michael@0: crmf_init_encoder_callback_arg (struct crmfEncoderArg *encoderArg, michael@0: SECItem *derDest) michael@0: { michael@0: derDest->data = PORT_ZNewArray(unsigned char, CRMF_DEFAULT_ALLOC_SIZE); michael@0: if (derDest->data == NULL) { michael@0: return SECFailure; michael@0: } michael@0: derDest->len = 0; michael@0: encoderArg->allocatedLen = CRMF_DEFAULT_ALLOC_SIZE; michael@0: encoderArg->buffer = derDest; michael@0: return SECSuccess; michael@0: michael@0: } michael@0: michael@0: /* Caller should release or unmark the pool, instead of doing it here. michael@0: ** But there are NO callers of this function at present... michael@0: */ michael@0: SECStatus michael@0: CRMF_CertReqMsgSetRAVerifiedPOP(CRMFCertReqMsg *inCertReqMsg) michael@0: { michael@0: SECItem *dummy; michael@0: CRMFProofOfPossession *pop; michael@0: PLArenaPool *poolp; michael@0: void *mark; michael@0: michael@0: PORT_Assert(inCertReqMsg != NULL && inCertReqMsg->pop == NULL); michael@0: poolp = inCertReqMsg->poolp; michael@0: mark = PORT_ArenaMark(poolp); michael@0: if (CRMF_CertReqMsgGetPOPType(inCertReqMsg) != crmfNoPOPChoice) { michael@0: return SECFailure; michael@0: } michael@0: pop = PORT_ArenaZNew(poolp, CRMFProofOfPossession); michael@0: if (pop == NULL) { michael@0: goto loser; michael@0: } michael@0: pop->popUsed = crmfRAVerified; michael@0: pop->popChoice.raVerified.data = NULL; michael@0: pop->popChoice.raVerified.len = 0; michael@0: inCertReqMsg->pop = pop; michael@0: dummy = SEC_ASN1EncodeItem(poolp, &(inCertReqMsg->derPOP), michael@0: &(pop->popChoice.raVerified), michael@0: CRMFRAVerifiedTemplate); michael@0: return SECSuccess; michael@0: loser: michael@0: PORT_ArenaRelease(poolp, mark); michael@0: return SECFailure; michael@0: } michael@0: michael@0: static SECOidTag michael@0: crmf_get_key_sign_tag(SECKEYPublicKey *inPubKey) michael@0: { michael@0: /* maintain backward compatibility with older michael@0: * implementations */ michael@0: if (inPubKey->keyType == rsaKey) { michael@0: return SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; michael@0: } michael@0: return SEC_GetSignatureAlgorithmOidTag(inPubKey->keyType, SEC_OID_UNKNOWN); michael@0: } michael@0: michael@0: static SECAlgorithmID* michael@0: crmf_create_poposignkey_algid(PLArenaPool *poolp, michael@0: SECKEYPublicKey *inPubKey) michael@0: { michael@0: SECAlgorithmID *algID; michael@0: SECOidTag tag; michael@0: SECStatus rv; michael@0: void *mark; michael@0: michael@0: mark = PORT_ArenaMark(poolp); michael@0: algID = PORT_ArenaZNew(poolp, SECAlgorithmID); michael@0: if (algID == NULL) { michael@0: goto loser; michael@0: } michael@0: tag = crmf_get_key_sign_tag(inPubKey); michael@0: if (tag == SEC_OID_UNKNOWN) { michael@0: goto loser; michael@0: } michael@0: rv = SECOID_SetAlgorithmID(poolp, algID, tag, NULL); michael@0: if (rv != SECSuccess) { michael@0: goto loser; michael@0: } michael@0: PORT_ArenaUnmark(poolp, mark); michael@0: return algID; michael@0: loser: michael@0: PORT_ArenaRelease(poolp, mark); michael@0: return NULL; michael@0: } michael@0: michael@0: static CRMFPOPOSigningKeyInput* michael@0: crmf_create_poposigningkeyinput(PLArenaPool *poolp, CERTCertificate *inCert, michael@0: CRMFMACPasswordCallback fn, void *arg) michael@0: { michael@0: /* PSM isn't going to do this, so we'll fail here for now.*/ michael@0: return NULL; michael@0: } michael@0: michael@0: void michael@0: crmf_generic_encoder_callback(void *arg, const char* buf, unsigned long len, michael@0: int depth, SEC_ASN1EncodingPart data_kind) michael@0: { michael@0: struct crmfEncoderArg *encoderArg = (struct crmfEncoderArg*)arg; michael@0: unsigned char *cursor; michael@0: michael@0: if (encoderArg->buffer->len + len > encoderArg->allocatedLen) { michael@0: int newSize = encoderArg->buffer->len+CRMF_DEFAULT_ALLOC_SIZE; michael@0: void *dummy = PORT_Realloc(encoderArg->buffer->data, newSize); michael@0: if (dummy == NULL) { michael@0: /* I really want to return an error code here */ michael@0: PORT_Assert(0); michael@0: return; michael@0: } michael@0: encoderArg->buffer->data = dummy; michael@0: encoderArg->allocatedLen = newSize; michael@0: } michael@0: cursor = &(encoderArg->buffer->data[encoderArg->buffer->len]); michael@0: PORT_Memcpy (cursor, buf, len); michael@0: encoderArg->buffer->len += len; michael@0: } michael@0: michael@0: static SECStatus michael@0: crmf_encode_certreq(CRMFCertRequest *inCertReq, SECItem *derDest) michael@0: { michael@0: struct crmfEncoderArg encoderArg; michael@0: SECStatus rv; michael@0: michael@0: rv = crmf_init_encoder_callback_arg (&encoderArg, derDest); michael@0: if (rv != SECSuccess) { michael@0: return SECFailure; michael@0: } michael@0: return SEC_ASN1Encode(inCertReq, CRMFCertRequestTemplate, michael@0: crmf_generic_encoder_callback, &encoderArg); michael@0: } michael@0: michael@0: static SECStatus michael@0: crmf_sign_certreq(PLArenaPool *poolp, michael@0: CRMFPOPOSigningKey *crmfSignKey, michael@0: CRMFCertRequest *certReq, michael@0: SECKEYPrivateKey *inKey, michael@0: SECAlgorithmID *inAlgId) michael@0: { michael@0: SECItem derCertReq = { siBuffer, NULL, 0 }; michael@0: SECItem certReqSig = { siBuffer, NULL, 0 }; michael@0: SECStatus rv = SECSuccess; michael@0: michael@0: rv = crmf_encode_certreq(certReq, &derCertReq); michael@0: if (rv != SECSuccess) { michael@0: goto loser; michael@0: } michael@0: rv = SEC_SignData(&certReqSig, derCertReq.data, derCertReq.len, michael@0: inKey,SECOID_GetAlgorithmTag(inAlgId)); michael@0: if (rv != SECSuccess) { michael@0: goto loser; michael@0: } michael@0: michael@0: /* Now make it a part of the POPOSigningKey */ michael@0: rv = SECITEM_CopyItem(poolp, &(crmfSignKey->signature), &certReqSig); michael@0: /* Convert this length to number of bits */ michael@0: crmfSignKey->signature.len <<= 3; michael@0: michael@0: loser: michael@0: if (derCertReq.data != NULL) { michael@0: PORT_Free(derCertReq.data); michael@0: } michael@0: if (certReqSig.data != NULL) { michael@0: PORT_Free(certReqSig.data); michael@0: } michael@0: return rv; michael@0: } michael@0: michael@0: static SECStatus michael@0: crmf_create_poposignkey(PLArenaPool *poolp, michael@0: CRMFCertReqMsg *inCertReqMsg, michael@0: CRMFPOPOSigningKeyInput *signKeyInput, michael@0: SECKEYPrivateKey *inPrivKey, michael@0: SECAlgorithmID *inAlgID, michael@0: CRMFPOPOSigningKey *signKey) michael@0: { michael@0: CRMFCertRequest *certReq; michael@0: void *mark; michael@0: PRBool useSignKeyInput; michael@0: SECStatus rv; michael@0: michael@0: PORT_Assert(inCertReqMsg != NULL && inCertReqMsg->certReq != NULL); michael@0: mark = PORT_ArenaMark(poolp); michael@0: if (signKey == NULL) { michael@0: goto loser; michael@0: } michael@0: certReq = inCertReqMsg->certReq; michael@0: useSignKeyInput = !(CRMF_DoesRequestHaveField(certReq,crmfSubject) && michael@0: CRMF_DoesRequestHaveField(certReq,crmfPublicKey)); michael@0: michael@0: if (useSignKeyInput) { michael@0: goto loser; michael@0: } else { michael@0: rv = crmf_sign_certreq(poolp, signKey, certReq,inPrivKey, inAlgID); michael@0: if (rv != SECSuccess) { michael@0: goto loser; michael@0: } michael@0: } michael@0: PORT_ArenaUnmark(poolp,mark); michael@0: return SECSuccess; michael@0: loser: michael@0: PORT_ArenaRelease(poolp,mark); michael@0: return SECFailure; michael@0: } michael@0: michael@0: SECStatus michael@0: CRMF_CertReqMsgSetSignaturePOP(CRMFCertReqMsg *inCertReqMsg, michael@0: SECKEYPrivateKey *inPrivKey, michael@0: SECKEYPublicKey *inPubKey, michael@0: CERTCertificate *inCertForInput, michael@0: CRMFMACPasswordCallback fn, michael@0: void *arg) michael@0: { michael@0: SECAlgorithmID *algID; michael@0: PLArenaPool *poolp; michael@0: SECItem derTemp = {siBuffer, NULL, 0}; michael@0: void *mark; michael@0: SECStatus rv; michael@0: CRMFPOPOSigningKeyInput *signKeyInput = NULL; michael@0: CRMFCertRequest *certReq; michael@0: CRMFProofOfPossession *pop; michael@0: struct crmfEncoderArg encoderArg; michael@0: michael@0: PORT_Assert(inCertReqMsg != NULL && inCertReqMsg->certReq != NULL && michael@0: inCertReqMsg->pop == NULL); michael@0: certReq = inCertReqMsg->certReq; michael@0: if (CRMF_CertReqMsgGetPOPType(inCertReqMsg) != crmfNoPOPChoice || michael@0: !CRMF_DoesRequestHaveField(certReq, crmfPublicKey)) { michael@0: return SECFailure; michael@0: } michael@0: poolp = inCertReqMsg->poolp; michael@0: mark = PORT_ArenaMark(poolp); michael@0: algID = crmf_create_poposignkey_algid(poolp, inPubKey); michael@0: michael@0: if(!CRMF_DoesRequestHaveField(certReq,crmfSubject)) { michael@0: signKeyInput = crmf_create_poposigningkeyinput(poolp, inCertForInput, michael@0: fn, arg); michael@0: if (signKeyInput == NULL) { michael@0: goto loser; michael@0: } michael@0: } michael@0: michael@0: pop = PORT_ArenaZNew(poolp, CRMFProofOfPossession); michael@0: if (pop == NULL) { michael@0: goto loser; michael@0: } michael@0: michael@0: rv = crmf_create_poposignkey(poolp, inCertReqMsg, michael@0: signKeyInput, inPrivKey, algID, michael@0: &(pop->popChoice.signature)); michael@0: if (rv != SECSuccess) { michael@0: goto loser; michael@0: } michael@0: michael@0: pop->popUsed = crmfSignature; michael@0: pop->popChoice.signature.algorithmIdentifier = algID; michael@0: inCertReqMsg->pop = pop; michael@0: michael@0: rv = crmf_init_encoder_callback_arg (&encoderArg, &derTemp); michael@0: if (rv != SECSuccess) { michael@0: goto loser; michael@0: } michael@0: rv = SEC_ASN1Encode(&pop->popChoice.signature, michael@0: CRMFPOPOSigningKeyTemplate, michael@0: crmf_generic_encoder_callback, &encoderArg); michael@0: if (rv != SECSuccess) { michael@0: goto loser; michael@0: } michael@0: rv = SECITEM_CopyItem(poolp, &(inCertReqMsg->derPOP), &derTemp); michael@0: if (rv != SECSuccess) { michael@0: goto loser; michael@0: } michael@0: PORT_Free (derTemp.data); michael@0: PORT_ArenaUnmark(poolp,mark); michael@0: return SECSuccess; michael@0: michael@0: loser: michael@0: PORT_ArenaRelease(poolp,mark); michael@0: if (derTemp.data != NULL) { michael@0: PORT_Free(derTemp.data); michael@0: } michael@0: return SECFailure; michael@0: } michael@0: michael@0: static const SEC_ASN1Template* michael@0: crmf_get_popoprivkey_subtemplate(CRMFPOPOPrivKey *inPrivKey) michael@0: { michael@0: const SEC_ASN1Template *retTemplate = NULL; michael@0: michael@0: switch (inPrivKey->messageChoice) { michael@0: case crmfThisMessage: michael@0: retTemplate = CRMFThisMessageTemplate; michael@0: break; michael@0: case crmfSubsequentMessage: michael@0: retTemplate = CRMFSubsequentMessageTemplate; michael@0: break; michael@0: case crmfDHMAC: michael@0: retTemplate = CRMFDHMACTemplate; michael@0: break; michael@0: default: michael@0: retTemplate = NULL; michael@0: } michael@0: return retTemplate; michael@0: } michael@0: michael@0: static SECStatus michael@0: crmf_encode_popoprivkey(PLArenaPool *poolp, michael@0: CRMFCertReqMsg *inCertReqMsg, michael@0: CRMFPOPOPrivKey *popoPrivKey, michael@0: const SEC_ASN1Template *privKeyTemplate) michael@0: { michael@0: struct crmfEncoderArg encoderArg; michael@0: SECItem derTemp = { siBuffer, NULL, 0 }; michael@0: SECStatus rv; michael@0: void *mark; michael@0: const SEC_ASN1Template *subDerTemplate; michael@0: michael@0: mark = PORT_ArenaMark(poolp); michael@0: rv = crmf_init_encoder_callback_arg(&encoderArg, &derTemp); michael@0: if (rv != SECSuccess) { michael@0: goto loser; michael@0: } michael@0: subDerTemplate = crmf_get_popoprivkey_subtemplate(popoPrivKey); michael@0: /* We've got a union, so a pointer to one item is a pointer to michael@0: * all the items in the union. michael@0: */ michael@0: rv = SEC_ASN1Encode(&popoPrivKey->message.thisMessage, michael@0: subDerTemplate, michael@0: crmf_generic_encoder_callback, &encoderArg); michael@0: if (rv != SECSuccess) { michael@0: goto loser; michael@0: } michael@0: if (encoderArg.allocatedLen > derTemp.len+2) { michael@0: void *dummy = PORT_Realloc(derTemp.data, derTemp.len+2); michael@0: if (dummy == NULL) { michael@0: goto loser; michael@0: } michael@0: derTemp.data = dummy; michael@0: } michael@0: PORT_Memmove(&derTemp.data[2], &derTemp.data[0], derTemp.len); michael@0: /* I couldn't figure out how to get the ASN1 encoder to implicitly michael@0: * tag an implicitly tagged der blob. So I'm putting in the outter- michael@0: * most tag myself. -javi michael@0: */ michael@0: derTemp.data[0] = (unsigned char)privKeyTemplate->kind; michael@0: derTemp.data[1] = (unsigned char)derTemp.len; michael@0: derTemp.len += 2; michael@0: rv = SECITEM_CopyItem(poolp, &inCertReqMsg->derPOP, &derTemp); michael@0: if (rv != SECSuccess) { michael@0: goto loser; michael@0: } michael@0: PORT_Free(derTemp.data); michael@0: PORT_ArenaUnmark(poolp, mark); michael@0: return SECSuccess; michael@0: loser: michael@0: PORT_ArenaRelease(poolp, mark); michael@0: if (derTemp.data) { michael@0: PORT_Free(derTemp.data); michael@0: } michael@0: return SECFailure; michael@0: } michael@0: michael@0: static const SEC_ASN1Template* michael@0: crmf_get_template_for_privkey(CRMFPOPChoice inChoice) michael@0: { michael@0: switch (inChoice) { michael@0: case crmfKeyAgreement: michael@0: return CRMFPOPOKeyAgreementTemplate; michael@0: case crmfKeyEncipherment: michael@0: return CRMFPOPOKeyEnciphermentTemplate; michael@0: default: michael@0: break; michael@0: } michael@0: return NULL; michael@0: } michael@0: michael@0: static SECStatus michael@0: crmf_add_privkey_thismessage(CRMFCertReqMsg *inCertReqMsg, SECItem *encPrivKey, michael@0: CRMFPOPChoice inChoice) michael@0: { michael@0: PLArenaPool *poolp; michael@0: void *mark; michael@0: CRMFPOPOPrivKey *popoPrivKey; michael@0: CRMFProofOfPossession *pop; michael@0: SECStatus rv; michael@0: michael@0: PORT_Assert(inCertReqMsg != NULL && encPrivKey != NULL); michael@0: poolp = inCertReqMsg->poolp; michael@0: mark = PORT_ArenaMark(poolp); michael@0: pop = PORT_ArenaZNew(poolp, CRMFProofOfPossession); michael@0: if (pop == NULL) { michael@0: goto loser; michael@0: } michael@0: pop->popUsed = inChoice; michael@0: /* popChoice is a union, so getting a pointer to one michael@0: * field gives me a pointer to the other fields as michael@0: * well. This in essence points to both michael@0: * pop->popChoice.keyEncipherment and michael@0: * pop->popChoice.keyAgreement michael@0: */ michael@0: popoPrivKey = &pop->popChoice.keyEncipherment; michael@0: michael@0: rv = SECITEM_CopyItem(poolp, &(popoPrivKey->message.thisMessage), michael@0: encPrivKey); michael@0: if (rv != SECSuccess) { michael@0: goto loser; michael@0: } michael@0: popoPrivKey->message.thisMessage.len <<= 3; michael@0: popoPrivKey->messageChoice = crmfThisMessage; michael@0: inCertReqMsg->pop = pop; michael@0: rv = crmf_encode_popoprivkey(poolp, inCertReqMsg, popoPrivKey, michael@0: crmf_get_template_for_privkey(inChoice)); michael@0: if (rv != SECSuccess) { michael@0: goto loser; michael@0: } michael@0: PORT_ArenaUnmark(poolp, mark); michael@0: return SECSuccess; michael@0: michael@0: loser: michael@0: PORT_ArenaRelease(poolp, mark); michael@0: return SECFailure; michael@0: } michael@0: michael@0: static SECStatus michael@0: crmf_add_privkey_dhmac(CRMFCertReqMsg *inCertReqMsg, SECItem *dhmac, michael@0: CRMFPOPChoice inChoice) michael@0: { michael@0: PLArenaPool *poolp; michael@0: void *mark; michael@0: CRMFPOPOPrivKey *popoPrivKey; michael@0: CRMFProofOfPossession *pop; michael@0: SECStatus rv; michael@0: michael@0: PORT_Assert(inCertReqMsg != NULL && dhmac != NULL); michael@0: poolp = inCertReqMsg->poolp; michael@0: mark = PORT_ArenaMark(poolp); michael@0: pop = PORT_ArenaZNew(poolp, CRMFProofOfPossession); michael@0: if (pop == NULL) { michael@0: goto loser; michael@0: } michael@0: pop->popUsed = inChoice; michael@0: popoPrivKey = &pop->popChoice.keyAgreement; michael@0: michael@0: rv = SECITEM_CopyItem(poolp, &(popoPrivKey->message.dhMAC), michael@0: dhmac); michael@0: if (rv != SECSuccess) { michael@0: goto loser; michael@0: } michael@0: popoPrivKey->message.dhMAC.len <<= 3; michael@0: popoPrivKey->messageChoice = crmfDHMAC; michael@0: inCertReqMsg->pop = pop; michael@0: rv = crmf_encode_popoprivkey(poolp, inCertReqMsg, popoPrivKey, michael@0: crmf_get_template_for_privkey(inChoice)); michael@0: if (rv != SECSuccess) { michael@0: goto loser; michael@0: } michael@0: PORT_ArenaUnmark(poolp, mark); michael@0: return SECSuccess; michael@0: michael@0: loser: michael@0: PORT_ArenaRelease(poolp, mark); michael@0: return SECFailure; michael@0: } michael@0: michael@0: static SECStatus michael@0: crmf_add_privkey_subseqmessage(CRMFCertReqMsg *inCertReqMsg, michael@0: CRMFSubseqMessOptions subsequentMessage, michael@0: CRMFPOPChoice inChoice) michael@0: { michael@0: void *mark; michael@0: PLArenaPool *poolp; michael@0: CRMFProofOfPossession *pop; michael@0: CRMFPOPOPrivKey *popoPrivKey; michael@0: SECStatus rv; michael@0: const SEC_ASN1Template *privKeyTemplate; michael@0: michael@0: if (subsequentMessage == crmfNoSubseqMess) { michael@0: return SECFailure; michael@0: } michael@0: poolp = inCertReqMsg->poolp; michael@0: mark = PORT_ArenaMark(poolp); michael@0: pop = PORT_ArenaZNew(poolp, CRMFProofOfPossession); michael@0: if (pop == NULL) { michael@0: goto loser; michael@0: } michael@0: michael@0: pop->popUsed = inChoice; michael@0: /* michael@0: * We have a union, so a pointer to one member of the union michael@0: * is also a member to another member of that same union. michael@0: */ michael@0: popoPrivKey = &pop->popChoice.keyEncipherment; michael@0: michael@0: switch (subsequentMessage) { michael@0: case crmfEncrCert: michael@0: rv = crmf_encode_integer(poolp, michael@0: &(popoPrivKey->message.subsequentMessage), michael@0: 0); michael@0: break; michael@0: case crmfChallengeResp: michael@0: rv = crmf_encode_integer(poolp, michael@0: &(popoPrivKey->message.subsequentMessage), michael@0: 1); michael@0: break; michael@0: default: michael@0: goto loser; michael@0: } michael@0: if (rv != SECSuccess) { michael@0: goto loser; michael@0: } michael@0: popoPrivKey->messageChoice = crmfSubsequentMessage; michael@0: privKeyTemplate = crmf_get_template_for_privkey(inChoice); michael@0: inCertReqMsg->pop = pop; michael@0: rv = crmf_encode_popoprivkey(poolp, inCertReqMsg, popoPrivKey, michael@0: privKeyTemplate); michael@0: michael@0: if (rv != SECSuccess) { michael@0: goto loser; michael@0: } michael@0: PORT_ArenaUnmark(poolp, mark); michael@0: return SECSuccess; michael@0: loser: michael@0: PORT_ArenaRelease(poolp, mark); michael@0: return SECFailure; michael@0: } michael@0: michael@0: SECStatus michael@0: CRMF_CertReqMsgSetKeyEnciphermentPOP(CRMFCertReqMsg *inCertReqMsg, michael@0: CRMFPOPOPrivKeyChoice inKeyChoice, michael@0: CRMFSubseqMessOptions subseqMess, michael@0: SECItem *encPrivKey) michael@0: { michael@0: SECStatus rv; michael@0: michael@0: PORT_Assert(inCertReqMsg != NULL && inCertReqMsg->pop == NULL); michael@0: if (CRMF_CertReqMsgGetPOPType(inCertReqMsg) != crmfNoPOPChoice) { michael@0: return SECFailure; michael@0: } michael@0: switch (inKeyChoice) { michael@0: case crmfThisMessage: michael@0: rv = crmf_add_privkey_thismessage(inCertReqMsg, encPrivKey, michael@0: crmfKeyEncipherment); michael@0: break; michael@0: case crmfSubsequentMessage: michael@0: rv = crmf_add_privkey_subseqmessage(inCertReqMsg, subseqMess, michael@0: crmfKeyEncipherment); michael@0: break; michael@0: case crmfDHMAC: michael@0: default: michael@0: rv = SECFailure; michael@0: } michael@0: return rv; michael@0: } michael@0: michael@0: SECStatus michael@0: CRMF_CertReqMsgSetKeyAgreementPOP (CRMFCertReqMsg *inCertReqMsg, michael@0: CRMFPOPOPrivKeyChoice inKeyChoice, michael@0: CRMFSubseqMessOptions subseqMess, michael@0: SECItem *encPrivKey) michael@0: { michael@0: SECStatus rv; michael@0: michael@0: PORT_Assert(inCertReqMsg != NULL && inCertReqMsg->pop == NULL); michael@0: switch (inKeyChoice) { michael@0: case crmfThisMessage: michael@0: rv = crmf_add_privkey_thismessage(inCertReqMsg, encPrivKey, michael@0: crmfKeyAgreement); michael@0: break; michael@0: case crmfSubsequentMessage: michael@0: rv = crmf_add_privkey_subseqmessage(inCertReqMsg, subseqMess, michael@0: crmfKeyAgreement); michael@0: break; michael@0: case crmfDHMAC: michael@0: /* In this case encPrivKey should be the calculated dhMac michael@0: * as specified in RFC 2511 */ michael@0: rv = crmf_add_privkey_dhmac(inCertReqMsg, encPrivKey, michael@0: crmfKeyAgreement); michael@0: break; michael@0: default: michael@0: rv = SECFailure; michael@0: } michael@0: return rv; michael@0: } michael@0: