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