Back to index

lightning-sunbird  0.9+nobinonly
crmfreq.c
Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 8 -*-*/
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is the Netscape security libraries.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1994-2000
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include "crmf.h"
00039 #include "crmfi.h"
00040 #include "keyhi.h"
00041 #include "secder.h"
00042 
00043 /*
00044  * Macro that returns PR_TRUE if the pointer is not NULL.
00045  * If the pointer is NULL, then the macro will return PR_FALSE.
00046  */
00047 #define IS_NOT_NULL(ptr) ((ptr) == NULL) ? PR_FALSE : PR_TRUE
00048 
00049 const unsigned char hexTrue  = 0xff;
00050 const unsigned char hexFalse = 0x00;
00051 
00052 
00053 SECStatus
00054 crmf_encode_integer(PRArenaPool *poolp, SECItem *dest, long value) 
00055 {
00056     SECItem *dummy;
00057 
00058     dummy = SEC_ASN1EncodeInteger(poolp, dest, value);
00059     PORT_Assert (dummy == dest);
00060     if (dummy == NULL) {
00061         return SECFailure;
00062     }
00063     return SECSuccess;
00064 }
00065 
00066 SECStatus
00067 crmf_encode_unsigned_integer(PRArenaPool *poolp, SECItem *dest, 
00068                              unsigned long value) 
00069 {
00070     SECItem *dummy;
00071 
00072     dummy = SEC_ASN1EncodeUnsignedInteger(poolp, dest, value);
00073     PORT_Assert (dummy == dest);
00074     if (dummy != dest) {
00075         return SECFailure;
00076     }
00077     return SECSuccess;
00078 }
00079 
00080 static SECStatus
00081 crmf_copy_secitem (PRArenaPool *poolp, SECItem *dest, SECItem *src)
00082 {
00083     return  SECITEM_CopyItem (poolp, dest, src); 
00084 }
00085 
00086 PRBool
00087 CRMF_DoesRequestHaveField (CRMFCertRequest       *inCertReq, 
00088                         CRMFCertTemplateField  inField)
00089 {
00090   
00091     PORT_Assert(inCertReq != NULL);
00092     if (inCertReq == NULL) {
00093         return PR_FALSE;
00094     }
00095     switch (inField) {
00096     case crmfVersion:
00097         return inCertReq->certTemplate.version.data != NULL;
00098     case crmfSerialNumber:
00099         return inCertReq->certTemplate.serialNumber.data != NULL;
00100     case crmfSigningAlg:
00101         return inCertReq->certTemplate.signingAlg != NULL;
00102     case crmfIssuer:
00103         return inCertReq->certTemplate.issuer != NULL;
00104     case crmfValidity:
00105         return inCertReq->certTemplate.validity != NULL;
00106     case crmfSubject:
00107         return inCertReq->certTemplate.subject != NULL;
00108     case crmfPublicKey:
00109         return inCertReq->certTemplate.publicKey != NULL;
00110     case crmfIssuerUID:
00111         return inCertReq->certTemplate.issuerUID.data != NULL;
00112     case crmfSubjectUID:
00113         return inCertReq->certTemplate.subjectUID.data != NULL;
00114     case crmfExtension:
00115         return CRMF_CertRequestGetNumberOfExtensions(inCertReq) != 0;
00116     }
00117     return PR_FALSE;
00118 }
00119 
00120 CRMFCertRequest *
00121 CRMF_CreateCertRequest (PRUint32 inRequestID)
00122 {
00123     PRArenaPool     *poolp;
00124     CRMFCertRequest *certReq;
00125     SECStatus        rv;
00126     
00127     poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
00128     if (poolp == NULL) {
00129         goto loser;
00130     }
00131     
00132     certReq=PORT_ArenaZNew(poolp,CRMFCertRequest);
00133     if (certReq == NULL) {
00134         goto loser;
00135     }
00136 
00137     certReq->poolp = poolp;
00138     certReq->requestID = inRequestID;
00139     
00140     rv = crmf_encode_unsigned_integer(poolp, &(certReq->certReqId), 
00141                                       inRequestID);
00142     if (rv != SECSuccess) {
00143         goto loser;
00144     }
00145 
00146     return certReq;
00147  loser:
00148     if (poolp) {
00149         PORT_FreeArena(poolp, PR_FALSE);
00150     }
00151     return NULL;
00152 }
00153 
00154 SECStatus
00155 CRMF_DestroyCertRequest(CRMFCertRequest *inCertReq)
00156 {
00157     PORT_Assert(inCertReq != NULL);
00158     if (inCertReq != NULL) {
00159         if (inCertReq->certTemplate.extensions) {
00160            PORT_Free(inCertReq->certTemplate.extensions);
00161        }
00162        if (inCertReq->controls) {
00163            /* Right now we don't support EnveloppedData option,
00164             * so we won't go through and delete each occurrence of 
00165             * an EnveloppedData in the control.
00166             */
00167            PORT_Free(inCertReq->controls);
00168        }
00169        if (inCertReq->poolp) {
00170            PORT_FreeArena(inCertReq->poolp, PR_TRUE);
00171        }
00172     }
00173     return SECSuccess;
00174 }
00175 
00176 static SECStatus
00177 crmf_template_add_version(PRArenaPool *poolp, SECItem *dest, long version)
00178 {
00179     return (crmf_encode_integer(poolp, dest, version));
00180 }
00181 
00182 static SECStatus
00183 crmf_template_add_serialnumber(PRArenaPool *poolp, SECItem *dest, long serial)
00184 {
00185     return (crmf_encode_integer(poolp, dest, serial));
00186 }
00187 
00188 SECStatus
00189 crmf_template_copy_secalg (PRArenaPool *poolp, SECAlgorithmID **dest, 
00190                         SECAlgorithmID* src)
00191 {
00192     SECStatus         rv;
00193     void             *mark = NULL;
00194     SECAlgorithmID   *mySecAlg;
00195 
00196     if (!poolp) {
00197         PORT_SetError(SEC_ERROR_INVALID_ARGS);
00198         return SECFailure;
00199     }
00200 
00201     mark = PORT_ArenaMark(poolp);
00202     *dest = mySecAlg = PORT_ArenaZNew(poolp, SECAlgorithmID);
00203     if (mySecAlg == NULL) {
00204         goto loser;
00205     }
00206     rv = SECOID_CopyAlgorithmID(poolp, mySecAlg, src);
00207     if (rv != SECSuccess) {
00208         goto loser;
00209     }
00210     if (mark) {
00211         PORT_ArenaUnmark(poolp, mark);
00212     }
00213     return SECSuccess;
00214 
00215  loser:
00216     *dest = NULL;
00217     if (mark) {
00218         PORT_ArenaRelease(poolp, mark);
00219     }
00220     return SECFailure;
00221 }
00222 
00223 SECStatus
00224 crmf_copy_cert_name(PRArenaPool *poolp, CERTName **dest, 
00225                   CERTName *src)
00226 {
00227     CERTName *newName;
00228     SECStatus rv;
00229     void     *mark;
00230 
00231     mark = PORT_ArenaMark(poolp);
00232     *dest = newName = PORT_ArenaZNew(poolp, CERTName);
00233     if (newName == NULL) {
00234         goto loser;
00235     }
00236 
00237     rv = CERT_CopyName(poolp, newName, src);
00238     if (rv != SECSuccess) {
00239       goto loser;
00240     }
00241     PORT_ArenaUnmark(poolp, mark);
00242     return SECSuccess;
00243  loser:
00244     PORT_ArenaRelease(poolp, mark);
00245     *dest = NULL;
00246     return SECFailure;
00247 }
00248 
00249 static SECStatus
00250 crmf_template_add_issuer (PRArenaPool *poolp, CERTName **dest, 
00251                        CERTName* issuerName)
00252 {
00253     return crmf_copy_cert_name(poolp, dest, issuerName);
00254 }
00255 
00256 
00257 static SECStatus
00258 crmf_template_add_validity (PRArenaPool *poolp, CRMFOptionalValidity **dest,
00259                          CRMFValidityCreationInfo *info)
00260 {
00261     SECStatus             rv;
00262     void                 *mark; 
00263     CRMFOptionalValidity *myValidity;
00264 
00265     /*First off, let's make sure at least one of the two fields is present*/
00266     if (!info  || (!info->notBefore && !info->notAfter)) {
00267         return SECFailure;
00268     }
00269     mark = PORT_ArenaMark (poolp);
00270     *dest = myValidity = PORT_ArenaZNew(poolp, CRMFOptionalValidity);
00271     if (myValidity == NULL) {
00272         goto loser;
00273     }
00274 
00275     if (info->notBefore) {
00276         rv = DER_EncodeTimeChoice (poolp, &myValidity->notBefore, 
00277                               *info->notBefore);
00278        if (rv != SECSuccess) {
00279            goto loser;
00280        }
00281     }
00282     if (info->notAfter) {
00283         rv = DER_EncodeTimeChoice (poolp, &myValidity->notAfter,
00284                               *info->notAfter);
00285        if (rv != SECSuccess) {
00286            goto loser;
00287        }
00288     }
00289     PORT_ArenaUnmark(poolp, mark);
00290     return SECSuccess;
00291  loser:
00292     PORT_ArenaRelease(poolp, mark);
00293     *dest = NULL;
00294     return SECFailure;
00295 }
00296 
00297 static SECStatus
00298 crmf_template_add_subject (PRArenaPool *poolp, CERTName **dest,
00299                         CERTName *subject)
00300 {
00301     return crmf_copy_cert_name(poolp, dest, subject);
00302 }
00303 
00304 SECStatus
00305 crmf_template_add_public_key(PRArenaPool *poolp, 
00306                           CERTSubjectPublicKeyInfo **dest,
00307                           CERTSubjectPublicKeyInfo  *pubKey)
00308 {
00309     CERTSubjectPublicKeyInfo *spki;
00310     SECStatus rv;
00311 
00312     *dest = spki = (poolp == NULL) ?
00313                               PORT_ZNew(CERTSubjectPublicKeyInfo) :
00314                               PORT_ArenaZNew (poolp, CERTSubjectPublicKeyInfo);
00315     if (spki == NULL) {
00316         goto loser;
00317     }
00318     rv = SECKEY_CopySubjectPublicKeyInfo (poolp, spki, pubKey);
00319     if (rv != SECSuccess) {
00320         goto loser;
00321     }
00322     return SECSuccess;
00323  loser:
00324     if (poolp == NULL && spki != NULL) {
00325         SECKEY_DestroySubjectPublicKeyInfo(spki);
00326     }
00327     *dest = NULL;
00328     return SECFailure;
00329 }
00330 
00331 static SECStatus
00332 crmf_copy_bitstring (PRArenaPool *poolp, SECItem *dest, const SECItem *src)
00333 {
00334     SECStatus rv;
00335     SECItem  byteSrc;
00336     
00337     byteSrc = *src;
00338     byteSrc.len = CRMF_BITS_TO_BYTES(byteSrc.len);
00339     rv = crmf_copy_secitem(poolp, dest, &byteSrc);
00340     dest->len = src->len;
00341     return rv;
00342 }
00343 
00344 static SECStatus
00345 crmf_template_add_issuer_uid(PRArenaPool *poolp, SECItem *dest,
00346                           const SECItem *issuerUID)
00347 {
00348     return crmf_copy_bitstring (poolp, dest, issuerUID);
00349 }
00350 
00351 static SECStatus
00352 crmf_template_add_subject_uid(PRArenaPool *poolp, SECItem *dest, 
00353                            const SECItem *subjectUID)
00354 {
00355     return crmf_copy_bitstring (poolp, dest, subjectUID);
00356 }
00357 
00358 static void
00359 crmf_zeroize_new_extensions (CRMFCertExtension **extensions,
00360                           int numToZeroize) 
00361 {
00362     PORT_Memset((void*)extensions, 0, sizeof(CERTCertExtension*)*numToZeroize);
00363 }
00364 
00365 /*
00366  * The strategy for adding templates will differ from all the other
00367  * attributes in the template.  First, we want to allow the client
00368  * of this API to set extensions more than just once.  So we will
00369  * need the ability grow the array of extensions.  Since arenas don't
00370  * give us the realloc function, we'll use the generic PORT_* functions
00371  * to allocate the array of pointers *ONLY*.  Then we will allocate each
00372  * individual extension from the arena that comes along with the certReq
00373  * structure that owns this template.
00374  */
00375 static SECStatus
00376 crmf_template_add_extensions(PRArenaPool *poolp, CRMFCertTemplate *inTemplate,
00377                           CRMFCertExtCreationInfo *extensions)
00378 {
00379     void               *mark;
00380     int                 newSize, oldSize, i;
00381     SECStatus           rv;
00382     CRMFCertExtension **extArray;
00383     CRMFCertExtension  *newExt, *currExt;
00384 
00385     mark = PORT_ArenaMark(poolp);
00386     if (inTemplate->extensions == NULL) {
00387         newSize = extensions->numExtensions;
00388         extArray = PORT_ZNewArray(CRMFCertExtension*,newSize+1);
00389     } else {
00390         newSize = inTemplate->numExtensions + extensions->numExtensions;
00391         extArray = PORT_Realloc(inTemplate->extensions, 
00392                             sizeof(CRMFCertExtension*)*(newSize+1));
00393     }
00394     if (extArray == NULL) {
00395         goto loser;
00396     }
00397     oldSize                   = inTemplate->numExtensions;
00398     inTemplate->extensions    = extArray;
00399     inTemplate->numExtensions = newSize;
00400     for (i=oldSize; i < newSize; i++) {
00401         newExt = PORT_ArenaZNew(poolp, CRMFCertExtension);
00402        if (newExt == NULL) {
00403            goto loser2;
00404        }
00405        currExt = extensions->extensions[i-oldSize];
00406        rv = crmf_copy_secitem(poolp, &(newExt->id), &(currExt->id));
00407        if (rv != SECSuccess) {
00408            goto loser2;
00409        }
00410        rv = crmf_copy_secitem(poolp, &(newExt->critical),
00411                             &(currExt->critical));
00412        if (rv != SECSuccess) {
00413            goto loser2;
00414        }
00415        rv = crmf_copy_secitem(poolp, &(newExt->value), &(currExt->value));
00416        if (rv != SECSuccess) {
00417            goto loser2;
00418        }
00419        extArray[i] = newExt;
00420     }
00421     extArray[newSize] = NULL;
00422     PORT_ArenaUnmark(poolp, mark);
00423     return SECSuccess;
00424  loser2:
00425     crmf_zeroize_new_extensions (&(inTemplate->extensions[oldSize]),
00426                              extensions->numExtensions);
00427     inTemplate->numExtensions = oldSize;
00428  loser:
00429     PORT_ArenaRelease(poolp, mark);
00430     return SECFailure;
00431 }
00432 
00433 SECStatus
00434 CRMF_CertRequestSetTemplateField(CRMFCertRequest       *inCertReq, 
00435                              CRMFCertTemplateField  inTemplateField,
00436                              void                  *data)
00437 {
00438     CRMFCertTemplate *certTemplate;
00439     PRArenaPool      *poolp;
00440     SECStatus         rv = SECFailure;
00441     void             *mark;
00442     
00443 
00444     if (inCertReq == NULL) {
00445         return SECFailure;
00446     }
00447 
00448     certTemplate = &(inCertReq->certTemplate);
00449 
00450     poolp = inCertReq->poolp;
00451     mark = PORT_ArenaMark(poolp);
00452     switch (inTemplateField) {
00453     case crmfVersion:
00454       rv = crmf_template_add_version(poolp,&(certTemplate->version), 
00455                                  *(long*)data);
00456       break;
00457     case crmfSerialNumber:
00458       rv = crmf_template_add_serialnumber(poolp, 
00459                                      &(certTemplate->serialNumber),
00460                                      *(long*)data);
00461       break;
00462     case crmfSigningAlg:
00463       rv = crmf_template_copy_secalg (poolp, &(certTemplate->signingAlg),
00464                                   (SECAlgorithmID*)data);
00465       break;
00466     case crmfIssuer:
00467       rv = crmf_template_add_issuer (poolp, &(certTemplate->issuer), 
00468                                  (CERTName*)data);
00469       break;
00470     case crmfValidity:
00471       rv = crmf_template_add_validity (poolp, &(certTemplate->validity),
00472                                    (CRMFValidityCreationInfo*)data);
00473       break;
00474     case crmfSubject:
00475       rv = crmf_template_add_subject (poolp, &(certTemplate->subject),
00476                                   (CERTName*)data);
00477       break;
00478     case crmfPublicKey:
00479       rv = crmf_template_add_public_key(poolp, &(certTemplate->publicKey),
00480                                    (CERTSubjectPublicKeyInfo*)data);
00481       break;
00482     case crmfIssuerUID:
00483       rv = crmf_template_add_issuer_uid(poolp, &(certTemplate->issuerUID),
00484                                    (SECItem*)data);
00485       break;
00486     case crmfSubjectUID:
00487       rv = crmf_template_add_subject_uid(poolp, &(certTemplate->subjectUID),
00488                                     (SECItem*)data);
00489       break;
00490     case crmfExtension:
00491       rv = crmf_template_add_extensions(poolp, certTemplate, 
00492                                    (CRMFCertExtCreationInfo*)data);
00493       break;
00494     }
00495     if (rv != SECSuccess) {
00496         PORT_ArenaRelease(poolp, mark);
00497     } else {
00498         PORT_ArenaUnmark(poolp, mark);
00499     }
00500     return rv;
00501 }
00502 
00503 SECStatus
00504 CRMF_CertReqMsgSetCertRequest (CRMFCertReqMsg  *inCertReqMsg, 
00505                             CRMFCertRequest *inCertReq)
00506 {
00507     PORT_Assert (inCertReqMsg != NULL && inCertReq != NULL);
00508     if (inCertReqMsg == NULL || inCertReq == NULL) {
00509         return SECFailure;
00510     }
00511     inCertReqMsg->certReq = crmf_copy_cert_request(inCertReqMsg->poolp,
00512                                              inCertReq);
00513     return (inCertReqMsg->certReq == NULL) ? SECFailure : SECSuccess;
00514 }
00515 
00516 CRMFCertReqMsg*
00517 CRMF_CreateCertReqMsg(void)
00518 {
00519     PRArenaPool    *poolp;
00520     CRMFCertReqMsg *reqMsg;
00521 
00522     poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
00523     if (poolp == NULL) {
00524         goto loser;
00525     }
00526     reqMsg = PORT_ArenaZNew(poolp, CRMFCertReqMsg);
00527     if (reqMsg == NULL) {
00528         goto loser;
00529     }
00530     reqMsg->poolp = poolp;
00531     return reqMsg;
00532     
00533  loser:
00534     if (poolp) {
00535         PORT_FreeArena(poolp, PR_FALSE);
00536     }
00537     return NULL;
00538 }
00539 
00540 SECStatus 
00541 CRMF_DestroyCertReqMsg(CRMFCertReqMsg *inCertReqMsg)
00542 {
00543     PORT_Assert(inCertReqMsg != NULL && inCertReqMsg->poolp != NULL);
00544     if (!inCertReqMsg->isDecoded) {
00545         if (inCertReqMsg->certReq->certTemplate.extensions != NULL) {
00546            PORT_Free(inCertReqMsg->certReq->certTemplate.extensions);
00547        }
00548        if (inCertReqMsg->certReq->controls != NULL) {
00549            PORT_Free(inCertReqMsg->certReq->controls);
00550        }
00551     }
00552     PORT_FreeArena(inCertReqMsg->poolp, PR_TRUE);
00553     return SECSuccess;
00554 }
00555 
00556 CRMFCertExtension*
00557 crmf_create_cert_extension(PRArenaPool *poolp, 
00558                         SECOidTag    id,
00559                         PRBool       isCritical,
00560                         SECItem     *data)
00561 {
00562     CRMFCertExtension *newExt;
00563     SECOidData        *oidData;
00564     SECStatus          rv;
00565 
00566     newExt = (poolp == NULL) ? PORT_ZNew(CRMFCertExtension) :
00567                                PORT_ArenaZNew(poolp, CRMFCertExtension);
00568     if (newExt == NULL) {
00569         goto loser;
00570     }
00571     oidData = SECOID_FindOIDByTag(id);
00572     if (oidData == NULL || 
00573        oidData->supportedExtension != SUPPORTED_CERT_EXTENSION) {
00574        goto loser;
00575     }
00576 
00577     rv = SECITEM_CopyItem(poolp, &(newExt->id), &(oidData->oid));
00578     if (rv != SECSuccess) {
00579         goto loser;
00580     }
00581 
00582     rv = SECITEM_CopyItem(poolp, &(newExt->value), data);
00583     if (rv != SECSuccess) {
00584         goto loser;
00585     }
00586 
00587     if (isCritical) {
00588         newExt->critical.data = (poolp == NULL) ? 
00589                                        PORT_New(unsigned char) :
00590                                        PORT_ArenaNew(poolp, unsigned char);
00591        if (newExt->critical.data == NULL) {
00592            goto loser;
00593        }
00594        newExt->critical.data[0] = hexTrue;
00595        newExt->critical.len = 1;
00596     }
00597     return newExt;
00598  loser:
00599     if (newExt != NULL && poolp == NULL) {
00600         CRMF_DestroyCertExtension(newExt);
00601     }
00602     return NULL;
00603 }
00604 
00605 CRMFCertExtension *
00606 CRMF_CreateCertExtension(SECOidTag id,
00607                       PRBool    isCritical,
00608                       SECItem  *data) 
00609 {
00610     return crmf_create_cert_extension(NULL, id, isCritical, data);
00611 }
00612 
00613 SECStatus
00614 crmf_destroy_cert_extension(CRMFCertExtension *inExtension, PRBool freeit)
00615 {
00616     if (inExtension != NULL) {
00617         SECITEM_FreeItem (&(inExtension->id), PR_FALSE);
00618        SECITEM_FreeItem (&(inExtension->value), PR_FALSE);
00619        SECITEM_FreeItem (&(inExtension->critical), PR_FALSE);
00620        if (freeit) {
00621            PORT_Free(inExtension);
00622        }
00623     }
00624     return SECSuccess;
00625 }
00626 
00627 SECStatus
00628 CRMF_DestroyCertExtension(CRMFCertExtension *inExtension)
00629 {
00630     return crmf_destroy_cert_extension(inExtension, PR_TRUE);
00631 }
00632 
00633 SECStatus
00634 CRMF_DestroyCertReqMessages(CRMFCertReqMessages *inCertReqMsgs) 
00635 {
00636     PORT_Assert (inCertReqMsgs != NULL);
00637     if (inCertReqMsgs != NULL) {
00638         PORT_FreeArena(inCertReqMsgs->poolp, PR_TRUE);
00639     }
00640     return SECSuccess;
00641 }
00642 
00643 static PRBool
00644 crmf_item_has_data(SECItem *item)
00645 {
00646     if (item != NULL && item->data != NULL) {
00647         return PR_TRUE;
00648     }
00649     return PR_FALSE;
00650 }
00651 
00652 PRBool
00653 CRMF_CertRequestIsFieldPresent(CRMFCertRequest       *inCertReq,
00654                             CRMFCertTemplateField  inTemplateField)
00655 {
00656     PRBool             retVal;
00657     CRMFCertTemplate *certTemplate;
00658 
00659     PORT_Assert(inCertReq != NULL);
00660     if (inCertReq == NULL) {
00661         /* This is probably some kind of error, but this is 
00662         * the safest return value for this function.
00663         */
00664         return PR_FALSE;
00665     }
00666     certTemplate = &inCertReq->certTemplate;
00667     switch (inTemplateField) {
00668     case crmfVersion:
00669       retVal = crmf_item_has_data(&certTemplate->version);
00670       break;
00671     case crmfSerialNumber:
00672       retVal = crmf_item_has_data(&certTemplate->serialNumber);
00673       break;
00674     case crmfSigningAlg:
00675       retVal = IS_NOT_NULL(certTemplate->signingAlg);
00676       break;
00677     case crmfIssuer:
00678       retVal = IS_NOT_NULL(certTemplate->issuer);
00679       break;
00680     case crmfValidity:
00681       retVal = IS_NOT_NULL(certTemplate->validity);
00682       break;
00683     case crmfSubject:
00684       retVal = IS_NOT_NULL(certTemplate->subject);
00685       break;
00686     case crmfPublicKey:
00687       retVal = IS_NOT_NULL(certTemplate->publicKey);
00688       break;
00689     case crmfIssuerUID:
00690       retVal = crmf_item_has_data(&certTemplate->issuerUID);
00691       break;
00692     case crmfSubjectUID:
00693       retVal = crmf_item_has_data(&certTemplate->subjectUID);
00694       break;
00695     case crmfExtension:
00696       retVal = IS_NOT_NULL(certTemplate->extensions);
00697       break;
00698     default:
00699       retVal = PR_FALSE;
00700     }
00701     return retVal;
00702 }