security/nss/lib/crmf/crmfreq.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial