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