PageRenderTime 78ms CodeModel.GetById 19ms app.highlight 54ms RepoModel.GetById 1ms app.codeStats 0ms

/security/nss/lib/crmf/crmfreq.c

http://github.com/zpao/v8monkey
C | 702 lines | 580 code | 64 blank | 58 comment | 139 complexity | cba3eb9002ece57a5b635e2cb9823e00 MD5 | raw file
  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#include "crmf.h"
 39#include "crmfi.h"
 40#include "keyhi.h"
 41#include "secder.h"
 42
 43/*
 44 * Macro that returns PR_TRUE if the pointer is not NULL.
 45 * If the pointer is NULL, then the macro will return PR_FALSE.
 46 */
 47#define IS_NOT_NULL(ptr) ((ptr) == NULL) ? PR_FALSE : PR_TRUE
 48
 49const unsigned char hexTrue  = 0xff;
 50const unsigned char hexFalse = 0x00;
 51
 52
 53SECStatus
 54crmf_encode_integer(PRArenaPool *poolp, SECItem *dest, long value) 
 55{
 56    SECItem *dummy;
 57
 58    dummy = SEC_ASN1EncodeInteger(poolp, dest, value);
 59    PORT_Assert (dummy == dest);
 60    if (dummy == NULL) {
 61        return SECFailure;
 62    }
 63    return SECSuccess;
 64}
 65
 66SECStatus
 67crmf_encode_unsigned_integer(PRArenaPool *poolp, SECItem *dest, 
 68                             unsigned long value) 
 69{
 70    SECItem *dummy;
 71
 72    dummy = SEC_ASN1EncodeUnsignedInteger(poolp, dest, value);
 73    PORT_Assert (dummy == dest);
 74    if (dummy != dest) {
 75        return SECFailure;
 76    }
 77    return SECSuccess;
 78}
 79
 80static SECStatus
 81crmf_copy_secitem (PRArenaPool *poolp, SECItem *dest, SECItem *src)
 82{
 83    return  SECITEM_CopyItem (poolp, dest, src); 
 84}
 85
 86PRBool
 87CRMF_DoesRequestHaveField (CRMFCertRequest       *inCertReq, 
 88			   CRMFCertTemplateField  inField)
 89{
 90  
 91    PORT_Assert(inCertReq != NULL);
 92    if (inCertReq == NULL) {
 93        return PR_FALSE;
 94    }
 95    switch (inField) {
 96    case crmfVersion:
 97        return inCertReq->certTemplate.version.data != NULL;
 98    case crmfSerialNumber:
 99        return inCertReq->certTemplate.serialNumber.data != NULL;
100    case crmfSigningAlg:
101        return inCertReq->certTemplate.signingAlg != NULL;
102    case crmfIssuer:
103        return inCertReq->certTemplate.issuer != NULL;
104    case crmfValidity:
105        return inCertReq->certTemplate.validity != NULL;
106    case crmfSubject:
107        return inCertReq->certTemplate.subject != NULL;
108    case crmfPublicKey:
109        return inCertReq->certTemplate.publicKey != NULL;
110    case crmfIssuerUID:
111        return inCertReq->certTemplate.issuerUID.data != NULL;
112    case crmfSubjectUID:
113        return inCertReq->certTemplate.subjectUID.data != NULL;
114    case crmfExtension:
115        return CRMF_CertRequestGetNumberOfExtensions(inCertReq) != 0;
116    }
117    return PR_FALSE;
118}
119
120CRMFCertRequest *
121CRMF_CreateCertRequest (PRUint32 inRequestID)
122{
123    PRArenaPool     *poolp;
124    CRMFCertRequest *certReq;
125    SECStatus        rv;
126    
127    poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
128    if (poolp == NULL) {
129        goto loser;
130    }
131    
132    certReq=PORT_ArenaZNew(poolp,CRMFCertRequest);
133    if (certReq == NULL) {
134        goto loser;
135    }
136
137    certReq->poolp = poolp;
138    certReq->requestID = inRequestID;
139    
140    rv = crmf_encode_unsigned_integer(poolp, &(certReq->certReqId), 
141                                      inRequestID);
142    if (rv != SECSuccess) {
143        goto loser;
144    }
145
146    return certReq;
147 loser:
148    if (poolp) {
149        PORT_FreeArena(poolp, PR_FALSE);
150    }
151    return NULL;
152}
153
154SECStatus
155CRMF_DestroyCertRequest(CRMFCertRequest *inCertReq)
156{
157    PORT_Assert(inCertReq != NULL);
158    if (inCertReq != NULL) {
159        if (inCertReq->certTemplate.extensions) {
160	    PORT_Free(inCertReq->certTemplate.extensions);
161	}
162	if (inCertReq->controls) {
163	    /* Right now we don't support EnveloppedData option,
164	     * so we won't go through and delete each occurrence of 
165	     * an EnveloppedData in the control.
166	     */
167	    PORT_Free(inCertReq->controls);
168	}
169	if (inCertReq->poolp) {
170	    PORT_FreeArena(inCertReq->poolp, PR_TRUE);
171	}
172    }
173    return SECSuccess;
174}
175
176static SECStatus
177crmf_template_add_version(PRArenaPool *poolp, SECItem *dest, long version)
178{
179    return (crmf_encode_integer(poolp, dest, version));
180}
181
182static SECStatus
183crmf_template_add_serialnumber(PRArenaPool *poolp, SECItem *dest, long serial)
184{
185    return (crmf_encode_integer(poolp, dest, serial));
186}
187
188SECStatus
189crmf_template_copy_secalg (PRArenaPool *poolp, SECAlgorithmID **dest, 
190			   SECAlgorithmID* src)
191{
192    SECStatus         rv;
193    void             *mark = NULL;
194    SECAlgorithmID   *mySecAlg;
195
196    if (!poolp) {
197        PORT_SetError(SEC_ERROR_INVALID_ARGS);
198        return SECFailure;
199    }
200
201    mark = PORT_ArenaMark(poolp);
202    *dest = mySecAlg = PORT_ArenaZNew(poolp, SECAlgorithmID);
203    if (mySecAlg == NULL) {
204        goto loser;
205    }
206    rv = SECOID_CopyAlgorithmID(poolp, mySecAlg, src);
207    if (rv != SECSuccess) {
208        goto loser;
209    }
210    if (mark) {
211        PORT_ArenaUnmark(poolp, mark);
212    }
213    return SECSuccess;
214
215 loser:
216    *dest = NULL;
217    if (mark) {
218        PORT_ArenaRelease(poolp, mark);
219    }
220    return SECFailure;
221}
222
223SECStatus
224crmf_copy_cert_name(PRArenaPool *poolp, CERTName **dest, 
225		    CERTName *src)
226{
227    CERTName *newName;
228    SECStatus rv;
229    void     *mark;
230
231    mark = PORT_ArenaMark(poolp);
232    *dest = newName = PORT_ArenaZNew(poolp, CERTName);
233    if (newName == NULL) {
234        goto loser;
235    }
236
237    rv = CERT_CopyName(poolp, newName, src);
238    if (rv != SECSuccess) {
239      goto loser;
240    }
241    PORT_ArenaUnmark(poolp, mark);
242    return SECSuccess;
243 loser:
244    PORT_ArenaRelease(poolp, mark);
245    *dest = NULL;
246    return SECFailure;
247}
248
249static SECStatus
250crmf_template_add_issuer (PRArenaPool *poolp, CERTName **dest, 
251			  CERTName* issuerName)
252{
253    return crmf_copy_cert_name(poolp, dest, issuerName);
254}
255
256
257static SECStatus
258crmf_template_add_validity (PRArenaPool *poolp, CRMFOptionalValidity **dest,
259			    CRMFValidityCreationInfo *info)
260{
261    SECStatus             rv;
262    void                 *mark; 
263    CRMFOptionalValidity *myValidity;
264
265    /*First off, let's make sure at least one of the two fields is present*/
266    if (!info  || (!info->notBefore && !info->notAfter)) {
267        return SECFailure;
268    }
269    mark = PORT_ArenaMark (poolp);
270    *dest = myValidity = PORT_ArenaZNew(poolp, CRMFOptionalValidity);
271    if (myValidity == NULL) {
272        goto loser;
273    }
274
275    if (info->notBefore) {
276        rv = DER_EncodeTimeChoice (poolp, &myValidity->notBefore, 
277				  *info->notBefore);
278	if (rv != SECSuccess) {
279	    goto loser;
280	}
281    }
282    if (info->notAfter) {
283        rv = DER_EncodeTimeChoice (poolp, &myValidity->notAfter,
284				  *info->notAfter);
285	if (rv != SECSuccess) {
286	    goto loser;
287	}
288    }
289    PORT_ArenaUnmark(poolp, mark);
290    return SECSuccess;
291 loser:
292    PORT_ArenaRelease(poolp, mark);
293    *dest = NULL;
294    return SECFailure;
295}
296
297static SECStatus
298crmf_template_add_subject (PRArenaPool *poolp, CERTName **dest,
299			   CERTName *subject)
300{
301    return crmf_copy_cert_name(poolp, dest, subject);
302}
303
304SECStatus
305crmf_template_add_public_key(PRArenaPool *poolp, 
306			     CERTSubjectPublicKeyInfo **dest,
307			     CERTSubjectPublicKeyInfo  *pubKey)
308{
309    CERTSubjectPublicKeyInfo *spki;
310    SECStatus rv;
311
312    *dest = spki = (poolp == NULL) ?
313                              PORT_ZNew(CERTSubjectPublicKeyInfo) :
314                              PORT_ArenaZNew (poolp, CERTSubjectPublicKeyInfo);
315    if (spki == NULL) {
316        goto loser;
317    }
318    rv = SECKEY_CopySubjectPublicKeyInfo (poolp, spki, pubKey);
319    if (rv != SECSuccess) {
320        goto loser;
321    }
322    return SECSuccess;
323 loser:
324    if (poolp == NULL && spki != NULL) {
325        SECKEY_DestroySubjectPublicKeyInfo(spki);
326    }
327    *dest = NULL;
328    return SECFailure;
329}
330
331static SECStatus
332crmf_copy_bitstring (PRArenaPool *poolp, SECItem *dest, const SECItem *src)
333{
334    SECStatus rv;
335    SECItem  byteSrc;
336    
337    byteSrc = *src;
338    byteSrc.len = CRMF_BITS_TO_BYTES(byteSrc.len);
339    rv = crmf_copy_secitem(poolp, dest, &byteSrc);
340    dest->len = src->len;
341    return rv;
342}
343
344static SECStatus
345crmf_template_add_issuer_uid(PRArenaPool *poolp, SECItem *dest,
346			     const SECItem *issuerUID)
347{
348    return crmf_copy_bitstring (poolp, dest, issuerUID);
349}
350
351static SECStatus
352crmf_template_add_subject_uid(PRArenaPool *poolp, SECItem *dest, 
353			      const SECItem *subjectUID)
354{
355    return crmf_copy_bitstring (poolp, dest, subjectUID);
356}
357
358static void
359crmf_zeroize_new_extensions (CRMFCertExtension **extensions,
360			     int numToZeroize) 
361{
362    PORT_Memset((void*)extensions, 0, sizeof(CERTCertExtension*)*numToZeroize);
363}
364
365/*
366 * The strategy for adding templates will differ from all the other
367 * attributes in the template.  First, we want to allow the client
368 * of this API to set extensions more than just once.  So we will
369 * need the ability grow the array of extensions.  Since arenas don't
370 * give us the realloc function, we'll use the generic PORT_* functions
371 * to allocate the array of pointers *ONLY*.  Then we will allocate each
372 * individual extension from the arena that comes along with the certReq
373 * structure that owns this template.
374 */
375static SECStatus
376crmf_template_add_extensions(PRArenaPool *poolp, CRMFCertTemplate *inTemplate,
377			     CRMFCertExtCreationInfo *extensions)
378{
379    void               *mark;
380    int                 newSize, oldSize, i;
381    SECStatus           rv;
382    CRMFCertExtension **extArray;
383    CRMFCertExtension  *newExt, *currExt;
384
385    mark = PORT_ArenaMark(poolp);
386    if (inTemplate->extensions == NULL) {
387        newSize = extensions->numExtensions;
388        extArray = PORT_ZNewArray(CRMFCertExtension*,newSize+1);
389    } else {
390        newSize = inTemplate->numExtensions + extensions->numExtensions;
391        extArray = PORT_Realloc(inTemplate->extensions, 
392				sizeof(CRMFCertExtension*)*(newSize+1));
393    }
394    if (extArray == NULL) {
395        goto loser;
396    }
397    oldSize                   = inTemplate->numExtensions;
398    inTemplate->extensions    = extArray;
399    inTemplate->numExtensions = newSize;
400    for (i=oldSize; i < newSize; i++) {
401        newExt = PORT_ArenaZNew(poolp, CRMFCertExtension);
402	if (newExt == NULL) {
403	    goto loser2;
404	}
405	currExt = extensions->extensions[i-oldSize];
406	rv = crmf_copy_secitem(poolp, &(newExt->id), &(currExt->id));
407	if (rv != SECSuccess) {
408	    goto loser2;
409	}
410	rv = crmf_copy_secitem(poolp, &(newExt->critical),
411			       &(currExt->critical));
412	if (rv != SECSuccess) {
413	    goto loser2;
414	}
415	rv = crmf_copy_secitem(poolp, &(newExt->value), &(currExt->value));
416	if (rv != SECSuccess) {
417	    goto loser2;
418	}
419	extArray[i] = newExt;
420    }
421    extArray[newSize] = NULL;
422    PORT_ArenaUnmark(poolp, mark);
423    return SECSuccess;
424 loser2:
425    crmf_zeroize_new_extensions (&(inTemplate->extensions[oldSize]),
426				 extensions->numExtensions);
427    inTemplate->numExtensions = oldSize;
428 loser:
429    PORT_ArenaRelease(poolp, mark);
430    return SECFailure;
431}
432
433SECStatus
434CRMF_CertRequestSetTemplateField(CRMFCertRequest       *inCertReq, 
435				 CRMFCertTemplateField  inTemplateField,
436				 void                  *data)
437{
438    CRMFCertTemplate *certTemplate;
439    PRArenaPool      *poolp;
440    SECStatus         rv = SECFailure;
441    void             *mark;
442    
443
444    if (inCertReq == NULL) {
445        return SECFailure;
446    }
447
448    certTemplate = &(inCertReq->certTemplate);
449
450    poolp = inCertReq->poolp;
451    mark = PORT_ArenaMark(poolp);
452    switch (inTemplateField) {
453    case crmfVersion:
454      rv = crmf_template_add_version(poolp,&(certTemplate->version), 
455				     *(long*)data);
456      break;
457    case crmfSerialNumber:
458      rv = crmf_template_add_serialnumber(poolp, 
459					  &(certTemplate->serialNumber),
460					  *(long*)data);
461      break;
462    case crmfSigningAlg:
463      rv = crmf_template_copy_secalg (poolp, &(certTemplate->signingAlg),
464				      (SECAlgorithmID*)data);
465      break;
466    case crmfIssuer:
467      rv = crmf_template_add_issuer (poolp, &(certTemplate->issuer), 
468				     (CERTName*)data);
469      break;
470    case crmfValidity:
471      rv = crmf_template_add_validity (poolp, &(certTemplate->validity),
472				       (CRMFValidityCreationInfo*)data);
473      break;
474    case crmfSubject:
475      rv = crmf_template_add_subject (poolp, &(certTemplate->subject),
476				      (CERTName*)data);
477      break;
478    case crmfPublicKey:
479      rv = crmf_template_add_public_key(poolp, &(certTemplate->publicKey),
480					(CERTSubjectPublicKeyInfo*)data);
481      break;
482    case crmfIssuerUID:
483      rv = crmf_template_add_issuer_uid(poolp, &(certTemplate->issuerUID),
484					(SECItem*)data);
485      break;
486    case crmfSubjectUID:
487      rv = crmf_template_add_subject_uid(poolp, &(certTemplate->subjectUID),
488					 (SECItem*)data);
489      break;
490    case crmfExtension:
491      rv = crmf_template_add_extensions(poolp, certTemplate, 
492					(CRMFCertExtCreationInfo*)data);
493      break;
494    }
495    if (rv != SECSuccess) {
496        PORT_ArenaRelease(poolp, mark);
497    } else {
498        PORT_ArenaUnmark(poolp, mark);
499    }
500    return rv;
501}
502
503SECStatus
504CRMF_CertReqMsgSetCertRequest (CRMFCertReqMsg  *inCertReqMsg, 
505			       CRMFCertRequest *inCertReq)
506{
507    PORT_Assert (inCertReqMsg != NULL && inCertReq != NULL);
508    if (inCertReqMsg == NULL || inCertReq == NULL) {
509        return SECFailure;
510    }
511    inCertReqMsg->certReq = crmf_copy_cert_request(inCertReqMsg->poolp,
512						   inCertReq);
513    return (inCertReqMsg->certReq == NULL) ? SECFailure : SECSuccess;
514}
515
516CRMFCertReqMsg*
517CRMF_CreateCertReqMsg(void)
518{
519    PRArenaPool    *poolp;
520    CRMFCertReqMsg *reqMsg;
521
522    poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
523    if (poolp == NULL) {
524        goto loser;
525    }
526    reqMsg = PORT_ArenaZNew(poolp, CRMFCertReqMsg);
527    if (reqMsg == NULL) {
528        goto loser;
529    }
530    reqMsg->poolp = poolp;
531    return reqMsg;
532    
533 loser:
534    if (poolp) {
535        PORT_FreeArena(poolp, PR_FALSE);
536    }
537    return NULL;
538}
539
540SECStatus 
541CRMF_DestroyCertReqMsg(CRMFCertReqMsg *inCertReqMsg)
542{
543    PORT_Assert(inCertReqMsg != NULL && inCertReqMsg->poolp != NULL);
544    if (!inCertReqMsg->isDecoded) {
545        if (inCertReqMsg->certReq->certTemplate.extensions != NULL) {
546	    PORT_Free(inCertReqMsg->certReq->certTemplate.extensions);
547	}
548	if (inCertReqMsg->certReq->controls != NULL) {
549	    PORT_Free(inCertReqMsg->certReq->controls);
550	}
551    }
552    PORT_FreeArena(inCertReqMsg->poolp, PR_TRUE);
553    return SECSuccess;
554}
555
556CRMFCertExtension*
557crmf_create_cert_extension(PRArenaPool *poolp, 
558			   SECOidTag    id,
559			   PRBool       isCritical,
560			   SECItem     *data)
561{
562    CRMFCertExtension *newExt;
563    SECOidData        *oidData;
564    SECStatus          rv;
565
566    newExt = (poolp == NULL) ? PORT_ZNew(CRMFCertExtension) :
567                               PORT_ArenaZNew(poolp, CRMFCertExtension);
568    if (newExt == NULL) {
569        goto loser;
570    }
571    oidData = SECOID_FindOIDByTag(id);
572    if (oidData == NULL || 
573	oidData->supportedExtension != SUPPORTED_CERT_EXTENSION) {
574       goto loser;
575    }
576
577    rv = SECITEM_CopyItem(poolp, &(newExt->id), &(oidData->oid));
578    if (rv != SECSuccess) {
579        goto loser;
580    }
581
582    rv = SECITEM_CopyItem(poolp, &(newExt->value), data);
583    if (rv != SECSuccess) {
584        goto loser;
585    }
586
587    if (isCritical) {
588        newExt->critical.data = (poolp == NULL) ? 
589	                                PORT_New(unsigned char) :
590	                                PORT_ArenaNew(poolp, unsigned char);
591	if (newExt->critical.data == NULL) {
592	    goto loser;
593	}
594	newExt->critical.data[0] = hexTrue;
595	newExt->critical.len = 1;
596    }
597    return newExt;
598 loser:
599    if (newExt != NULL && poolp == NULL) {
600        CRMF_DestroyCertExtension(newExt);
601    }
602    return NULL;
603}
604
605CRMFCertExtension *
606CRMF_CreateCertExtension(SECOidTag id,
607			 PRBool    isCritical,
608			 SECItem  *data) 
609{
610    return crmf_create_cert_extension(NULL, id, isCritical, data);
611}
612
613static SECStatus
614crmf_destroy_cert_extension(CRMFCertExtension *inExtension, PRBool freeit)
615{
616    if (inExtension != NULL) {
617        SECITEM_FreeItem (&(inExtension->id), PR_FALSE);
618	SECITEM_FreeItem (&(inExtension->value), PR_FALSE);
619	SECITEM_FreeItem (&(inExtension->critical), PR_FALSE);
620	if (freeit) {
621	    PORT_Free(inExtension);
622	}
623    }
624    return SECSuccess;
625}
626
627SECStatus
628CRMF_DestroyCertExtension(CRMFCertExtension *inExtension)
629{
630    return crmf_destroy_cert_extension(inExtension, PR_TRUE);
631}
632
633SECStatus
634CRMF_DestroyCertReqMessages(CRMFCertReqMessages *inCertReqMsgs) 
635{
636    PORT_Assert (inCertReqMsgs != NULL);
637    if (inCertReqMsgs != NULL) {
638        PORT_FreeArena(inCertReqMsgs->poolp, PR_TRUE);
639    }
640    return SECSuccess;
641}
642
643static PRBool
644crmf_item_has_data(SECItem *item)
645{
646    if (item != NULL && item->data != NULL) {
647        return PR_TRUE;
648    }
649    return PR_FALSE;
650}
651
652PRBool
653CRMF_CertRequestIsFieldPresent(CRMFCertRequest       *inCertReq,
654			       CRMFCertTemplateField  inTemplateField)
655{
656    PRBool             retVal;
657    CRMFCertTemplate *certTemplate;
658
659    PORT_Assert(inCertReq != NULL);
660    if (inCertReq == NULL) {
661        /* This is probably some kind of error, but this is 
662	 * the safest return value for this function.
663	 */
664        return PR_FALSE;
665    }
666    certTemplate = &inCertReq->certTemplate;
667    switch (inTemplateField) {
668    case crmfVersion:
669      retVal = crmf_item_has_data(&certTemplate->version);
670      break;
671    case crmfSerialNumber:
672      retVal = crmf_item_has_data(&certTemplate->serialNumber);
673      break;
674    case crmfSigningAlg:
675      retVal = IS_NOT_NULL(certTemplate->signingAlg);
676      break;
677    case crmfIssuer:
678      retVal = IS_NOT_NULL(certTemplate->issuer);
679      break;
680    case crmfValidity:
681      retVal = IS_NOT_NULL(certTemplate->validity);
682      break;
683    case crmfSubject:
684      retVal = IS_NOT_NULL(certTemplate->subject);
685      break;
686    case crmfPublicKey:
687      retVal = IS_NOT_NULL(certTemplate->publicKey);
688      break;
689    case crmfIssuerUID:
690      retVal = crmf_item_has_data(&certTemplate->issuerUID);
691      break;
692    case crmfSubjectUID:
693      retVal = crmf_item_has_data(&certTemplate->subjectUID);
694      break;
695    case crmfExtension:
696      retVal = IS_NOT_NULL(certTemplate->extensions);
697      break;
698    default:
699      retVal = PR_FALSE;
700    }
701    return retVal;
702}