crmfpop.c 18 KB

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