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 "cmmf.h"
7 #include "cmmfi.h"
8 #include "secitem.h"
9 #include "keyhi.h"
10 #include "secder.h"
11 
12 CRMFEncryptedKeyChoice
CRMF_EncryptedKeyGetChoice(CRMFEncryptedKey * inEncrKey)13 CRMF_EncryptedKeyGetChoice(CRMFEncryptedKey *inEncrKey)
14 {
15     PORT_Assert(inEncrKey != NULL);
16     if (inEncrKey == NULL) {
17         return crmfNoEncryptedKeyChoice;
18     }
19     return inEncrKey->encKeyChoice;
20 }
21 
22 CRMFEncryptedValue *
CRMF_EncryptedKeyGetEncryptedValue(CRMFEncryptedKey * inEncrKey)23 CRMF_EncryptedKeyGetEncryptedValue(CRMFEncryptedKey *inEncrKey)
24 {
25     CRMFEncryptedValue *newEncrValue = NULL;
26     SECStatus rv;
27 
28     PORT_Assert(inEncrKey != NULL);
29     if (inEncrKey == NULL ||
30         CRMF_EncryptedKeyGetChoice(inEncrKey) != crmfEncryptedValueChoice) {
31         goto loser;
32     }
33     newEncrValue = PORT_ZNew(CRMFEncryptedValue);
34     if (newEncrValue == NULL) {
35         goto loser;
36     }
37     rv = crmf_copy_encryptedvalue(NULL, &inEncrKey->value.encryptedValue,
38                                   newEncrValue);
39     if (rv != SECSuccess) {
40         goto loser;
41     }
42     return newEncrValue;
43 loser:
44     if (newEncrValue != NULL) {
45         CRMF_DestroyEncryptedValue(newEncrValue);
46     }
47     return NULL;
48 }
49 
50 static SECItem *
crmf_get_encvalue_bitstring(SECItem * srcItem)51 crmf_get_encvalue_bitstring(SECItem *srcItem)
52 {
53     SECItem *newItem = NULL;
54     SECStatus rv;
55 
56     if (srcItem->data == NULL) {
57         return NULL;
58     }
59     newItem = PORT_ZNew(SECItem);
60     if (newItem == NULL) {
61         goto loser;
62     }
63     rv = crmf_make_bitstring_copy(NULL, newItem, srcItem);
64     if (rv != SECSuccess) {
65         goto loser;
66     }
67     return newItem;
68 loser:
69     if (newItem != NULL) {
70         SECITEM_FreeItem(newItem, PR_TRUE);
71     }
72     return NULL;
73 }
74 
75 SECItem *
CRMF_EncryptedValueGetEncSymmKey(CRMFEncryptedValue * inEncValue)76 CRMF_EncryptedValueGetEncSymmKey(CRMFEncryptedValue *inEncValue)
77 {
78     if (inEncValue == NULL) {
79         return NULL;
80     }
81     return crmf_get_encvalue_bitstring(&inEncValue->encSymmKey);
82 }
83 
84 SECItem *
CRMF_EncryptedValueGetEncValue(CRMFEncryptedValue * inEncrValue)85 CRMF_EncryptedValueGetEncValue(CRMFEncryptedValue *inEncrValue)
86 {
87     if (inEncrValue == NULL || inEncrValue->encValue.data == NULL) {
88         return NULL;
89     }
90     return crmf_get_encvalue_bitstring(&inEncrValue->encValue);
91 }
92 
93 static SECAlgorithmID *
crmf_get_encvalue_algid(SECAlgorithmID * srcAlg)94 crmf_get_encvalue_algid(SECAlgorithmID *srcAlg)
95 {
96     SECStatus rv;
97     SECAlgorithmID *newAlgID;
98 
99     if (srcAlg == NULL) {
100         return NULL;
101     }
102     rv = crmf_copy_encryptedvalue_secalg(NULL, srcAlg, &newAlgID);
103     if (rv != SECSuccess) {
104         return NULL;
105     }
106     return newAlgID;
107 }
108 
109 SECAlgorithmID *
CRMF_EncryptedValueGetIntendedAlg(CRMFEncryptedValue * inEncValue)110 CRMF_EncryptedValueGetIntendedAlg(CRMFEncryptedValue *inEncValue)
111 {
112     if (inEncValue == NULL) {
113         return NULL;
114     }
115     return crmf_get_encvalue_algid(inEncValue->intendedAlg);
116 }
117 
118 SECAlgorithmID *
CRMF_EncryptedValueGetKeyAlg(CRMFEncryptedValue * inEncValue)119 CRMF_EncryptedValueGetKeyAlg(CRMFEncryptedValue *inEncValue)
120 {
121     if (inEncValue == NULL) {
122         return NULL;
123     }
124     return crmf_get_encvalue_algid(inEncValue->keyAlg);
125 }
126 
127 SECAlgorithmID *
CRMF_EncryptedValueGetSymmAlg(CRMFEncryptedValue * inEncValue)128 CRMF_EncryptedValueGetSymmAlg(CRMFEncryptedValue *inEncValue)
129 {
130     if (inEncValue == NULL) {
131         return NULL;
132     }
133     return crmf_get_encvalue_algid(inEncValue->symmAlg);
134 }
135 
136 SECItem *
CRMF_EncryptedValueGetValueHint(CRMFEncryptedValue * inEncValue)137 CRMF_EncryptedValueGetValueHint(CRMFEncryptedValue *inEncValue)
138 {
139     if (inEncValue == NULL || inEncValue->valueHint.data == NULL) {
140         return NULL;
141     }
142     return SECITEM_DupItem(&inEncValue->valueHint);
143 }
144 
145 SECStatus
CRMF_PKIArchiveOptionsGetArchiveRemGenPrivKey(CRMFPKIArchiveOptions * inOpt,PRBool * destVal)146 CRMF_PKIArchiveOptionsGetArchiveRemGenPrivKey(CRMFPKIArchiveOptions *inOpt,
147                                               PRBool *destVal)
148 {
149     if (inOpt == NULL || destVal == NULL ||
150         CRMF_PKIArchiveOptionsGetOptionType(inOpt) != crmfArchiveRemGenPrivKey) {
151         return SECFailure;
152     }
153     *destVal = (inOpt->option.archiveRemGenPrivKey.data[0] == hexFalse)
154                    ? PR_FALSE
155                    : PR_TRUE;
156     return SECSuccess;
157 }
158 
159 CRMFEncryptedKey *
CRMF_PKIArchiveOptionsGetEncryptedPrivKey(CRMFPKIArchiveOptions * inOpts)160 CRMF_PKIArchiveOptionsGetEncryptedPrivKey(CRMFPKIArchiveOptions *inOpts)
161 {
162     CRMFEncryptedKey *newEncrKey = NULL;
163     SECStatus rv;
164 
165     PORT_Assert(inOpts != NULL);
166     if (inOpts == NULL ||
167         CRMF_PKIArchiveOptionsGetOptionType(inOpts) != crmfEncryptedPrivateKey) {
168         return NULL;
169     }
170     newEncrKey = PORT_ZNew(CRMFEncryptedKey);
171     if (newEncrKey == NULL) {
172         goto loser;
173     }
174     rv = crmf_copy_encryptedkey(NULL, &inOpts->option.encryptedKey,
175                                 newEncrKey);
176     if (rv != SECSuccess) {
177         goto loser;
178     }
179     return newEncrKey;
180 loser:
181     if (newEncrKey != NULL) {
182         CRMF_DestroyEncryptedKey(newEncrKey);
183     }
184     return NULL;
185 }
186 
187 SECItem *
CRMF_PKIArchiveOptionsGetKeyGenParameters(CRMFPKIArchiveOptions * inOptions)188 CRMF_PKIArchiveOptionsGetKeyGenParameters(CRMFPKIArchiveOptions *inOptions)
189 {
190     if (inOptions == NULL ||
191         CRMF_PKIArchiveOptionsGetOptionType(inOptions) != crmfKeyGenParameters ||
192         inOptions->option.keyGenParameters.data == NULL) {
193         return NULL;
194     }
195     return SECITEM_DupItem(&inOptions->option.keyGenParameters);
196 }
197 
198 CRMFPKIArchiveOptionsType
CRMF_PKIArchiveOptionsGetOptionType(CRMFPKIArchiveOptions * inOptions)199 CRMF_PKIArchiveOptionsGetOptionType(CRMFPKIArchiveOptions *inOptions)
200 {
201     PORT_Assert(inOptions != NULL);
202     if (inOptions == NULL) {
203         return crmfNoArchiveOptions;
204     }
205     return inOptions->archOption;
206 }
207 
208 static SECStatus
crmf_extract_long_from_item(SECItem * intItem,long * destLong)209 crmf_extract_long_from_item(SECItem *intItem, long *destLong)
210 {
211     *destLong = DER_GetInteger(intItem);
212     return (*destLong == -1) ? SECFailure : SECSuccess;
213 }
214 
215 SECStatus
CRMF_POPOPrivGetKeySubseqMess(CRMFPOPOPrivKey * inKey,CRMFSubseqMessOptions * destOpt)216 CRMF_POPOPrivGetKeySubseqMess(CRMFPOPOPrivKey *inKey,
217                               CRMFSubseqMessOptions *destOpt)
218 {
219     long value;
220     SECStatus rv;
221 
222     PORT_Assert(inKey != NULL);
223     if (inKey == NULL ||
224         inKey->messageChoice != crmfSubsequentMessage) {
225         return SECFailure;
226     }
227     rv = crmf_extract_long_from_item(&inKey->message.subsequentMessage, &value);
228     if (rv != SECSuccess) {
229         return SECFailure;
230     }
231     switch (value) {
232         case 0:
233             *destOpt = crmfEncrCert;
234             break;
235         case 1:
236             *destOpt = crmfChallengeResp;
237             break;
238         default:
239             rv = SECFailure;
240     }
241     if (rv != SECSuccess) {
242         return rv;
243     }
244     return SECSuccess;
245 }
246 
247 CRMFPOPOPrivKeyChoice
CRMF_POPOPrivKeyGetChoice(CRMFPOPOPrivKey * inPrivKey)248 CRMF_POPOPrivKeyGetChoice(CRMFPOPOPrivKey *inPrivKey)
249 {
250     PORT_Assert(inPrivKey != NULL);
251     if (inPrivKey != NULL) {
252         return inPrivKey->messageChoice;
253     }
254     return crmfNoMessage;
255 }
256 
257 SECStatus
CRMF_POPOPrivKeyGetDHMAC(CRMFPOPOPrivKey * inKey,SECItem * destMAC)258 CRMF_POPOPrivKeyGetDHMAC(CRMFPOPOPrivKey *inKey, SECItem *destMAC)
259 {
260     PORT_Assert(inKey != NULL);
261     if (inKey == NULL || inKey->message.dhMAC.data == NULL) {
262         return SECFailure;
263     }
264     return crmf_make_bitstring_copy(NULL, destMAC, &inKey->message.dhMAC);
265 }
266 
267 SECStatus
CRMF_POPOPrivKeyGetThisMessage(CRMFPOPOPrivKey * inKey,SECItem * destString)268 CRMF_POPOPrivKeyGetThisMessage(CRMFPOPOPrivKey *inKey,
269                                SECItem *destString)
270 {
271     PORT_Assert(inKey != NULL);
272     if (inKey == NULL ||
273         inKey->messageChoice != crmfThisMessage) {
274         return SECFailure;
275     }
276 
277     return crmf_make_bitstring_copy(NULL, destString,
278                                     &inKey->message.thisMessage);
279 }
280 
281 SECAlgorithmID *
CRMF_POPOSigningKeyGetAlgID(CRMFPOPOSigningKey * inSignKey)282 CRMF_POPOSigningKeyGetAlgID(CRMFPOPOSigningKey *inSignKey)
283 {
284     SECAlgorithmID *newAlgId = NULL;
285     SECStatus rv;
286 
287     PORT_Assert(inSignKey != NULL);
288     if (inSignKey == NULL) {
289         return NULL;
290     }
291     newAlgId = PORT_ZNew(SECAlgorithmID);
292     if (newAlgId == NULL) {
293         goto loser;
294     }
295     rv = SECOID_CopyAlgorithmID(NULL, newAlgId,
296                                 inSignKey->algorithmIdentifier);
297     if (rv != SECSuccess) {
298         goto loser;
299     }
300     return newAlgId;
301 
302 loser:
303     if (newAlgId != NULL) {
304         SECOID_DestroyAlgorithmID(newAlgId, PR_TRUE);
305     }
306     return NULL;
307 }
308 
309 SECItem *
CRMF_POPOSigningKeyGetInput(CRMFPOPOSigningKey * inSignKey)310 CRMF_POPOSigningKeyGetInput(CRMFPOPOSigningKey *inSignKey)
311 {
312     PORT_Assert(inSignKey != NULL);
313     if (inSignKey == NULL || inSignKey->derInput.data == NULL) {
314         return NULL;
315     }
316     return SECITEM_DupItem(&inSignKey->derInput);
317 }
318 
319 SECItem *
CRMF_POPOSigningKeyGetSignature(CRMFPOPOSigningKey * inSignKey)320 CRMF_POPOSigningKeyGetSignature(CRMFPOPOSigningKey *inSignKey)
321 {
322     SECItem *newSig = NULL;
323     SECStatus rv;
324 
325     PORT_Assert(inSignKey != NULL);
326     if (inSignKey == NULL) {
327         return NULL;
328     }
329     newSig = PORT_ZNew(SECItem);
330     if (newSig == NULL) {
331         goto loser;
332     }
333     rv = crmf_make_bitstring_copy(NULL, newSig, &inSignKey->signature);
334     if (rv != SECSuccess) {
335         goto loser;
336     }
337     return newSig;
338 loser:
339     if (newSig != NULL) {
340         SECITEM_FreeItem(newSig, PR_TRUE);
341     }
342     return NULL;
343 }
344 
345 static SECStatus
crmf_copy_poposigningkey(PLArenaPool * poolp,CRMFPOPOSigningKey * inPopoSignKey,CRMFPOPOSigningKey * destPopoSignKey)346 crmf_copy_poposigningkey(PLArenaPool *poolp,
347                          CRMFPOPOSigningKey *inPopoSignKey,
348                          CRMFPOPOSigningKey *destPopoSignKey)
349 {
350     SECStatus rv;
351 
352     /* We don't support use of the POPOSigningKeyInput, so we'll only
353      * store away the DER encoding.
354      */
355     if (inPopoSignKey->derInput.data != NULL) {
356         rv = SECITEM_CopyItem(poolp, &destPopoSignKey->derInput,
357                               &inPopoSignKey->derInput);
358         if (rv != SECSuccess) {
359             goto loser;
360         }
361     }
362     destPopoSignKey->algorithmIdentifier = (poolp == NULL) ? PORT_ZNew(SECAlgorithmID)
363                                                            : PORT_ArenaZNew(poolp, SECAlgorithmID);
364 
365     if (destPopoSignKey->algorithmIdentifier == NULL) {
366         goto loser;
367     }
368     rv = SECOID_CopyAlgorithmID(poolp, destPopoSignKey->algorithmIdentifier,
369                                 inPopoSignKey->algorithmIdentifier);
370     if (rv != SECSuccess) {
371         goto loser;
372     }
373 
374     rv = crmf_make_bitstring_copy(poolp, &destPopoSignKey->signature,
375                                   &inPopoSignKey->signature);
376     if (rv != SECSuccess) {
377         goto loser;
378     }
379     return SECSuccess;
380 loser:
381     if (poolp == NULL) {
382         CRMF_DestroyPOPOSigningKey(destPopoSignKey);
383     }
384     return SECFailure;
385 }
386 
387 static SECStatus
crmf_copy_popoprivkey(PLArenaPool * poolp,CRMFPOPOPrivKey * srcPrivKey,CRMFPOPOPrivKey * destPrivKey)388 crmf_copy_popoprivkey(PLArenaPool *poolp,
389                       CRMFPOPOPrivKey *srcPrivKey,
390                       CRMFPOPOPrivKey *destPrivKey)
391 {
392     SECStatus rv;
393 
394     destPrivKey->messageChoice = srcPrivKey->messageChoice;
395     switch (destPrivKey->messageChoice) {
396         case crmfThisMessage:
397         case crmfDHMAC:
398             /* I've got a union, so taking the address of one, will also give
399              * me a pointer to the other (eg, message.dhMAC)
400              */
401             rv = crmf_make_bitstring_copy(poolp, &destPrivKey->message.thisMessage,
402                                           &srcPrivKey->message.thisMessage);
403             break;
404         case crmfSubsequentMessage:
405             rv = SECITEM_CopyItem(poolp, &destPrivKey->message.subsequentMessage,
406                                   &srcPrivKey->message.subsequentMessage);
407             break;
408         default:
409             rv = SECFailure;
410     }
411 
412     if (rv != SECSuccess && poolp == NULL) {
413         CRMF_DestroyPOPOPrivKey(destPrivKey);
414     }
415     return rv;
416 }
417 
418 static CRMFProofOfPossession *
crmf_copy_pop(PLArenaPool * poolp,CRMFProofOfPossession * srcPOP)419 crmf_copy_pop(PLArenaPool *poolp, CRMFProofOfPossession *srcPOP)
420 {
421     CRMFProofOfPossession *newPOP;
422     SECStatus rv;
423 
424     /*
425      * Proof Of Possession structures are always part of the Request
426      * message, so there will always be an arena for allocating memory.
427      */
428     if (poolp == NULL) {
429         return NULL;
430     }
431     newPOP = PORT_ArenaZNew(poolp, CRMFProofOfPossession);
432     if (newPOP == NULL) {
433         return NULL;
434     }
435     switch (srcPOP->popUsed) {
436         case crmfRAVerified:
437             newPOP->popChoice.raVerified.data = NULL;
438             newPOP->popChoice.raVerified.len = 0;
439             break;
440         case crmfSignature:
441             rv = crmf_copy_poposigningkey(poolp, &srcPOP->popChoice.signature,
442                                           &newPOP->popChoice.signature);
443             if (rv != SECSuccess) {
444                 goto loser;
445             }
446             break;
447         case crmfKeyEncipherment:
448         case crmfKeyAgreement:
449             /* We've got a union, so a pointer to one, is a pointer to the
450              * other one.
451              */
452             rv = crmf_copy_popoprivkey(poolp, &srcPOP->popChoice.keyEncipherment,
453                                        &newPOP->popChoice.keyEncipherment);
454             if (rv != SECSuccess) {
455                 goto loser;
456             }
457             break;
458         default:
459             goto loser;
460     }
461     newPOP->popUsed = srcPOP->popUsed;
462     return newPOP;
463 
464 loser:
465     return NULL;
466 }
467 
468 static CRMFCertReqMsg *
crmf_copy_cert_req_msg(CRMFCertReqMsg * srcReqMsg)469 crmf_copy_cert_req_msg(CRMFCertReqMsg *srcReqMsg)
470 {
471     CRMFCertReqMsg *newReqMsg;
472     PLArenaPool *poolp;
473 
474     poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
475     if (poolp == NULL) {
476         return NULL;
477     }
478     newReqMsg = PORT_ArenaZNew(poolp, CRMFCertReqMsg);
479     if (newReqMsg == NULL) {
480         PORT_FreeArena(poolp, PR_TRUE);
481         return NULL;
482     }
483 
484     newReqMsg->poolp = poolp;
485     newReqMsg->certReq = crmf_copy_cert_request(poolp, srcReqMsg->certReq);
486     if (newReqMsg->certReq == NULL) {
487         goto loser;
488     }
489     newReqMsg->pop = crmf_copy_pop(poolp, srcReqMsg->pop);
490     if (newReqMsg->pop == NULL) {
491         goto loser;
492     }
493     /* None of my set/get routines operate on the regInfo field, so
494      * for now, that won't get copied over.
495      */
496     return newReqMsg;
497 
498 loser:
499     CRMF_DestroyCertReqMsg(newReqMsg);
500     return NULL;
501 }
502 
503 CRMFCertReqMsg *
CRMF_CertReqMessagesGetCertReqMsgAtIndex(CRMFCertReqMessages * inReqMsgs,int index)504 CRMF_CertReqMessagesGetCertReqMsgAtIndex(CRMFCertReqMessages *inReqMsgs,
505                                          int index)
506 {
507     int numMsgs;
508 
509     PORT_Assert(inReqMsgs != NULL && index >= 0);
510     if (inReqMsgs == NULL) {
511         return NULL;
512     }
513     numMsgs = CRMF_CertReqMessagesGetNumMessages(inReqMsgs);
514     if (index < 0 || index >= numMsgs) {
515         return NULL;
516     }
517     return crmf_copy_cert_req_msg(inReqMsgs->messages[index]);
518 }
519 
520 int
CRMF_CertReqMessagesGetNumMessages(CRMFCertReqMessages * inCertReqMsgs)521 CRMF_CertReqMessagesGetNumMessages(CRMFCertReqMessages *inCertReqMsgs)
522 {
523     int numMessages = 0;
524 
525     PORT_Assert(inCertReqMsgs != NULL);
526     if (inCertReqMsgs == NULL) {
527         return 0;
528     }
529     while (inCertReqMsgs->messages[numMessages] != NULL) {
530         numMessages++;
531     }
532     return numMessages;
533 }
534 
535 CRMFCertRequest *
CRMF_CertReqMsgGetCertRequest(CRMFCertReqMsg * inCertReqMsg)536 CRMF_CertReqMsgGetCertRequest(CRMFCertReqMsg *inCertReqMsg)
537 {
538     PLArenaPool *poolp = NULL;
539     CRMFCertRequest *newCertReq = NULL;
540 
541     PORT_Assert(inCertReqMsg != NULL);
542 
543     poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
544     if (poolp == NULL) {
545         goto loser;
546     }
547     newCertReq = crmf_copy_cert_request(poolp, inCertReqMsg->certReq);
548     if (newCertReq == NULL) {
549         goto loser;
550     }
551     newCertReq->poolp = poolp;
552     return newCertReq;
553 loser:
554     if (poolp != NULL) {
555         PORT_FreeArena(poolp, PR_FALSE);
556     }
557     return NULL;
558 }
559 
560 SECStatus
CRMF_CertReqMsgGetID(CRMFCertReqMsg * inCertReqMsg,long * destID)561 CRMF_CertReqMsgGetID(CRMFCertReqMsg *inCertReqMsg, long *destID)
562 {
563     PORT_Assert(inCertReqMsg != NULL && destID != NULL);
564     if (inCertReqMsg == NULL || inCertReqMsg->certReq == NULL) {
565         return SECFailure;
566     }
567     return crmf_extract_long_from_item(&inCertReqMsg->certReq->certReqId,
568                                        destID);
569 }
570 
571 SECStatus
CRMF_CertReqMsgGetPOPKeyAgreement(CRMFCertReqMsg * inCertReqMsg,CRMFPOPOPrivKey ** destKey)572 CRMF_CertReqMsgGetPOPKeyAgreement(CRMFCertReqMsg *inCertReqMsg,
573                                   CRMFPOPOPrivKey **destKey)
574 {
575     PORT_Assert(inCertReqMsg != NULL && destKey != NULL);
576     if (inCertReqMsg == NULL || destKey == NULL ||
577         CRMF_CertReqMsgGetPOPType(inCertReqMsg) != crmfKeyAgreement) {
578         return SECFailure;
579     }
580     *destKey = PORT_ZNew(CRMFPOPOPrivKey);
581     if (*destKey == NULL) {
582         return SECFailure;
583     }
584     return crmf_copy_popoprivkey(NULL,
585                                  &inCertReqMsg->pop->popChoice.keyAgreement,
586                                  *destKey);
587 }
588 
589 SECStatus
CRMF_CertReqMsgGetPOPKeyEncipherment(CRMFCertReqMsg * inCertReqMsg,CRMFPOPOPrivKey ** destKey)590 CRMF_CertReqMsgGetPOPKeyEncipherment(CRMFCertReqMsg *inCertReqMsg,
591                                      CRMFPOPOPrivKey **destKey)
592 {
593     PORT_Assert(inCertReqMsg != NULL && destKey != NULL);
594     if (inCertReqMsg == NULL || destKey == NULL ||
595         CRMF_CertReqMsgGetPOPType(inCertReqMsg) != crmfKeyEncipherment) {
596         return SECFailure;
597     }
598     *destKey = PORT_ZNew(CRMFPOPOPrivKey);
599     if (*destKey == NULL) {
600         return SECFailure;
601     }
602     return crmf_copy_popoprivkey(NULL,
603                                  &inCertReqMsg->pop->popChoice.keyEncipherment,
604                                  *destKey);
605 }
606 
607 SECStatus
CRMF_CertReqMsgGetPOPOSigningKey(CRMFCertReqMsg * inCertReqMsg,CRMFPOPOSigningKey ** destKey)608 CRMF_CertReqMsgGetPOPOSigningKey(CRMFCertReqMsg *inCertReqMsg,
609                                  CRMFPOPOSigningKey **destKey)
610 {
611     CRMFProofOfPossession *pop;
612     PORT_Assert(inCertReqMsg != NULL);
613     if (inCertReqMsg == NULL) {
614         return SECFailure;
615     }
616     pop = inCertReqMsg->pop;
617     ;
618     if (pop->popUsed != crmfSignature) {
619         return SECFailure;
620     }
621     *destKey = PORT_ZNew(CRMFPOPOSigningKey);
622     if (*destKey == NULL) {
623         return SECFailure;
624     }
625     return crmf_copy_poposigningkey(NULL, &pop->popChoice.signature, *destKey);
626 }
627 
628 static SECStatus
crmf_copy_name(CERTName * destName,CERTName * srcName)629 crmf_copy_name(CERTName *destName, CERTName *srcName)
630 {
631     PLArenaPool *poolp = NULL;
632     SECStatus rv;
633 
634     if (destName->arena != NULL) {
635         poolp = destName->arena;
636     } else {
637         poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
638     }
639     if (poolp == NULL) {
640         return SECFailure;
641     }
642     /* Need to do this so that CERT_CopyName doesn't free out
643      * the arena from underneath us.
644      */
645     destName->arena = NULL;
646     rv = CERT_CopyName(poolp, destName, srcName);
647     destName->arena = poolp;
648     return rv;
649 }
650 
651 SECStatus
CRMF_CertRequestGetCertTemplateIssuer(CRMFCertRequest * inCertReq,CERTName * destIssuer)652 CRMF_CertRequestGetCertTemplateIssuer(CRMFCertRequest *inCertReq,
653                                       CERTName *destIssuer)
654 {
655     PORT_Assert(inCertReq != NULL);
656     if (inCertReq == NULL) {
657         return SECFailure;
658     }
659     if (CRMF_DoesRequestHaveField(inCertReq, crmfIssuer)) {
660         return crmf_copy_name(destIssuer,
661                               inCertReq->certTemplate.issuer);
662     }
663     return SECFailure;
664 }
665 
666 SECStatus
CRMF_CertRequestGetCertTemplateIssuerUID(CRMFCertRequest * inCertReq,SECItem * destIssuerUID)667 CRMF_CertRequestGetCertTemplateIssuerUID(CRMFCertRequest *inCertReq,
668                                          SECItem *destIssuerUID)
669 {
670     PORT_Assert(inCertReq != NULL);
671     if (inCertReq == NULL) {
672         return SECFailure;
673     }
674     if (CRMF_DoesRequestHaveField(inCertReq, crmfIssuerUID)) {
675         return crmf_make_bitstring_copy(NULL, destIssuerUID,
676                                         &inCertReq->certTemplate.issuerUID);
677     }
678     return SECFailure;
679 }
680 
681 SECStatus
CRMF_CertRequestGetCertTemplatePublicKey(CRMFCertRequest * inCertReq,CERTSubjectPublicKeyInfo * destPublicKey)682 CRMF_CertRequestGetCertTemplatePublicKey(CRMFCertRequest *inCertReq,
683                                          CERTSubjectPublicKeyInfo *destPublicKey)
684 {
685     PORT_Assert(inCertReq != NULL);
686     if (inCertReq == NULL) {
687         return SECFailure;
688     }
689     if (CRMF_DoesRequestHaveField(inCertReq, crmfPublicKey)) {
690         return SECKEY_CopySubjectPublicKeyInfo(NULL, destPublicKey,
691                                                inCertReq->certTemplate.publicKey);
692     }
693     return SECFailure;
694 }
695 
696 SECStatus
CRMF_CertRequestGetCertTemplateSerialNumber(CRMFCertRequest * inCertReq,long * serialNumber)697 CRMF_CertRequestGetCertTemplateSerialNumber(CRMFCertRequest *inCertReq,
698                                             long *serialNumber)
699 {
700     PORT_Assert(inCertReq != NULL);
701     if (inCertReq == NULL) {
702         return SECFailure;
703     }
704     if (CRMF_DoesRequestHaveField(inCertReq, crmfSerialNumber)) {
705         return crmf_extract_long_from_item(&inCertReq->certTemplate.serialNumber,
706                                            serialNumber);
707     }
708     return SECFailure;
709 }
710 
711 SECStatus
CRMF_CertRequestGetCertTemplateSigningAlg(CRMFCertRequest * inCertReq,SECAlgorithmID * destAlg)712 CRMF_CertRequestGetCertTemplateSigningAlg(CRMFCertRequest *inCertReq,
713                                           SECAlgorithmID *destAlg)
714 {
715     PORT_Assert(inCertReq != NULL);
716     if (inCertReq == NULL) {
717         return SECFailure;
718     }
719     if (CRMF_DoesRequestHaveField(inCertReq, crmfSigningAlg)) {
720         return SECOID_CopyAlgorithmID(NULL, destAlg,
721                                       inCertReq->certTemplate.signingAlg);
722     }
723     return SECFailure;
724 }
725 
726 SECStatus
CRMF_CertRequestGetCertTemplateSubject(CRMFCertRequest * inCertReq,CERTName * destSubject)727 CRMF_CertRequestGetCertTemplateSubject(CRMFCertRequest *inCertReq,
728                                        CERTName *destSubject)
729 {
730     PORT_Assert(inCertReq != NULL);
731     if (inCertReq == NULL) {
732         return SECFailure;
733     }
734     if (CRMF_DoesRequestHaveField(inCertReq, crmfSubject)) {
735         return crmf_copy_name(destSubject, inCertReq->certTemplate.subject);
736     }
737     return SECFailure;
738 }
739 
740 SECStatus
CRMF_CertRequestGetCertTemplateSubjectUID(CRMFCertRequest * inCertReq,SECItem * destSubjectUID)741 CRMF_CertRequestGetCertTemplateSubjectUID(CRMFCertRequest *inCertReq,
742                                           SECItem *destSubjectUID)
743 {
744     PORT_Assert(inCertReq != NULL);
745     if (inCertReq == NULL) {
746         return SECFailure;
747     }
748     if (CRMF_DoesRequestHaveField(inCertReq, crmfSubjectUID)) {
749         return crmf_make_bitstring_copy(NULL, destSubjectUID,
750                                         &inCertReq->certTemplate.subjectUID);
751     }
752     return SECFailure;
753 }
754 
755 SECStatus
CRMF_CertRequestGetCertTemplateVersion(CRMFCertRequest * inCertReq,long * version)756 CRMF_CertRequestGetCertTemplateVersion(CRMFCertRequest *inCertReq,
757                                        long *version)
758 {
759     PORT_Assert(inCertReq != NULL);
760     if (inCertReq == NULL) {
761         return SECFailure;
762     }
763     if (CRMF_DoesRequestHaveField(inCertReq, crmfVersion)) {
764         return crmf_extract_long_from_item(&inCertReq->certTemplate.version,
765                                            version);
766     }
767     return SECFailure;
768 }
769 
770 static SECStatus
crmf_copy_validity(CRMFGetValidity * destValidity,CRMFOptionalValidity * src)771 crmf_copy_validity(CRMFGetValidity *destValidity,
772                    CRMFOptionalValidity *src)
773 {
774     SECStatus rv;
775 
776     destValidity->notBefore = destValidity->notAfter = NULL;
777     if (src->notBefore.data != NULL) {
778         rv = crmf_create_prtime(&src->notBefore,
779                                 &destValidity->notBefore);
780         if (rv != SECSuccess) {
781             return rv;
782         }
783     }
784     if (src->notAfter.data != NULL) {
785         rv = crmf_create_prtime(&src->notAfter,
786                                 &destValidity->notAfter);
787         if (rv != SECSuccess) {
788             return rv;
789         }
790     }
791     return SECSuccess;
792 }
793 
794 SECStatus
CRMF_CertRequestGetCertTemplateValidity(CRMFCertRequest * inCertReq,CRMFGetValidity * destValidity)795 CRMF_CertRequestGetCertTemplateValidity(CRMFCertRequest *inCertReq,
796                                         CRMFGetValidity *destValidity)
797 {
798     PORT_Assert(inCertReq != NULL);
799     if (inCertReq == NULL) {
800         return SECFailure;
801     }
802     if (CRMF_DoesRequestHaveField(inCertReq, crmfValidity)) {
803         return crmf_copy_validity(destValidity,
804                                   inCertReq->certTemplate.validity);
805     }
806     return SECFailure;
807 }
808 
809 CRMFControl *
CRMF_CertRequestGetControlAtIndex(CRMFCertRequest * inCertReq,int index)810 CRMF_CertRequestGetControlAtIndex(CRMFCertRequest *inCertReq, int index)
811 {
812     CRMFControl *newControl, *srcControl;
813     int numControls;
814     SECStatus rv;
815 
816     PORT_Assert(inCertReq != NULL);
817     if (inCertReq == NULL) {
818         return NULL;
819     }
820     numControls = CRMF_CertRequestGetNumControls(inCertReq);
821     if (index >= numControls || index < 0) {
822         return NULL;
823     }
824     newControl = PORT_ZNew(CRMFControl);
825     if (newControl == NULL) {
826         return NULL;
827     }
828     srcControl = inCertReq->controls[index];
829     newControl->tag = srcControl->tag;
830     rv = SECITEM_CopyItem(NULL, &newControl->derTag, &srcControl->derTag);
831     if (rv != SECSuccess) {
832         goto loser;
833     }
834 
835     rv = SECITEM_CopyItem(NULL, &newControl->derValue,
836                           &srcControl->derValue);
837     if (rv != SECSuccess) {
838         goto loser;
839     }
840     /* Copy over the PKIArchiveOptions stuff */
841     switch (srcControl->tag) {
842         case SEC_OID_PKIX_REGCTRL_REGTOKEN:
843         case SEC_OID_PKIX_REGCTRL_AUTHENTICATOR:
844             /* No further processing necessary for these types. */
845             rv = SECSuccess;
846             break;
847         case SEC_OID_PKIX_REGCTRL_OLD_CERT_ID:
848         case SEC_OID_PKIX_REGCTRL_PKIPUBINFO:
849         case SEC_OID_PKIX_REGCTRL_PROTOCOL_ENC_KEY:
850             /* These aren't supported yet, so no post-processing will
851              * be done at this time.  But we don't want to fail in case
852              * we read in DER that has one of these options.
853              */
854             rv = SECSuccess;
855             break;
856         case SEC_OID_PKIX_REGCTRL_PKI_ARCH_OPTIONS:
857             rv = crmf_copy_pkiarchiveoptions(NULL,
858                                              &newControl->value.archiveOptions,
859                                              &srcControl->value.archiveOptions);
860             break;
861         default:
862             rv = SECFailure;
863     }
864     if (rv != SECSuccess) {
865         goto loser;
866     }
867     return newControl;
868 loser:
869     CRMF_DestroyControl(newControl);
870     return NULL;
871 }
872 
873 static SECItem *
crmf_copy_control_value(CRMFControl * inControl)874 crmf_copy_control_value(CRMFControl *inControl)
875 {
876     return SECITEM_DupItem(&inControl->derValue);
877 }
878 
879 SECItem *
CRMF_ControlGetAuthenticatorControlValue(CRMFControl * inControl)880 CRMF_ControlGetAuthenticatorControlValue(CRMFControl *inControl)
881 {
882     PORT_Assert(inControl != NULL);
883     if (inControl == NULL ||
884         CRMF_ControlGetControlType(inControl) != crmfAuthenticatorControl) {
885         return NULL;
886     }
887     return crmf_copy_control_value(inControl);
888 }
889 
890 CRMFControlType
CRMF_ControlGetControlType(CRMFControl * inControl)891 CRMF_ControlGetControlType(CRMFControl *inControl)
892 {
893     CRMFControlType retType;
894 
895     PORT_Assert(inControl != NULL);
896     switch (inControl->tag) {
897         case SEC_OID_PKIX_REGCTRL_REGTOKEN:
898             retType = crmfRegTokenControl;
899             break;
900         case SEC_OID_PKIX_REGCTRL_AUTHENTICATOR:
901             retType = crmfAuthenticatorControl;
902             break;
903         case SEC_OID_PKIX_REGCTRL_PKIPUBINFO:
904             retType = crmfPKIPublicationInfoControl;
905             break;
906         case SEC_OID_PKIX_REGCTRL_PKI_ARCH_OPTIONS:
907             retType = crmfPKIArchiveOptionsControl;
908             break;
909         case SEC_OID_PKIX_REGCTRL_OLD_CERT_ID:
910             retType = crmfOldCertIDControl;
911             break;
912         case SEC_OID_PKIX_REGCTRL_PROTOCOL_ENC_KEY:
913             retType = crmfProtocolEncrKeyControl;
914             break;
915         default:
916             retType = crmfNoControl;
917     }
918     return retType;
919 }
920 
921 CRMFPKIArchiveOptions *
CRMF_ControlGetPKIArchiveOptions(CRMFControl * inControl)922 CRMF_ControlGetPKIArchiveOptions(CRMFControl *inControl)
923 {
924     CRMFPKIArchiveOptions *newOpt = NULL;
925     SECStatus rv;
926 
927     PORT_Assert(inControl != NULL);
928     if (inControl == NULL ||
929         CRMF_ControlGetControlType(inControl) != crmfPKIArchiveOptionsControl) {
930         goto loser;
931     }
932     newOpt = PORT_ZNew(CRMFPKIArchiveOptions);
933     if (newOpt == NULL) {
934         goto loser;
935     }
936     rv = crmf_copy_pkiarchiveoptions(NULL, newOpt,
937                                      &inControl->value.archiveOptions);
938     if (rv != SECSuccess) {
939         goto loser;
940     }
941 
942 loser:
943     if (newOpt != NULL) {
944         CRMF_DestroyPKIArchiveOptions(newOpt);
945     }
946     return NULL;
947 }
948 
949 SECItem *
CRMF_ControlGetRegTokenControlValue(CRMFControl * inControl)950 CRMF_ControlGetRegTokenControlValue(CRMFControl *inControl)
951 {
952     PORT_Assert(inControl != NULL);
953     if (inControl == NULL ||
954         CRMF_ControlGetControlType(inControl) != crmfRegTokenControl) {
955         return NULL;
956     }
957     return crmf_copy_control_value(inControl);
958     ;
959 }
960 
961 CRMFCertExtension *
CRMF_CertRequestGetExtensionAtIndex(CRMFCertRequest * inCertReq,int index)962 CRMF_CertRequestGetExtensionAtIndex(CRMFCertRequest *inCertReq,
963                                     int index)
964 {
965     int numExtensions;
966 
967     PORT_Assert(inCertReq != NULL);
968     numExtensions = CRMF_CertRequestGetNumberOfExtensions(inCertReq);
969     if (index >= numExtensions || index < 0) {
970         return NULL;
971     }
972     return crmf_copy_cert_extension(NULL,
973                                     inCertReq->certTemplate.extensions[index]);
974 }
975