crmfpop.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:17k
源码类别:

CA认证

开发平台:

WINDOWS

  1. /* -*- Mode: C; tab-width: 8 -*-*/
  2. /*
  3.  * The contents of this file are subject to the Mozilla Public
  4.  * License Version 1.1 (the "License"); you may not use this file
  5.  * except in compliance with the License. You may obtain a copy of
  6.  * the License at http://www.mozilla.org/MPL/
  7.  * 
  8.  * Software distributed under the License is distributed on an "AS
  9.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  10.  * implied. See the License for the specific language governing
  11.  * rights and limitations under the License.
  12.  * 
  13.  * The Original Code is the Netscape security libraries.
  14.  * 
  15.  * The Initial Developer of the Original Code is Netscape
  16.  * Communications Corporation.  Portions created by Netscape are 
  17.  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
  18.  * Rights Reserved.
  19.  * 
  20.  * Contributor(s):
  21.  * 
  22.  * Alternatively, the contents of this file may be used under the
  23.  * terms of the GNU General Public License Version 2 or later (the
  24.  * "GPL"), in which case the provisions of the GPL are applicable 
  25.  * instead of those above.  If you wish to allow use of your 
  26.  * version of this file only under the terms of the GPL and not to
  27.  * allow others to use your version of this file under the MPL,
  28.  * indicate your decision by deleting the provisions above and
  29.  * replace them with the notice and other provisions required by
  30.  * the GPL.  If you do not delete the provisions above, a recipient
  31.  * may use your version of this file under either the MPL or the
  32.  * GPL.
  33.  */
  34. #include "crmf.h"
  35. #include "crmfi.h"
  36. #include "secasn1.h"
  37. #include "keyhi.h"
  38. #include "cryptohi.h"
  39. #define CRMF_DEFAULT_ALLOC_SIZE 1024
  40. SECStatus
  41. crmf_init_encoder_callback_arg (struct crmfEncoderArg *encoderArg, 
  42. SECItem               *derDest) 
  43. {
  44.     derDest->data = PORT_ZNewArray(unsigned char, CRMF_DEFAULT_ALLOC_SIZE);
  45.     if (derDest->data == NULL) {
  46.         return SECFailure;
  47.     }
  48.     derDest->len = 0;
  49.     encoderArg->allocatedLen = CRMF_DEFAULT_ALLOC_SIZE;
  50.     encoderArg->buffer = derDest;
  51.     return SECSuccess;
  52. }
  53. /* Caller should release or unmark the pool, instead of doing it here.
  54. ** But there are NO callers of this function at present...
  55. */
  56. SECStatus 
  57. CRMF_CertReqMsgSetRAVerifiedPOP(CRMFCertReqMsg *inCertReqMsg)
  58. {
  59.     SECItem               *dummy;
  60.     CRMFProofOfPossession *pop;
  61.     PRArenaPool           *poolp;
  62.     void                  *mark;
  63.     PORT_Assert(inCertReqMsg != NULL && inCertReqMsg->pop == NULL);
  64.     poolp = inCertReqMsg->poolp;
  65.     mark = PORT_ArenaMark(poolp);
  66.     if (CRMF_CertReqMsgGetPOPType(inCertReqMsg) != crmfNoPOPChoice) {
  67.         return SECFailure;
  68.     }
  69.     pop = PORT_ArenaZNew(poolp, CRMFProofOfPossession);
  70.     if (pop == NULL) {
  71.         goto loser;
  72.     }
  73.     pop->popUsed = crmfRAVerified;
  74.     pop->popChoice.raVerified.data = NULL;
  75.     pop->popChoice.raVerified.len  = 0;
  76.     inCertReqMsg->pop = pop;
  77.     dummy = SEC_ASN1EncodeItem(poolp, &(inCertReqMsg->derPOP),
  78.        &(pop->popChoice.raVerified),
  79.        CRMFRAVerifiedTemplate);
  80.     return SECSuccess;
  81.  loser:
  82.     PORT_ArenaRelease(poolp, mark);
  83.     return SECFailure;
  84. }
  85. SECOidTag
  86. crmf_map_keytag_to_signtag(SECOidTag inTag)
  87. {
  88.     switch (inTag) {
  89.     case SEC_OID_PKCS1_RSA_ENCRYPTION:
  90.         return SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
  91.     case SEC_OID_ANSIX9_DSA_SIGNATURE:
  92.     case SEC_OID_MISSI_KEA_DSS:
  93.     case SEC_OID_MISSI_DSS:
  94.         return SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
  95.     default:
  96.         /* Put this in here to kill warnings. */
  97.         break;
  98.     }
  99.     return inTag;
  100. }
  101. SECOidTag
  102. crmf_get_key_sign_tag(SECKEYPublicKey *inPubKey)
  103. {
  104.     CERTSubjectPublicKeyInfo *spki;
  105.     SECOidTag                 tag;
  106.     spki = SECKEY_CreateSubjectPublicKeyInfo(inPubKey);
  107.     if (spki == NULL) {
  108.         return SEC_OID_UNKNOWN;
  109.     }
  110.     tag = SECOID_GetAlgorithmTag(&spki->algorithm);
  111.     SECKEY_DestroySubjectPublicKeyInfo(spki);
  112.     return crmf_map_keytag_to_signtag(tag);
  113. }
  114. SECAlgorithmID*
  115. crmf_create_poposignkey_algid(PRArenaPool      *poolp,
  116.       SECKEYPublicKey  *inPubKey)
  117. {
  118.     SECAlgorithmID *algID;
  119.     SECOidTag       tag;
  120.     SECStatus       rv;
  121.     void           *mark;
  122.     mark = PORT_ArenaMark(poolp);
  123.     algID = PORT_ArenaZNew(poolp, SECAlgorithmID);
  124.     if (algID == NULL) {
  125.         goto loser;
  126.     }
  127.     tag = crmf_get_key_sign_tag(inPubKey);
  128.     if (tag == SEC_OID_UNKNOWN) {
  129.         goto loser;
  130.     }
  131.     rv = SECOID_SetAlgorithmID(poolp, algID, tag, NULL);
  132.     if (rv != SECSuccess) {
  133.         goto loser;
  134.     }
  135.     PORT_ArenaUnmark(poolp, mark);
  136.     return algID;
  137.  loser:
  138.     PORT_ArenaRelease(poolp, mark);
  139.     return NULL;
  140. }
  141. static CRMFPOPOSigningKeyInput*
  142. crmf_create_poposigningkeyinput(PRArenaPool *poolp, CERTCertificate *inCert,
  143. CRMFMACPasswordCallback fn, void *arg)
  144. {
  145.   /* PSM isn't going to do this, so we'll fail here for now.*/
  146.      return NULL;
  147. }
  148. void
  149. crmf_generic_encoder_callback(void *arg, const char* buf, unsigned long len,
  150.       int depth, SEC_ASN1EncodingPart data_kind)
  151. {
  152.     struct crmfEncoderArg *encoderArg = (struct crmfEncoderArg*)arg;
  153.     unsigned char *cursor;
  154.     
  155.    if (encoderArg->buffer->len + len > encoderArg->allocatedLen) {
  156.         int newSize = encoderArg->buffer->len+CRMF_DEFAULT_ALLOC_SIZE;
  157.         void *dummy = PORT_Realloc(encoderArg->buffer->data, newSize);
  158. if (dummy == NULL) {
  159.     /* I really want to return an error code here */
  160.     PORT_Assert(0);
  161.     return;
  162. }
  163. encoderArg->buffer->data = dummy;
  164. encoderArg->allocatedLen = newSize;
  165.     }
  166.     cursor = &(encoderArg->buffer->data[encoderArg->buffer->len]);
  167.     PORT_Memcpy (cursor, buf, len);
  168.     encoderArg->buffer->len += len;    
  169. }
  170. static SECStatus
  171. crmf_encode_certreq(CRMFCertRequest *inCertReq, SECItem *derDest)
  172. {
  173.     struct crmfEncoderArg encoderArg;
  174.     SECStatus             rv;
  175.   
  176.     rv = crmf_init_encoder_callback_arg (&encoderArg, derDest);
  177.     if (rv != SECSuccess) {
  178.         return SECFailure;
  179.     }
  180.     return SEC_ASN1Encode(inCertReq, CRMFCertRequestTemplate, 
  181.   crmf_generic_encoder_callback, &encoderArg);
  182. }
  183. static SECStatus
  184. crmf_sign_certreq(PRArenaPool        *poolp, 
  185.   CRMFPOPOSigningKey *crmfSignKey, 
  186.   CRMFCertRequest    *certReq,
  187.   SECKEYPrivateKey   *inKey,
  188.   SECAlgorithmID     *inAlgId)
  189. {
  190.     SECItem                      derCertReq;
  191.     SECItem                      certReqSig;
  192.     SECStatus                    rv = SECSuccess;
  193.     rv = crmf_encode_certreq(certReq, &derCertReq);
  194.     if (rv != SECSuccess) {
  195.        goto loser;
  196.     }
  197.     rv = SEC_SignData(&certReqSig, derCertReq.data, derCertReq.len,
  198.       inKey,SECOID_GetAlgorithmTag(inAlgId));
  199.     if (rv != SECSuccess) {
  200.         goto loser;
  201.     }
  202.  
  203.     /* Now make it a part of the POPOSigningKey */
  204.     rv = SECITEM_CopyItem(poolp, &(crmfSignKey->signature), &certReqSig);
  205.     /* Convert this length to number of bits */
  206.     crmfSignKey->signature.len <<= 3; 
  207.    
  208.  loser:
  209.     if (derCertReq.data != NULL) {
  210.         PORT_Free(derCertReq.data);
  211.     }
  212.     if (certReqSig.data != NULL) {
  213.         PORT_Free(certReqSig.data);
  214.     }
  215.     return rv;
  216. }
  217. static SECStatus
  218. crmf_create_poposignkey(PRArenaPool             *poolp, 
  219. CRMFCertReqMsg          *inCertReqMsg, 
  220. CRMFPOPOSigningKeyInput *signKeyInput, 
  221. SECKEYPrivateKey        *inPrivKey,
  222. SECAlgorithmID          *inAlgID,
  223. CRMFPOPOSigningKey      *signKey) 
  224. {
  225.     CRMFCertRequest    *certReq;
  226.     void               *mark;
  227.     PRBool              useSignKeyInput;
  228.     SECStatus           rv;
  229.     
  230.     PORT_Assert(inCertReqMsg != NULL && inCertReqMsg->certReq != NULL);
  231.     mark = PORT_ArenaMark(poolp);
  232.     if (signKey == NULL) {
  233.         goto loser;
  234.     }
  235.     certReq = inCertReqMsg->certReq;
  236.     useSignKeyInput = !(CRMF_DoesRequestHaveField(certReq,crmfSubject)  &&
  237. CRMF_DoesRequestHaveField(certReq,crmfPublicKey));
  238.     if (useSignKeyInput) {
  239.         goto loser; 
  240.     } else {
  241.         rv = crmf_sign_certreq(poolp, signKey, certReq,inPrivKey, inAlgID);
  242. if (rv != SECSuccess) {
  243.     goto loser;
  244. }
  245.     }
  246.     PORT_ArenaUnmark(poolp,mark);
  247.     return SECSuccess;
  248.  loser:
  249.     PORT_ArenaRelease(poolp,mark);
  250.     return SECFailure;
  251. }
  252. SECStatus
  253. CRMF_CertReqMsgSetSignaturePOP(CRMFCertReqMsg   *inCertReqMsg,
  254.        SECKEYPrivateKey *inPrivKey,
  255.        SECKEYPublicKey  *inPubKey,
  256.        CERTCertificate  *inCertForInput,
  257.        CRMFMACPasswordCallback  fn,
  258.        void                    *arg)
  259. {
  260.     SECAlgorithmID  *algID;
  261.     PRArenaPool     *poolp;
  262.     SECItem          derDest = {siBuffer, NULL, 0};
  263.     void            *mark;
  264.     SECStatus        rv;
  265.     CRMFPOPOSigningKeyInput *signKeyInput = NULL;
  266.     CRMFCertRequest         *certReq;
  267.     CRMFProofOfPossession   *pop;
  268.     struct crmfEncoderArg    encoderArg;
  269.     PORT_Assert(inCertReqMsg != NULL && inCertReqMsg->certReq != NULL &&
  270. inCertReqMsg->pop == NULL);
  271.     certReq = inCertReqMsg->certReq;
  272.     if (CRMF_CertReqMsgGetPOPType(inCertReqMsg) != crmfNoPOPChoice || 
  273. !CRMF_DoesRequestHaveField(certReq, crmfPublicKey)) {
  274.         return SECFailure;
  275.     } 
  276.     poolp = inCertReqMsg->poolp;
  277.     mark = PORT_ArenaMark(poolp);
  278.     algID = crmf_create_poposignkey_algid(poolp, inPubKey);
  279.     if(!CRMF_DoesRequestHaveField(certReq,crmfSubject)) {
  280.         signKeyInput = crmf_create_poposigningkeyinput(poolp, inCertForInput,
  281.        fn, arg);
  282. if (signKeyInput == NULL) {
  283.     goto loser;
  284. }
  285.     }
  286.     pop = PORT_ArenaZNew(poolp, CRMFProofOfPossession);
  287.     if (pop == NULL) {
  288.         goto loser;
  289.     }
  290.     
  291.     rv = crmf_create_poposignkey(poolp, inCertReqMsg, 
  292.  signKeyInput, inPrivKey, algID,
  293.  &(pop->popChoice.signature));
  294.     if (rv != SECSuccess) {
  295.         goto loser;
  296.     }
  297.     pop->popUsed = crmfSignature;
  298.     pop->popChoice.signature.algorithmIdentifier = algID;
  299.     inCertReqMsg->pop = pop;
  300.   
  301.     rv = crmf_init_encoder_callback_arg (&encoderArg, &derDest);
  302.     if (rv != SECSuccess) {
  303.         goto loser;
  304.     }
  305.     rv = SEC_ASN1Encode(&pop->popChoice.signature, 
  306. CRMFPOPOSigningKeyTemplate,
  307. crmf_generic_encoder_callback, &encoderArg);
  308.     if (rv != SECSuccess) {
  309.         goto loser;
  310.     }
  311.     rv = SECITEM_CopyItem(poolp, &(inCertReqMsg->derPOP), &derDest);
  312.     PORT_Free (derDest.data);
  313.     if (rv != SECSuccess) {
  314.         goto loser;
  315.     }
  316.     PORT_ArenaUnmark(poolp,mark);
  317.     return SECSuccess;
  318.  loser:
  319.     PORT_ArenaRelease(poolp,mark);
  320.     if (derDest.data != NULL) {
  321.         PORT_Free(derDest.data);
  322.     }
  323.     return SECFailure;
  324. }
  325. static const SEC_ASN1Template*
  326. crmf_get_popoprivkey_subtemplate(CRMFPOPOPrivKey *inPrivKey) 
  327. {
  328.     const SEC_ASN1Template *retTemplate = NULL;
  329.     switch (inPrivKey->messageChoice) {
  330.     case crmfThisMessage:
  331.         retTemplate = CRMFThisMessageTemplate;
  332. break;
  333.     case crmfSubsequentMessage:
  334.         retTemplate = CRMFSubsequentMessageTemplate;
  335. break;
  336.     case crmfDHMAC:
  337.         retTemplate = CRMFDHMACTemplate;
  338. break;
  339.     default:
  340.         retTemplate = NULL;
  341.     }
  342.     return retTemplate;
  343. }
  344. static SECStatus
  345. crmf_encode_popoprivkey(PRArenaPool            *poolp, 
  346. CRMFCertReqMsg         *inCertReqMsg,
  347. CRMFPOPOPrivKey        *popoPrivKey,
  348. const SEC_ASN1Template *privKeyTemplate)
  349. {
  350.     struct crmfEncoderArg   encoderArg;
  351.     SECItem                 derDest; 
  352.     SECStatus               rv;
  353.     void                   *mark;
  354.     const SEC_ASN1Template *subDerTemplate;
  355.     mark = PORT_ArenaMark(poolp);
  356.     rv = crmf_init_encoder_callback_arg(&encoderArg, &derDest);
  357.     if (rv != SECSuccess) {
  358.         goto loser;
  359.     }
  360.     subDerTemplate = crmf_get_popoprivkey_subtemplate(popoPrivKey);
  361.     /* We've got a union, so a pointer to one item is a pointer to 
  362.      * all the items in the union.
  363.      */
  364.     rv = SEC_ASN1Encode(&popoPrivKey->message.thisMessage, 
  365. subDerTemplate,
  366. crmf_generic_encoder_callback, &encoderArg);
  367.     if (rv != SECSuccess) {
  368.         goto loser;
  369.     }
  370.     if (encoderArg.allocatedLen > derDest.len+2) {
  371.         void *dummy = PORT_Realloc(derDest.data, derDest.len+2);
  372. if (dummy == NULL) {
  373.     goto loser;
  374. }
  375. derDest.data = dummy;
  376.     }
  377.     PORT_Memmove(&derDest.data[2], &derDest.data[0], derDest.len);
  378.     /* I couldn't figure out how to get the ASN1 encoder to implicitly
  379.      * tag an implicitly tagged der blob.  So I'm putting in the outter-
  380.      * most tag myself. -javi
  381.      */
  382.     derDest.data[0] = (unsigned char)privKeyTemplate->kind;
  383.     derDest.data[1] = (unsigned char)derDest.len;
  384.     derDest.len += 2;
  385.     rv = SECITEM_CopyItem(poolp, &inCertReqMsg->derPOP, &derDest);
  386.     if (rv != SECSuccess) {
  387.         goto loser;
  388.     }
  389.     PORT_Free(derDest.data);
  390.     PORT_ArenaUnmark(poolp, mark);
  391.     return SECSuccess;
  392.  loser:
  393.     PORT_ArenaRelease(poolp, mark);
  394.     if (derDest.data) {
  395.         PORT_Free(derDest.data);
  396.     }
  397.     return SECFailure;
  398. }
  399. static const SEC_ASN1Template*
  400. crmf_get_template_for_privkey(CRMFPOPChoice inChoice) 
  401. {
  402.     switch (inChoice) {
  403.     case crmfKeyAgreement:
  404.         return CRMFPOPOKeyAgreementTemplate;
  405.     case crmfKeyEncipherment:
  406.         return CRMFPOPOKeyEnciphermentTemplate;
  407.     default:
  408.         break;
  409.     }
  410.     return NULL;
  411. }
  412. static SECStatus
  413. crmf_add_privkey_thismessage(CRMFCertReqMsg *inCertReqMsg, SECItem *encPrivKey,
  414.      CRMFPOPChoice inChoice)
  415. {
  416.     PRArenaPool           *poolp;
  417.     void                  *mark;
  418.     CRMFPOPOPrivKey       *popoPrivKey;
  419.     CRMFProofOfPossession *pop;
  420.     SECStatus              rv;
  421.     PORT_Assert(inCertReqMsg != NULL && encPrivKey != NULL);
  422.     poolp = inCertReqMsg->poolp;
  423.     mark = PORT_ArenaMark(poolp);
  424.     pop = PORT_ArenaZNew(poolp, CRMFProofOfPossession);
  425.     if (pop == NULL) {
  426.         goto loser;
  427.     }
  428.     pop->popUsed = inChoice;
  429.     /* popChoice is a union, so getting a pointer to one
  430.      * field gives me a pointer to the other fields as
  431.      * well.  This in essence points to both 
  432.      * pop->popChoice.keyEncipherment and
  433.      * pop->popChoice.keyAgreement
  434.      */
  435.     popoPrivKey = &pop->popChoice.keyEncipherment;
  436.     rv = SECITEM_CopyItem(poolp, &(popoPrivKey->message.thisMessage),
  437.   encPrivKey);
  438.     if (rv != SECSuccess) {
  439.         goto loser;
  440.     }
  441.     popoPrivKey->message.thisMessage.len <<= 3;
  442.     popoPrivKey->messageChoice = crmfThisMessage;
  443.     inCertReqMsg->pop = pop;
  444.     rv = crmf_encode_popoprivkey(poolp, inCertReqMsg, popoPrivKey,
  445.  crmf_get_template_for_privkey(inChoice));
  446.     if (rv != SECSuccess) {
  447.         goto loser;
  448.     }
  449.     PORT_ArenaUnmark(poolp, mark);
  450.     return SECSuccess;
  451.     
  452.  loser:
  453.     PORT_ArenaRelease(poolp, mark);
  454.     return SECFailure;
  455. }
  456. static SECStatus
  457. crmf_add_privkey_subseqmessage(CRMFCertReqMsg        *inCertReqMsg,
  458.        CRMFSubseqMessOptions  subsequentMessage,
  459.        CRMFPOPChoice          inChoice)
  460. {
  461.     void                  *mark;
  462.     PRArenaPool           *poolp;
  463.     CRMFProofOfPossession *pop;
  464.     CRMFPOPOPrivKey       *popoPrivKey;
  465.     SECStatus              rv;
  466.     const SEC_ASN1Template *privKeyTemplate;
  467.     if (subsequentMessage == crmfNoSubseqMess) {
  468.         return SECFailure;
  469.     }
  470.     poolp = inCertReqMsg->poolp;
  471.     mark = PORT_ArenaMark(poolp);
  472.     pop = PORT_ArenaZNew(poolp, CRMFProofOfPossession);
  473.     if (pop == NULL) {
  474.         goto loser;
  475.     }
  476.     pop->popUsed = inChoice;
  477.     /* 
  478.      * We have a union, so a pointer to one member of the union
  479.      * is also a member to another member of that same union.
  480.      */
  481.     popoPrivKey = &pop->popChoice.keyEncipherment;
  482.     switch (subsequentMessage) {
  483.     case crmfEncrCert:
  484.         rv = crmf_encode_integer(poolp, 
  485.  &(popoPrivKey->message.subsequentMessage),
  486.  0);
  487. break;
  488.     case crmfChallengeResp:
  489.         rv = crmf_encode_integer(poolp,
  490.  &(popoPrivKey->message.subsequentMessage),
  491.  1);
  492. break;
  493.     default:
  494.         goto loser;
  495.     }
  496.     if (rv != SECSuccess) {
  497.         goto loser;
  498.     }
  499.     popoPrivKey->messageChoice = crmfSubsequentMessage;
  500.     privKeyTemplate = crmf_get_template_for_privkey(inChoice);
  501.     inCertReqMsg->pop = pop;
  502.     rv = crmf_encode_popoprivkey(poolp, inCertReqMsg, popoPrivKey,
  503.  privKeyTemplate);
  504.     if (rv != SECSuccess) {
  505.         goto loser;
  506.     }
  507.     PORT_ArenaUnmark(poolp, mark);
  508.     return SECSuccess;
  509.  loser:
  510.     PORT_ArenaRelease(poolp, mark);
  511.     return SECFailure;
  512. }
  513. SECStatus 
  514. CRMF_CertReqMsgSetKeyEnciphermentPOP(CRMFCertReqMsg        *inCertReqMsg,
  515.      CRMFPOPOPrivKeyChoice  inKeyChoice,
  516.      CRMFSubseqMessOptions  subseqMess,
  517.      SECItem               *encPrivKey)
  518. {
  519.     SECStatus rv;
  520.     PORT_Assert(inCertReqMsg != NULL && inCertReqMsg->pop == NULL);
  521.     if (CRMF_CertReqMsgGetPOPType(inCertReqMsg) != crmfNoPOPChoice) {
  522.         return SECFailure;
  523.     }
  524.     switch (inKeyChoice) {    
  525.     case crmfThisMessage:
  526.         rv = crmf_add_privkey_thismessage(inCertReqMsg, encPrivKey,
  527.   crmfKeyEncipherment);
  528. break;
  529.     case crmfSubsequentMessage:
  530.         rv = crmf_add_privkey_subseqmessage(inCertReqMsg, subseqMess, 
  531.     crmfKeyEncipherment);
  532.         break;
  533.     case crmfDHMAC:
  534.     default:
  535.         rv = SECFailure;
  536.     }
  537.     return rv;
  538. }
  539. SECStatus 
  540. CRMF_CertReqMsgSetKeyAgreementPOP (CRMFCertReqMsg        *inCertReqMsg,
  541.    CRMFPOPOPrivKeyChoice  inKeyChoice,
  542.    CRMFSubseqMessOptions  subseqMess,
  543.    SECItem               *encPrivKey)
  544. {
  545.     SECStatus rv;
  546.     PORT_Assert(inCertReqMsg != NULL && inCertReqMsg->pop == NULL);
  547.     switch (inKeyChoice) {    
  548.     case crmfThisMessage:
  549.         rv = crmf_add_privkey_thismessage(inCertReqMsg, encPrivKey,
  550.   crmfKeyAgreement);
  551. break;
  552.     case crmfSubsequentMessage:
  553.         rv = crmf_add_privkey_subseqmessage(inCertReqMsg, subseqMess, 
  554.     crmfKeyAgreement);
  555.     case crmfDHMAC:
  556.         /* This case should be added in the future. */
  557.     default:
  558.         rv = SECFailure;
  559.     }
  560.     return rv;
  561. }