Back to index

lightning-sunbird  0.9+nobinonly
crmfpop.c
Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 8 -*-*/
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is the Netscape security libraries.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1994-2000
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 
00039 #include "crmf.h"
00040 #include "crmfi.h"
00041 #include "secasn1.h"
00042 #include "keyhi.h"
00043 #include "cryptohi.h"
00044 
00045 #define CRMF_DEFAULT_ALLOC_SIZE 1024
00046 
00047 SECStatus
00048 crmf_init_encoder_callback_arg (struct crmfEncoderArg *encoderArg, 
00049                             SECItem               *derDest) 
00050 {
00051     derDest->data = PORT_ZNewArray(unsigned char, CRMF_DEFAULT_ALLOC_SIZE);
00052     if (derDest->data == NULL) {
00053         return SECFailure;
00054     }
00055     derDest->len = 0;
00056     encoderArg->allocatedLen = CRMF_DEFAULT_ALLOC_SIZE;
00057     encoderArg->buffer = derDest;
00058     return SECSuccess;
00059 
00060 }
00061 
00062 /* Caller should release or unmark the pool, instead of doing it here.
00063 ** But there are NO callers of this function at present...
00064 */
00065 SECStatus 
00066 CRMF_CertReqMsgSetRAVerifiedPOP(CRMFCertReqMsg *inCertReqMsg)
00067 {
00068     SECItem               *dummy;
00069     CRMFProofOfPossession *pop;
00070     PRArenaPool           *poolp;
00071     void                  *mark;
00072 
00073     PORT_Assert(inCertReqMsg != NULL && inCertReqMsg->pop == NULL);
00074     poolp = inCertReqMsg->poolp;
00075     mark = PORT_ArenaMark(poolp);
00076     if (CRMF_CertReqMsgGetPOPType(inCertReqMsg) != crmfNoPOPChoice) {
00077         return SECFailure;
00078     }
00079     pop = PORT_ArenaZNew(poolp, CRMFProofOfPossession);
00080     if (pop == NULL) {
00081         goto loser;
00082     }
00083     pop->popUsed = crmfRAVerified;
00084     pop->popChoice.raVerified.data = NULL;
00085     pop->popChoice.raVerified.len  = 0;
00086     inCertReqMsg->pop = pop;
00087     dummy = SEC_ASN1EncodeItem(poolp, &(inCertReqMsg->derPOP),
00088                             &(pop->popChoice.raVerified),
00089                             CRMFRAVerifiedTemplate);
00090     return SECSuccess;
00091  loser:
00092     PORT_ArenaRelease(poolp, mark);
00093     return SECFailure;
00094 }
00095 
00096 SECOidTag
00097 crmf_get_key_sign_tag(SECKEYPublicKey *inPubKey)
00098 {
00099     /* maintain backward compatibility with older
00100      * implementations */
00101     if (inPubKey->keyType == rsaKey) {
00102         return SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
00103     }
00104     return SEC_GetSignatureAlgorithmOidTag(inPubKey->keyType, SEC_OID_UNKNOWN);
00105 }
00106 
00107 SECAlgorithmID*
00108 crmf_create_poposignkey_algid(PRArenaPool      *poolp,
00109                            SECKEYPublicKey  *inPubKey)
00110 {
00111     SECAlgorithmID *algID;
00112     SECOidTag       tag;
00113     SECStatus       rv;
00114     void           *mark;
00115 
00116     mark = PORT_ArenaMark(poolp);
00117     algID = PORT_ArenaZNew(poolp, SECAlgorithmID);
00118     if (algID == NULL) {
00119         goto loser;
00120     }
00121     tag = crmf_get_key_sign_tag(inPubKey);
00122     if (tag == SEC_OID_UNKNOWN) {
00123         goto loser;
00124     }
00125     rv = SECOID_SetAlgorithmID(poolp, algID, tag, NULL);
00126     if (rv != SECSuccess) {
00127         goto loser;
00128     }
00129     PORT_ArenaUnmark(poolp, mark);
00130     return algID;
00131  loser:
00132     PORT_ArenaRelease(poolp, mark);
00133     return NULL;
00134 }
00135 
00136 static CRMFPOPOSigningKeyInput*
00137 crmf_create_poposigningkeyinput(PRArenaPool *poolp, CERTCertificate *inCert,
00138                             CRMFMACPasswordCallback fn, void *arg)
00139 {
00140   /* PSM isn't going to do this, so we'll fail here for now.*/
00141      return NULL;
00142 }
00143 
00144 void
00145 crmf_generic_encoder_callback(void *arg, const char* buf, unsigned long len,
00146                            int depth, SEC_ASN1EncodingPart data_kind)
00147 {
00148     struct crmfEncoderArg *encoderArg = (struct crmfEncoderArg*)arg;
00149     unsigned char *cursor;
00150     
00151    if (encoderArg->buffer->len + len > encoderArg->allocatedLen) {
00152         int newSize = encoderArg->buffer->len+CRMF_DEFAULT_ALLOC_SIZE;
00153         void *dummy = PORT_Realloc(encoderArg->buffer->data, newSize);
00154        if (dummy == NULL) {
00155            /* I really want to return an error code here */
00156            PORT_Assert(0);
00157            return;
00158        }
00159        encoderArg->buffer->data = dummy;
00160        encoderArg->allocatedLen = newSize;
00161     }
00162     cursor = &(encoderArg->buffer->data[encoderArg->buffer->len]);
00163     PORT_Memcpy (cursor, buf, len);
00164     encoderArg->buffer->len += len;    
00165 }
00166 
00167 static SECStatus
00168 crmf_encode_certreq(CRMFCertRequest *inCertReq, SECItem *derDest)
00169 {
00170     struct crmfEncoderArg encoderArg;
00171     SECStatus             rv;
00172   
00173     rv = crmf_init_encoder_callback_arg (&encoderArg, derDest);
00174     if (rv != SECSuccess) {
00175         return SECFailure;
00176     }
00177     return SEC_ASN1Encode(inCertReq, CRMFCertRequestTemplate, 
00178                        crmf_generic_encoder_callback, &encoderArg);
00179 }
00180 
00181 static SECStatus
00182 crmf_sign_certreq(PRArenaPool        *poolp, 
00183                 CRMFPOPOSigningKey *crmfSignKey, 
00184                 CRMFCertRequest    *certReq,
00185                 SECKEYPrivateKey   *inKey,
00186                 SECAlgorithmID     *inAlgId)
00187 {
00188     SECItem                      derCertReq = { siBuffer, NULL, 0 };
00189     SECItem                      certReqSig = { siBuffer, NULL, 0 };
00190     SECStatus                    rv = SECSuccess;
00191 
00192     rv = crmf_encode_certreq(certReq, &derCertReq);
00193     if (rv != SECSuccess) {
00194        goto loser;
00195     }
00196     rv = SEC_SignData(&certReqSig, derCertReq.data, derCertReq.len,
00197                     inKey,SECOID_GetAlgorithmTag(inAlgId));
00198     if (rv != SECSuccess) {
00199         goto loser;
00200     }
00201  
00202     /* Now make it a part of the POPOSigningKey */
00203     rv = SECITEM_CopyItem(poolp, &(crmfSignKey->signature), &certReqSig);
00204     /* Convert this length to number of bits */
00205     crmfSignKey->signature.len <<= 3; 
00206    
00207  loser:
00208     if (derCertReq.data != NULL) {
00209         PORT_Free(derCertReq.data);
00210     }
00211     if (certReqSig.data != NULL) {
00212         PORT_Free(certReqSig.data);
00213     }
00214     return rv;
00215 }
00216 
00217 static SECStatus
00218 crmf_create_poposignkey(PRArenaPool             *poolp, 
00219                      CRMFCertReqMsg          *inCertReqMsg, 
00220                      CRMFPOPOSigningKeyInput *signKeyInput, 
00221                      SECKEYPrivateKey        *inPrivKey,
00222                      SECAlgorithmID          *inAlgID,
00223                      CRMFPOPOSigningKey      *signKey) 
00224 {
00225     CRMFCertRequest    *certReq;
00226     void               *mark;
00227     PRBool              useSignKeyInput;
00228     SECStatus           rv;
00229     
00230     PORT_Assert(inCertReqMsg != NULL && inCertReqMsg->certReq != NULL);
00231     mark = PORT_ArenaMark(poolp);
00232     if (signKey == NULL) {
00233         goto loser;
00234     }
00235     certReq = inCertReqMsg->certReq;
00236     useSignKeyInput = !(CRMF_DoesRequestHaveField(certReq,crmfSubject)  &&
00237                      CRMF_DoesRequestHaveField(certReq,crmfPublicKey));
00238 
00239     if (useSignKeyInput) {
00240         goto loser; 
00241     } else {
00242         rv = crmf_sign_certreq(poolp, signKey, certReq,inPrivKey, inAlgID);
00243        if (rv != SECSuccess) {
00244            goto loser;
00245        }
00246     }
00247     PORT_ArenaUnmark(poolp,mark);
00248     return SECSuccess;
00249  loser:
00250     PORT_ArenaRelease(poolp,mark);
00251     return SECFailure;
00252 }
00253 
00254 SECStatus
00255 CRMF_CertReqMsgSetSignaturePOP(CRMFCertReqMsg   *inCertReqMsg,
00256                             SECKEYPrivateKey *inPrivKey,
00257                             SECKEYPublicKey  *inPubKey,
00258                             CERTCertificate  *inCertForInput,
00259                             CRMFMACPasswordCallback  fn,
00260                             void                    *arg)
00261 {
00262     SECAlgorithmID  *algID;
00263     PRArenaPool     *poolp;
00264     SECItem          derTemp = {siBuffer, NULL, 0};
00265     void            *mark;
00266     SECStatus        rv;
00267     CRMFPOPOSigningKeyInput *signKeyInput = NULL;
00268     CRMFCertRequest         *certReq;
00269     CRMFProofOfPossession   *pop;
00270     struct crmfEncoderArg    encoderArg;
00271 
00272     PORT_Assert(inCertReqMsg != NULL && inCertReqMsg->certReq != NULL &&
00273               inCertReqMsg->pop == NULL);
00274     certReq = inCertReqMsg->certReq;
00275     if (CRMF_CertReqMsgGetPOPType(inCertReqMsg) != crmfNoPOPChoice || 
00276        !CRMF_DoesRequestHaveField(certReq, crmfPublicKey)) {
00277         return SECFailure;
00278     } 
00279     poolp = inCertReqMsg->poolp;
00280     mark = PORT_ArenaMark(poolp);
00281     algID = crmf_create_poposignkey_algid(poolp, inPubKey);
00282 
00283     if(!CRMF_DoesRequestHaveField(certReq,crmfSubject)) {
00284         signKeyInput = crmf_create_poposigningkeyinput(poolp, inCertForInput,
00285                                                  fn, arg);
00286        if (signKeyInput == NULL) {
00287            goto loser;
00288        }
00289     }
00290 
00291     pop = PORT_ArenaZNew(poolp, CRMFProofOfPossession);
00292     if (pop == NULL) {
00293         goto loser;
00294     }
00295     
00296     rv = crmf_create_poposignkey(poolp, inCertReqMsg, 
00297                              signKeyInput, inPrivKey, algID,
00298                              &(pop->popChoice.signature));
00299     if (rv != SECSuccess) {
00300         goto loser;
00301     }
00302 
00303     pop->popUsed = crmfSignature;
00304     pop->popChoice.signature.algorithmIdentifier = algID;
00305     inCertReqMsg->pop = pop;
00306   
00307     rv = crmf_init_encoder_callback_arg (&encoderArg, &derTemp);
00308     if (rv != SECSuccess) {
00309         goto loser;
00310     }
00311     rv = SEC_ASN1Encode(&pop->popChoice.signature, 
00312                      CRMFPOPOSigningKeyTemplate,
00313                      crmf_generic_encoder_callback, &encoderArg);
00314     if (rv != SECSuccess) {
00315         goto loser;
00316     }
00317     rv = SECITEM_CopyItem(poolp, &(inCertReqMsg->derPOP), &derTemp);
00318     if (rv != SECSuccess) {
00319         goto loser;
00320     }
00321     PORT_Free (derTemp.data);
00322     PORT_ArenaUnmark(poolp,mark);
00323     return SECSuccess;
00324 
00325  loser:
00326     PORT_ArenaRelease(poolp,mark);
00327     if (derTemp.data != NULL) {
00328         PORT_Free(derTemp.data);
00329     }
00330     return SECFailure;
00331 }
00332 
00333 static const SEC_ASN1Template*
00334 crmf_get_popoprivkey_subtemplate(CRMFPOPOPrivKey *inPrivKey) 
00335 {
00336     const SEC_ASN1Template *retTemplate = NULL;
00337 
00338     switch (inPrivKey->messageChoice) {
00339     case crmfThisMessage:
00340         retTemplate = CRMFThisMessageTemplate;
00341        break;
00342     case crmfSubsequentMessage:
00343         retTemplate = CRMFSubsequentMessageTemplate;
00344        break;
00345     case crmfDHMAC:
00346         retTemplate = CRMFDHMACTemplate;
00347        break;
00348     default:
00349         retTemplate = NULL;
00350     }
00351     return retTemplate;
00352 }
00353 
00354 static SECStatus
00355 crmf_encode_popoprivkey(PRArenaPool            *poolp, 
00356                      CRMFCertReqMsg         *inCertReqMsg,
00357                      CRMFPOPOPrivKey        *popoPrivKey,
00358                      const SEC_ASN1Template *privKeyTemplate)
00359 {
00360     struct crmfEncoderArg   encoderArg;
00361     SECItem                 derTemp; 
00362     SECStatus               rv;
00363     void                   *mark;
00364     const SEC_ASN1Template *subDerTemplate;
00365 
00366     mark = PORT_ArenaMark(poolp);
00367     rv = crmf_init_encoder_callback_arg(&encoderArg, &derTemp);
00368     if (rv != SECSuccess) {
00369         goto loser;
00370     }
00371     subDerTemplate = crmf_get_popoprivkey_subtemplate(popoPrivKey);
00372     /* We've got a union, so a pointer to one item is a pointer to 
00373      * all the items in the union.
00374      */
00375     rv = SEC_ASN1Encode(&popoPrivKey->message.thisMessage, 
00376                      subDerTemplate,
00377                      crmf_generic_encoder_callback, &encoderArg);
00378     if (rv != SECSuccess) {
00379         goto loser;
00380     }
00381     if (encoderArg.allocatedLen > derTemp.len+2) {
00382         void *dummy = PORT_Realloc(derTemp.data, derTemp.len+2);
00383        if (dummy == NULL) {
00384            goto loser;
00385        }
00386        derTemp.data = dummy;
00387     }
00388     PORT_Memmove(&derTemp.data[2], &derTemp.data[0], derTemp.len);
00389     /* I couldn't figure out how to get the ASN1 encoder to implicitly
00390      * tag an implicitly tagged der blob.  So I'm putting in the outter-
00391      * most tag myself. -javi
00392      */
00393     derTemp.data[0] = (unsigned char)privKeyTemplate->kind;
00394     derTemp.data[1] = (unsigned char)derTemp.len;
00395     derTemp.len += 2;
00396     rv = SECITEM_CopyItem(poolp, &inCertReqMsg->derPOP, &derTemp);
00397     if (rv != SECSuccess) {
00398         goto loser;
00399     }
00400     PORT_Free(derTemp.data);
00401     PORT_ArenaUnmark(poolp, mark);
00402     return SECSuccess;
00403  loser:
00404     PORT_ArenaRelease(poolp, mark);
00405     if (derTemp.data) {
00406         PORT_Free(derTemp.data);
00407     }
00408     return SECFailure;
00409 }
00410 
00411 static const SEC_ASN1Template*
00412 crmf_get_template_for_privkey(CRMFPOPChoice inChoice) 
00413 {
00414     switch (inChoice) {
00415     case crmfKeyAgreement:
00416         return CRMFPOPOKeyAgreementTemplate;
00417     case crmfKeyEncipherment:
00418         return CRMFPOPOKeyEnciphermentTemplate;
00419     default:
00420         break;
00421     }
00422     return NULL;
00423 }
00424 
00425 static SECStatus
00426 crmf_add_privkey_thismessage(CRMFCertReqMsg *inCertReqMsg, SECItem *encPrivKey,
00427                           CRMFPOPChoice inChoice)
00428 {
00429     PRArenaPool           *poolp;
00430     void                  *mark;
00431     CRMFPOPOPrivKey       *popoPrivKey;
00432     CRMFProofOfPossession *pop;
00433     SECStatus              rv;
00434 
00435     PORT_Assert(inCertReqMsg != NULL && encPrivKey != NULL);
00436     poolp = inCertReqMsg->poolp;
00437     mark = PORT_ArenaMark(poolp);
00438     pop = PORT_ArenaZNew(poolp, CRMFProofOfPossession);
00439     if (pop == NULL) {
00440         goto loser;
00441     }
00442     pop->popUsed = inChoice;
00443     /* popChoice is a union, so getting a pointer to one
00444      * field gives me a pointer to the other fields as
00445      * well.  This in essence points to both 
00446      * pop->popChoice.keyEncipherment and
00447      * pop->popChoice.keyAgreement
00448      */
00449     popoPrivKey = &pop->popChoice.keyEncipherment;
00450 
00451     rv = SECITEM_CopyItem(poolp, &(popoPrivKey->message.thisMessage),
00452                        encPrivKey);
00453     if (rv != SECSuccess) {
00454         goto loser;
00455     }
00456     popoPrivKey->message.thisMessage.len <<= 3;
00457     popoPrivKey->messageChoice = crmfThisMessage;
00458     inCertReqMsg->pop = pop;
00459     rv = crmf_encode_popoprivkey(poolp, inCertReqMsg, popoPrivKey,
00460                              crmf_get_template_for_privkey(inChoice));
00461     if (rv != SECSuccess) {
00462         goto loser;
00463     }
00464     PORT_ArenaUnmark(poolp, mark);
00465     return SECSuccess;
00466     
00467  loser:
00468     PORT_ArenaRelease(poolp, mark);
00469     return SECFailure;
00470 }
00471 
00472 static SECStatus
00473 crmf_add_privkey_dhmac(CRMFCertReqMsg *inCertReqMsg, SECItem *dhmac,
00474                              CRMFPOPChoice inChoice)
00475 {
00476     PRArenaPool           *poolp;
00477     void                  *mark;
00478     CRMFPOPOPrivKey       *popoPrivKey;
00479     CRMFProofOfPossession *pop;
00480     SECStatus              rv;
00481 
00482     PORT_Assert(inCertReqMsg != NULL && dhmac != NULL);
00483     poolp = inCertReqMsg->poolp;
00484     mark = PORT_ArenaMark(poolp);
00485     pop = PORT_ArenaZNew(poolp, CRMFProofOfPossession);
00486     if (pop == NULL) {
00487         goto loser;
00488     }
00489     pop->popUsed = inChoice;
00490     popoPrivKey = &pop->popChoice.keyAgreement;
00491 
00492     rv = SECITEM_CopyItem(poolp, &(popoPrivKey->message.dhMAC),
00493                           dhmac);
00494     if (rv != SECSuccess) {
00495         goto loser;
00496     }
00497     popoPrivKey->message.dhMAC.len <<= 3;
00498     popoPrivKey->messageChoice = crmfDHMAC;
00499     inCertReqMsg->pop = pop;
00500     rv = crmf_encode_popoprivkey(poolp, inCertReqMsg, popoPrivKey,
00501                                  crmf_get_template_for_privkey(inChoice));
00502     if (rv != SECSuccess) {
00503         goto loser;
00504     }
00505     PORT_ArenaUnmark(poolp, mark);
00506     return SECSuccess;
00507     
00508  loser:
00509     PORT_ArenaRelease(poolp, mark);
00510     return SECFailure;
00511 }
00512 
00513 static SECStatus
00514 crmf_add_privkey_subseqmessage(CRMFCertReqMsg        *inCertReqMsg,
00515                             CRMFSubseqMessOptions  subsequentMessage,
00516                             CRMFPOPChoice          inChoice)
00517 {
00518     void                  *mark;
00519     PRArenaPool           *poolp;
00520     CRMFProofOfPossession *pop;
00521     CRMFPOPOPrivKey       *popoPrivKey;
00522     SECStatus              rv;
00523     const SEC_ASN1Template *privKeyTemplate;
00524 
00525     if (subsequentMessage == crmfNoSubseqMess) {
00526         return SECFailure;
00527     }
00528     poolp = inCertReqMsg->poolp;
00529     mark = PORT_ArenaMark(poolp);
00530     pop = PORT_ArenaZNew(poolp, CRMFProofOfPossession);
00531     if (pop == NULL) {
00532         goto loser;
00533     }
00534 
00535     pop->popUsed = inChoice;
00536     /* 
00537      * We have a union, so a pointer to one member of the union
00538      * is also a member to another member of that same union.
00539      */
00540     popoPrivKey = &pop->popChoice.keyEncipherment;
00541 
00542     switch (subsequentMessage) {
00543     case crmfEncrCert:
00544         rv = crmf_encode_integer(poolp, 
00545                              &(popoPrivKey->message.subsequentMessage),
00546                              0);
00547        break;
00548     case crmfChallengeResp:
00549         rv = crmf_encode_integer(poolp,
00550                              &(popoPrivKey->message.subsequentMessage),
00551                              1);
00552        break;
00553     default:
00554         goto loser;
00555     }
00556     if (rv != SECSuccess) {
00557         goto loser;
00558     }
00559     popoPrivKey->messageChoice = crmfSubsequentMessage;
00560     privKeyTemplate = crmf_get_template_for_privkey(inChoice);
00561     inCertReqMsg->pop = pop;
00562     rv = crmf_encode_popoprivkey(poolp, inCertReqMsg, popoPrivKey,
00563                              privKeyTemplate);
00564 
00565     if (rv != SECSuccess) {
00566         goto loser;
00567     }
00568     PORT_ArenaUnmark(poolp, mark);
00569     return SECSuccess;
00570  loser:
00571     PORT_ArenaRelease(poolp, mark);
00572     return SECFailure;
00573 }
00574 
00575 SECStatus 
00576 CRMF_CertReqMsgSetKeyEnciphermentPOP(CRMFCertReqMsg        *inCertReqMsg,
00577                                  CRMFPOPOPrivKeyChoice  inKeyChoice,
00578                                  CRMFSubseqMessOptions  subseqMess,
00579                                  SECItem               *encPrivKey)
00580 {
00581     SECStatus rv;
00582 
00583     PORT_Assert(inCertReqMsg != NULL && inCertReqMsg->pop == NULL);
00584     if (CRMF_CertReqMsgGetPOPType(inCertReqMsg) != crmfNoPOPChoice) {
00585         return SECFailure;
00586     }
00587     switch (inKeyChoice) {    
00588     case crmfThisMessage:
00589         rv = crmf_add_privkey_thismessage(inCertReqMsg, encPrivKey,
00590                                      crmfKeyEncipherment);
00591        break;
00592     case crmfSubsequentMessage:
00593         rv = crmf_add_privkey_subseqmessage(inCertReqMsg, subseqMess, 
00594                                        crmfKeyEncipherment);
00595         break;
00596     case crmfDHMAC:
00597     default:
00598         rv = SECFailure;
00599     }
00600     return rv;
00601 }
00602 
00603 SECStatus 
00604 CRMF_CertReqMsgSetKeyAgreementPOP (CRMFCertReqMsg        *inCertReqMsg,
00605                                CRMFPOPOPrivKeyChoice  inKeyChoice,
00606                                CRMFSubseqMessOptions  subseqMess,
00607                                SECItem               *encPrivKey)
00608 {
00609     SECStatus rv;
00610 
00611     PORT_Assert(inCertReqMsg != NULL && inCertReqMsg->pop == NULL);
00612     switch (inKeyChoice) {    
00613     case crmfThisMessage:
00614         rv = crmf_add_privkey_thismessage(inCertReqMsg, encPrivKey,
00615                                      crmfKeyAgreement);
00616        break;
00617     case crmfSubsequentMessage:
00618         rv = crmf_add_privkey_subseqmessage(inCertReqMsg, subseqMess, 
00619                                        crmfKeyAgreement);
00620        break;
00621     case crmfDHMAC:
00622         /* In this case encPrivKey should be the calculated dhMac
00623          * as specified in RFC 2511 */
00624         rv = crmf_add_privkey_dhmac(inCertReqMsg, encPrivKey,
00625                                     crmfKeyAgreement);
00626         break;
00627     default:
00628         rv = SECFailure;
00629     }
00630     return rv;
00631 }
00632