Back to index

lightning-sunbird  0.9+nobinonly
certificate.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Netscape security libraries.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 1994-2000
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 #ifdef DEBUG
00038 static const char CVS_ID[] = "@(#) $RCSfile: certificate.c,v $ $Revision: 1.56.2.4 $ $Date: 2007/11/16 05:25:08 $";
00039 #endif /* DEBUG */
00040 
00041 #ifndef NSSPKI_H
00042 #include "nsspki.h"
00043 #endif /* NSSPKI_H */
00044 
00045 #ifndef PKIT_H
00046 #include "pkit.h"
00047 #endif /* PKIT_H */
00048 
00049 #ifndef PKIM_H
00050 #include "pkim.h"
00051 #endif /* PKIM_H */
00052 
00053 #ifndef DEV_H
00054 #include "dev.h"
00055 #endif /* DEV_H */
00056 
00057 #include "pkistore.h"
00058 
00059 #include "pki3hack.h"
00060 #include "pk11func.h"
00061 #include "hasht.h"
00062 
00063 #ifndef BASE_H
00064 #include "base.h"
00065 #endif /* BASE_H */
00066 
00067 extern const NSSError NSS_ERROR_NOT_FOUND;
00068 
00069 /* Creates a certificate from a base object */
00070 NSS_IMPLEMENT NSSCertificate *
00071 nssCertificate_Create (
00072   nssPKIObject *object
00073 )
00074 {
00075     PRStatus status;
00076     NSSCertificate *rvCert;
00077     /* mark? */
00078     NSSArena *arena = object->arena;
00079     PR_ASSERT(object->instances != NULL && object->numInstances > 0);
00080     PR_ASSERT(object->lockType == nssPKIMonitor);
00081     rvCert = nss_ZNEW(arena, NSSCertificate);
00082     if (!rvCert) {
00083        return (NSSCertificate *)NULL;
00084     }
00085     rvCert->object = *object;
00086     /* XXX should choose instance based on some criteria */
00087     status = nssCryptokiCertificate_GetAttributes(object->instances[0],
00088                                                   NULL,  /* XXX sessionOpt */
00089                                                   arena,
00090                                                   &rvCert->type,
00091                                                   &rvCert->id,
00092                                                   &rvCert->encoding,
00093                                                   &rvCert->issuer,
00094                                                   &rvCert->serial,
00095                                                   &rvCert->subject);
00096     if (status != PR_SUCCESS) {
00097        return (NSSCertificate *)NULL;
00098     }
00099     /* all certs need an encoding value */
00100     if (rvCert->encoding.data == NULL) {
00101        return (NSSCertificate *)NULL;
00102     }
00103     return rvCert;
00104 }
00105 
00106 NSS_IMPLEMENT NSSCertificate *
00107 nssCertificate_AddRef (
00108   NSSCertificate *c
00109 )
00110 {
00111     if (c) {
00112        nssPKIObject_AddRef(&c->object);
00113     }
00114     return c;
00115 }
00116 
00117 NSS_IMPLEMENT PRStatus
00118 nssCertificate_Destroy (
00119   NSSCertificate *c
00120 )
00121 {
00122     nssCertificateStoreTrace lockTrace = {NULL, NULL, PR_FALSE, PR_FALSE};
00123     nssCertificateStoreTrace unlockTrace = {NULL, NULL, PR_FALSE, PR_FALSE};
00124     PRBool locked = PR_FALSE;
00125 
00126     if (c) {
00127        PRUint32 i;
00128        nssDecodedCert *dc = c->decoding;
00129        NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
00130        NSSCryptoContext *cc = c->object.cryptoContext;
00131 
00132        PR_ASSERT(c->object.refCount > 0);
00133 
00134        /* --- LOCK storage --- */
00135        if (cc) {
00136            nssCertificateStore_Lock(cc->certStore, &lockTrace);
00137             locked = PR_TRUE;
00138        } else {
00139            nssTrustDomain_LockCertCache(td);
00140        }
00141        if (PR_AtomicDecrement(&c->object.refCount) == 0) {
00142            /* --- remove cert and UNLOCK storage --- */
00143            if (cc) {
00144               nssCertificateStore_RemoveCertLOCKED(cc->certStore, c);
00145               nssCertificateStore_Unlock(cc->certStore, &lockTrace,
00146                                            &unlockTrace);
00147                 nssCertificateStore_Check(&lockTrace, &unlockTrace);
00148 
00149            } else {
00150               nssTrustDomain_RemoveCertFromCacheLOCKED(td, c);
00151               nssTrustDomain_UnlockCertCache(td);
00152            }
00153            /* free cert data */
00154            for (i=0; i<c->object.numInstances; i++) {
00155               nssCryptokiObject_Destroy(c->object.instances[i]);
00156            }
00157            nssPKIObject_DestroyLock(&c->object);
00158            nssArena_Destroy(c->object.arena);
00159            nssDecodedCert_Destroy(dc);
00160        } else {
00161            /* --- UNLOCK storage --- */
00162            if (cc) {
00163               nssCertificateStore_Unlock(cc->certStore,
00164                                       &lockTrace,
00165                                       &unlockTrace);
00166               nssCertificateStore_Check(&lockTrace, &unlockTrace);
00167            } else {
00168               nssTrustDomain_UnlockCertCache(td);
00169            }
00170        }
00171     }
00172     if (locked) {
00173         nssCertificateStore_Check(&lockTrace, &unlockTrace);
00174     }
00175     return PR_SUCCESS;
00176 }
00177 
00178 NSS_IMPLEMENT PRStatus
00179 NSSCertificate_Destroy (
00180   NSSCertificate *c
00181 )
00182 {
00183     return nssCertificate_Destroy(c);
00184 }
00185 
00186 NSS_IMPLEMENT NSSDER *
00187 nssCertificate_GetEncoding (
00188   NSSCertificate *c
00189 )
00190 {
00191     if (c->encoding.size > 0 && c->encoding.data) {
00192        return &c->encoding;
00193     } else {
00194        return (NSSDER *)NULL;
00195     }
00196 }
00197 
00198 NSS_IMPLEMENT NSSDER *
00199 nssCertificate_GetIssuer (
00200   NSSCertificate *c
00201 )
00202 {
00203     if (c->issuer.size > 0 && c->issuer.data) {
00204        return &c->issuer;
00205     } else {
00206        return (NSSDER *)NULL;
00207     }
00208 }
00209 
00210 NSS_IMPLEMENT NSSDER *
00211 nssCertificate_GetSerialNumber (
00212   NSSCertificate *c
00213 )
00214 {
00215     if (c->serial.size > 0 && c->serial.data) {
00216        return &c->serial;
00217     } else {
00218        return (NSSDER *)NULL;
00219     }
00220 }
00221 
00222 NSS_IMPLEMENT NSSDER *
00223 nssCertificate_GetSubject (
00224   NSSCertificate *c
00225 )
00226 {
00227     if (c->subject.size > 0 && c->subject.data) {
00228        return &c->subject;
00229     } else {
00230        return (NSSDER *)NULL;
00231     }
00232 }
00233 
00234 NSS_IMPLEMENT NSSUTF8 *
00235 nssCertificate_GetNickname (
00236   NSSCertificate *c,
00237   NSSToken *tokenOpt
00238 )
00239 {
00240     return nssPKIObject_GetNicknameForToken(&c->object, tokenOpt);
00241 }
00242 
00243 NSS_IMPLEMENT NSSASCII7 *
00244 nssCertificate_GetEmailAddress (
00245   NSSCertificate *c
00246 )
00247 {
00248     return c->email;
00249 }
00250 
00251 NSS_IMPLEMENT PRStatus
00252 NSSCertificate_DeleteStoredObject (
00253   NSSCertificate *c,
00254   NSSCallback *uhh
00255 )
00256 {
00257     return nssPKIObject_DeleteStoredObject(&c->object, uhh, PR_TRUE);
00258 }
00259 
00260 NSS_IMPLEMENT PRStatus
00261 NSSCertificate_Validate (
00262   NSSCertificate *c,
00263   NSSTime *timeOpt, /* NULL for "now" */
00264   NSSUsage *usage,
00265   NSSPolicies *policiesOpt /* NULL for none */
00266 )
00267 {
00268     nss_SetError(NSS_ERROR_NOT_FOUND);
00269     return PR_FAILURE;
00270 }
00271 
00272 NSS_IMPLEMENT void ** /* void *[] */
00273 NSSCertificate_ValidateCompletely (
00274   NSSCertificate *c,
00275   NSSTime *timeOpt, /* NULL for "now" */
00276   NSSUsage *usage,
00277   NSSPolicies *policiesOpt, /* NULL for none */
00278   void **rvOpt, /* NULL for allocate */
00279   PRUint32 rvLimit, /* zero for no limit */
00280   NSSArena *arenaOpt /* NULL for heap */
00281 )
00282 {
00283     nss_SetError(NSS_ERROR_NOT_FOUND);
00284     return NULL;
00285 }
00286 
00287 NSS_IMPLEMENT PRStatus
00288 NSSCertificate_ValidateAndDiscoverUsagesAndPolicies (
00289   NSSCertificate *c,
00290   NSSTime **notBeforeOutOpt,
00291   NSSTime **notAfterOutOpt,
00292   void *allowedUsages,
00293   void *disallowedUsages,
00294   void *allowedPolicies,
00295   void *disallowedPolicies,
00296   /* more args.. work on this fgmr */
00297   NSSArena *arenaOpt
00298 )
00299 {
00300     nss_SetError(NSS_ERROR_NOT_FOUND);
00301     return PR_FAILURE;
00302 }
00303 
00304 NSS_IMPLEMENT NSSDER *
00305 NSSCertificate_Encode (
00306   NSSCertificate *c,
00307   NSSDER *rvOpt,
00308   NSSArena *arenaOpt
00309 )
00310 {
00311     /* Item, DER, BER are all typedefs now... */
00312     return nssItem_Duplicate((NSSItem *)&c->encoding, arenaOpt, rvOpt);
00313 }
00314 
00315 NSS_IMPLEMENT nssDecodedCert *
00316 nssCertificate_GetDecoding (
00317   NSSCertificate *c
00318 )
00319 {
00320     nssDecodedCert* deco = NULL;
00321     nssPKIObject_Lock(&c->object);
00322     if (!c->decoding) {
00323        deco = nssDecodedCert_Create(NULL, &c->encoding, c->type);
00324        PORT_Assert(!c->decoding); 
00325         c->decoding = deco;
00326     } else {
00327         deco = c->decoding;
00328     }
00329     nssPKIObject_Unlock(&c->object);
00330     return deco;
00331 }
00332 
00333 static NSSCertificate **
00334 filter_subject_certs_for_id (
00335   NSSCertificate **subjectCerts, 
00336   void *id
00337 )
00338 {
00339     NSSCertificate **si;
00340     nssDecodedCert *dcp;
00341     int nextOpenSlot = 0;
00342     int i;
00343     nssCertIDMatch matchLevel = nssCertIDMatch_Unknown;
00344     nssCertIDMatch match;
00345 
00346     /* walk the subject certs */
00347     for (si = subjectCerts; *si; si++) {
00348        dcp = nssCertificate_GetDecoding(*si);
00349        if (!dcp) {
00350            NSSCertificate_Destroy(*si);
00351            continue;
00352        }
00353        match = dcp->matchIdentifier(dcp, id);
00354        switch (match) {
00355        case nssCertIDMatch_Yes:
00356            if (matchLevel == nssCertIDMatch_Unknown) {
00357               /* we have non-definitive matches, forget them */
00358               for (i = 0; i < nextOpenSlot; i++) {
00359                   NSSCertificate_Destroy(subjectCerts[i]);
00360                   subjectCerts[i] = NULL;
00361               }
00362               nextOpenSlot = 0;
00363               /* only keep definitive matches from now on */
00364               matchLevel = nssCertIDMatch_Yes;
00365            }
00366            /* keep the cert */
00367            subjectCerts[nextOpenSlot++] = *si;
00368            break;
00369        case nssCertIDMatch_Unknown:
00370            if (matchLevel == nssCertIDMatch_Unknown) {
00371               /* only have non-definitive matches so far, keep it */
00372               subjectCerts[nextOpenSlot++] = *si;
00373               break;
00374            }
00375            /* else fall through, we have a definitive match already */
00376        case nssCertIDMatch_No:
00377        default:
00378            NSSCertificate_Destroy(*si);
00379            *si = NULL;
00380        }
00381     }
00382     subjectCerts[nextOpenSlot] = NULL;
00383     return subjectCerts;
00384 }
00385 
00386 static NSSCertificate **
00387 filter_certs_for_valid_issuers (
00388   NSSCertificate **certs
00389 )
00390 {
00391     NSSCertificate **cp;
00392     nssDecodedCert *dcp;
00393     int nextOpenSlot = 0;
00394 
00395     for (cp = certs; *cp; cp++) {
00396        dcp = nssCertificate_GetDecoding(*cp);
00397        if (dcp && dcp->isValidIssuer(dcp)) {
00398            certs[nextOpenSlot++] = *cp;
00399        } else {
00400            NSSCertificate_Destroy(*cp);
00401        }
00402     }
00403     certs[nextOpenSlot] = NULL;
00404     return certs;
00405 }
00406 
00407 static NSSCertificate *
00408 find_cert_issuer (
00409   NSSCertificate *c,
00410   NSSTime *timeOpt,
00411   NSSUsage *usage,
00412   NSSPolicies *policiesOpt,
00413   NSSTrustDomain *td,
00414   NSSCryptoContext *cc
00415 )
00416 {
00417     NSSArena *arena;
00418     NSSCertificate **certs = NULL;
00419     NSSCertificate **ccIssuers = NULL;
00420     NSSCertificate **tdIssuers = NULL;
00421     NSSCertificate *issuer = NULL;
00422 
00423     if (!cc)
00424        cc = c->object.cryptoContext;
00425     if (!td)
00426        td = NSSCertificate_GetTrustDomain(c);
00427     arena = nssArena_Create();
00428     if (!arena) {
00429        return (NSSCertificate *)NULL;
00430     }
00431     if (cc) {
00432        ccIssuers = nssCryptoContext_FindCertificatesBySubject(cc,
00433                                                               &c->issuer,
00434                                                               NULL,
00435                                                               0,
00436                                                               arena);
00437     }
00438     if (td)
00439        tdIssuers = nssTrustDomain_FindCertificatesBySubject(td,
00440                                                          &c->issuer,
00441                                                          NULL,
00442                                                          0,
00443                                                          arena);
00444     certs = nssCertificateArray_Join(ccIssuers, tdIssuers);
00445     if (certs) {
00446        nssDecodedCert *dc = NULL;
00447        void *issuerID = NULL;
00448        dc = nssCertificate_GetDecoding(c);
00449        if (dc) {
00450            issuerID = dc->getIssuerIdentifier(dc);
00451        }
00452        /* XXX review based on CERT_FindCertIssuer
00453         * this function is not using the authCertIssuer field as a fallback
00454         * if authority key id does not exist
00455         */
00456        if (issuerID) {
00457            certs = filter_subject_certs_for_id(certs, issuerID);
00458        }
00459        certs = filter_certs_for_valid_issuers(certs);
00460        issuer = nssCertificateArray_FindBestCertificate(certs,
00461                                                         timeOpt,
00462                                                         usage,
00463                                                         policiesOpt);
00464        nssCertificateArray_Destroy(certs);
00465     }
00466     nssArena_Destroy(arena);
00467     return issuer;
00468 }
00469 
00470 /* This function returns the built chain, as far as it gets,
00471 ** even if/when it fails to find an issuer, and returns PR_FAILURE
00472 */
00473 NSS_IMPLEMENT NSSCertificate **
00474 nssCertificate_BuildChain (
00475   NSSCertificate *c,
00476   NSSTime *timeOpt,
00477   NSSUsage *usage,
00478   NSSPolicies *policiesOpt,
00479   NSSCertificate **rvOpt,
00480   PRUint32 rvLimit,
00481   NSSArena *arenaOpt,
00482   PRStatus *statusOpt,
00483   NSSTrustDomain *td,
00484   NSSCryptoContext *cc 
00485 )
00486 {
00487     NSSCertificate **rvChain = NULL;
00488     NSSUsage issuerUsage = *usage;
00489     nssPKIObjectCollection *collection = NULL;
00490     PRUint32  rvCount = 0;
00491     PRStatus  st;
00492     PRStatus  ret = PR_SUCCESS;
00493 
00494     if (!td)
00495        td = NSSCertificate_GetTrustDomain(c);
00496     if (!td || !c || !cc) 
00497        goto loser;
00498     /* bump the usage up to CA level */
00499     issuerUsage.nss3lookingForCA = PR_TRUE;
00500     collection = nssCertificateCollection_Create(td, NULL);
00501     if (!collection)
00502        goto loser;
00503     st = nssPKIObjectCollection_AddObject(collection, (nssPKIObject *)c);
00504     if (st != PR_SUCCESS)
00505        goto loser;
00506     for (rvCount = 1; (!rvLimit || rvCount < rvLimit); ++rvCount) {
00507        CERTCertificate *cCert = STAN_GetCERTCertificate(c);
00508        if (cCert->isRoot) {
00509            /* not including the issuer of the self-signed cert, which is,
00510             * of course, itself
00511             */
00512            break;
00513        }
00514        c = find_cert_issuer(c, timeOpt, &issuerUsage, policiesOpt, td, cc);
00515        if (!c) {
00516            ret = PR_FAILURE;
00517            break;
00518        }
00519        st = nssPKIObjectCollection_AddObject(collection, (nssPKIObject *)c);
00520        nssCertificate_Destroy(c); /* collection has it */
00521        if (st != PR_SUCCESS)
00522            goto loser;
00523     }
00524     rvChain = nssPKIObjectCollection_GetCertificates(collection, 
00525                                                      rvOpt, 
00526                                                      rvLimit, 
00527                                                      arenaOpt);
00528     if (rvChain) {
00529        nssPKIObjectCollection_Destroy(collection);
00530        if (statusOpt) 
00531            *statusOpt = ret;
00532        if (ret != PR_SUCCESS)
00533            nss_SetError(NSS_ERROR_CERTIFICATE_ISSUER_NOT_FOUND);
00534        return rvChain;
00535     }
00536 
00537 loser:
00538     if (collection)
00539        nssPKIObjectCollection_Destroy(collection);
00540     if (statusOpt) 
00541        *statusOpt = PR_FAILURE;
00542     nss_SetError(NSS_ERROR_CERTIFICATE_ISSUER_NOT_FOUND);
00543     return rvChain;
00544 }
00545 
00546 NSS_IMPLEMENT NSSCertificate **
00547 NSSCertificate_BuildChain (
00548   NSSCertificate *c,
00549   NSSTime *timeOpt,
00550   NSSUsage *usage,
00551   NSSPolicies *policiesOpt,
00552   NSSCertificate **rvOpt,
00553   PRUint32 rvLimit, /* zero for no limit */
00554   NSSArena *arenaOpt,
00555   PRStatus *statusOpt,
00556   NSSTrustDomain *td,
00557   NSSCryptoContext *cc 
00558 )
00559 {
00560     return nssCertificate_BuildChain(c, timeOpt, usage, policiesOpt,
00561                                      rvOpt, rvLimit, arenaOpt, statusOpt,
00562                                  td, cc);
00563 }
00564 
00565 NSS_IMPLEMENT NSSCryptoContext *
00566 nssCertificate_GetCryptoContext (
00567   NSSCertificate *c
00568 )
00569 {
00570     return c->object.cryptoContext;
00571 }
00572 
00573 NSS_IMPLEMENT NSSTrustDomain *
00574 nssCertificate_GetTrustDomain (
00575   NSSCertificate *c
00576 )
00577 {
00578     return c->object.trustDomain;
00579 }
00580 
00581 NSS_IMPLEMENT NSSTrustDomain *
00582 NSSCertificate_GetTrustDomain (
00583   NSSCertificate *c
00584 )
00585 {
00586     return nssCertificate_GetTrustDomain(c);
00587 }
00588 
00589 NSS_IMPLEMENT NSSToken *
00590 NSSCertificate_GetToken (
00591   NSSCertificate *c,
00592   PRStatus *statusOpt
00593 )
00594 {
00595     return (NSSToken *)NULL;
00596 }
00597 
00598 NSS_IMPLEMENT NSSSlot *
00599 NSSCertificate_GetSlot (
00600   NSSCertificate *c,
00601   PRStatus *statusOpt
00602 )
00603 {
00604     return (NSSSlot *)NULL;
00605 }
00606 
00607 NSS_IMPLEMENT NSSModule *
00608 NSSCertificate_GetModule (
00609   NSSCertificate *c,
00610   PRStatus *statusOpt
00611 )
00612 {
00613     return (NSSModule *)NULL;
00614 }
00615 
00616 NSS_IMPLEMENT NSSItem *
00617 NSSCertificate_Encrypt (
00618   NSSCertificate *c,
00619   NSSAlgorithmAndParameters *apOpt,
00620   NSSItem *data,
00621   NSSTime *timeOpt,
00622   NSSUsage *usage,
00623   NSSPolicies *policiesOpt,
00624   NSSCallback *uhh,
00625   NSSItem *rvOpt,
00626   NSSArena *arenaOpt
00627 )
00628 {
00629     nss_SetError(NSS_ERROR_NOT_FOUND);
00630     return NULL;
00631 }
00632 
00633 NSS_IMPLEMENT PRStatus
00634 NSSCertificate_Verify (
00635   NSSCertificate *c,
00636   NSSAlgorithmAndParameters *apOpt,
00637   NSSItem *data,
00638   NSSItem *signature,
00639   NSSTime *timeOpt,
00640   NSSUsage *usage,
00641   NSSPolicies *policiesOpt,
00642   NSSCallback *uhh
00643 )
00644 {
00645     nss_SetError(NSS_ERROR_NOT_FOUND);
00646     return PR_FAILURE;
00647 }
00648 
00649 NSS_IMPLEMENT NSSItem *
00650 NSSCertificate_VerifyRecover (
00651   NSSCertificate *c,
00652   NSSAlgorithmAndParameters *apOpt,
00653   NSSItem *signature,
00654   NSSTime *timeOpt,
00655   NSSUsage *usage,
00656   NSSPolicies *policiesOpt,
00657   NSSCallback *uhh,
00658   NSSItem *rvOpt,
00659   NSSArena *arenaOpt
00660 )
00661 {
00662     nss_SetError(NSS_ERROR_NOT_FOUND);
00663     return NULL;
00664 }
00665 
00666 NSS_IMPLEMENT NSSItem *
00667 NSSCertificate_WrapSymmetricKey (
00668   NSSCertificate *c,
00669   NSSAlgorithmAndParameters *apOpt,
00670   NSSSymmetricKey *keyToWrap,
00671   NSSTime *timeOpt,
00672   NSSUsage *usage,
00673   NSSPolicies *policiesOpt,
00674   NSSCallback *uhh,
00675   NSSItem *rvOpt,
00676   NSSArena *arenaOpt
00677 )
00678 {
00679     nss_SetError(NSS_ERROR_NOT_FOUND);
00680     return NULL;
00681 }
00682 
00683 NSS_IMPLEMENT NSSCryptoContext *
00684 NSSCertificate_CreateCryptoContext (
00685   NSSCertificate *c,
00686   NSSAlgorithmAndParameters *apOpt,
00687   NSSTime *timeOpt,
00688   NSSUsage *usage,
00689   NSSPolicies *policiesOpt,
00690   NSSCallback *uhh  
00691 )
00692 {
00693     nss_SetError(NSS_ERROR_NOT_FOUND);
00694     return NULL;
00695 }
00696 
00697 NSS_IMPLEMENT NSSPublicKey *
00698 NSSCertificate_GetPublicKey (
00699   NSSCertificate *c
00700 )
00701 {
00702 #if 0
00703     CK_ATTRIBUTE pubktemplate[] = {
00704        { CKA_CLASS,   NULL, 0 },
00705        { CKA_ID,      NULL, 0 },
00706        { CKA_SUBJECT, NULL, 0 }
00707     };
00708     PRStatus nssrv;
00709     CK_ULONG count = sizeof(pubktemplate) / sizeof(pubktemplate[0]);
00710     NSS_CK_SET_ATTRIBUTE_ITEM(pubktemplate, 0, &g_ck_class_pubkey);
00711     if (c->id.size > 0) {
00712        /* CKA_ID */
00713        NSS_CK_ITEM_TO_ATTRIBUTE(&c->id, &pubktemplate[1]);
00714     } else {
00715        /* failure, yes? */
00716        return (NSSPublicKey *)NULL;
00717     }
00718     if (c->subject.size > 0) {
00719        /* CKA_SUBJECT */
00720        NSS_CK_ITEM_TO_ATTRIBUTE(&c->subject, &pubktemplate[2]);
00721     } else {
00722        /* failure, yes? */
00723        return (NSSPublicKey *)NULL;
00724     }
00725     /* Try the cert's token first */
00726     if (c->token) {
00727        nssrv = nssToken_FindObjectByTemplate(c->token, pubktemplate, count);
00728     }
00729 #endif
00730     /* Try all other key tokens */
00731     return (NSSPublicKey *)NULL;
00732 }
00733 
00734 NSS_IMPLEMENT NSSPrivateKey *
00735 NSSCertificate_FindPrivateKey (
00736   NSSCertificate *c,
00737   NSSCallback *uhh
00738 )
00739 {
00740     nss_SetError(NSS_ERROR_NOT_FOUND);
00741     return NULL;
00742 }
00743 
00744 NSS_IMPLEMENT PRBool
00745 NSSCertificate_IsPrivateKeyAvailable (
00746   NSSCertificate *c,
00747   NSSCallback *uhh,
00748   PRStatus *statusOpt
00749 )
00750 {
00751     PRBool isUser = PR_FALSE;
00752     nssCryptokiObject **ip;
00753     nssCryptokiObject **instances = nssPKIObject_GetInstances(&c->object);
00754     if (!instances) {
00755        return PR_FALSE;
00756     }
00757     for (ip = instances; *ip; ip++) {
00758        nssCryptokiObject *instance = *ip;
00759        if (nssToken_IsPrivateKeyAvailable(instance->token, c, instance)) {
00760            isUser = PR_TRUE;
00761        }
00762     }
00763     nssCryptokiObjectArray_Destroy(instances);
00764     return isUser;
00765 }
00766 
00767 /* sort the subject cert list from newest to oldest */
00768 PRIntn
00769 nssCertificate_SubjectListSort (
00770   void *v1,
00771   void *v2
00772 )
00773 {
00774     NSSCertificate *c1 = (NSSCertificate *)v1;
00775     NSSCertificate *c2 = (NSSCertificate *)v2;
00776     nssDecodedCert *dc1 = nssCertificate_GetDecoding(c1);
00777     nssDecodedCert *dc2 = nssCertificate_GetDecoding(c2);
00778     if (!dc1) {
00779        return dc2 ? 1 : 0;
00780     } else if (!dc2) {
00781        return -1;
00782     } else {
00783        return dc1->isNewerThan(dc1, dc2) ? -1 : 1;
00784     }
00785 }
00786 
00787 NSS_IMPLEMENT PRBool
00788 NSSUserCertificate_IsStillPresent (
00789   NSSUserCertificate *uc,
00790   PRStatus *statusOpt
00791 )
00792 {
00793     nss_SetError(NSS_ERROR_NOT_FOUND);
00794     return PR_FALSE;
00795 }
00796 
00797 NSS_IMPLEMENT NSSItem *
00798 NSSUserCertificate_Decrypt (
00799   NSSUserCertificate *uc,
00800   NSSAlgorithmAndParameters *apOpt,
00801   NSSItem *data,
00802   NSSTime *timeOpt,
00803   NSSUsage *usage,
00804   NSSPolicies *policiesOpt,
00805   NSSCallback *uhh,
00806   NSSItem *rvOpt,
00807   NSSArena *arenaOpt
00808 )
00809 {
00810     nss_SetError(NSS_ERROR_NOT_FOUND);
00811     return NULL;
00812 }
00813 
00814 NSS_IMPLEMENT NSSItem *
00815 NSSUserCertificate_Sign (
00816   NSSUserCertificate *uc,
00817   NSSAlgorithmAndParameters *apOpt,
00818   NSSItem *data,
00819   NSSTime *timeOpt,
00820   NSSUsage *usage,
00821   NSSPolicies *policiesOpt,
00822   NSSCallback *uhh,
00823   NSSItem *rvOpt,
00824   NSSArena *arenaOpt
00825 )
00826 {
00827     nss_SetError(NSS_ERROR_NOT_FOUND);
00828     return NULL;
00829 }
00830 
00831 NSS_IMPLEMENT NSSItem *
00832 NSSUserCertificate_SignRecover (
00833   NSSUserCertificate *uc,
00834   NSSAlgorithmAndParameters *apOpt,
00835   NSSItem *data,
00836   NSSTime *timeOpt,
00837   NSSUsage *usage,
00838   NSSPolicies *policiesOpt,
00839   NSSCallback *uhh,
00840   NSSItem *rvOpt,
00841   NSSArena *arenaOpt
00842 )
00843 {
00844     nss_SetError(NSS_ERROR_NOT_FOUND);
00845     return NULL;
00846 }
00847 
00848 NSS_IMPLEMENT NSSSymmetricKey *
00849 NSSUserCertificate_UnwrapSymmetricKey (
00850   NSSUserCertificate *uc,
00851   NSSAlgorithmAndParameters *apOpt,
00852   NSSItem *wrappedKey,
00853   NSSTime *timeOpt,
00854   NSSUsage *usage,
00855   NSSPolicies *policiesOpt,
00856   NSSCallback *uhh,
00857   NSSItem *rvOpt,
00858   NSSArena *arenaOpt
00859 )
00860 {
00861     nss_SetError(NSS_ERROR_NOT_FOUND);
00862     return NULL;
00863 }
00864 
00865 NSS_IMPLEMENT NSSSymmetricKey *
00866 NSSUserCertificate_DeriveSymmetricKey (
00867   NSSUserCertificate *uc, /* provides private key */
00868   NSSCertificate *c, /* provides public key */
00869   NSSAlgorithmAndParameters *apOpt,
00870   NSSOID *target,
00871   PRUint32 keySizeOpt, /* zero for best allowed */
00872   NSSOperations operations,
00873   NSSCallback *uhh
00874 )
00875 {
00876     nss_SetError(NSS_ERROR_NOT_FOUND);
00877     return NULL;
00878 }
00879 
00880 NSS_IMPLEMENT nssSMIMEProfile *
00881 nssSMIMEProfile_Create (
00882   NSSCertificate *cert,
00883   NSSItem *profileTime,
00884   NSSItem *profileData
00885 )
00886 {
00887     NSSArena *arena;
00888     nssSMIMEProfile *rvProfile;
00889     nssPKIObject *object;
00890     NSSTrustDomain *td = nssCertificate_GetTrustDomain(cert);
00891     NSSCryptoContext *cc = nssCertificate_GetCryptoContext(cert);
00892     arena = nssArena_Create();
00893     if (!arena) {
00894        return NULL;
00895     }
00896     object = nssPKIObject_Create(arena, NULL, td, cc, nssPKILock);
00897     if (!object) {
00898        goto loser;
00899     }
00900     rvProfile = nss_ZNEW(arena, nssSMIMEProfile);
00901     if (!rvProfile) {
00902        goto loser;
00903     }
00904     rvProfile->object = *object;
00905     rvProfile->certificate = cert;
00906     rvProfile->email = nssUTF8_Duplicate(cert->email, arena);
00907     rvProfile->subject = nssItem_Duplicate(&cert->subject, arena, NULL);
00908     if (profileTime) {
00909        rvProfile->profileTime = nssItem_Duplicate(profileTime, arena, NULL);
00910     }
00911     if (profileData) {
00912        rvProfile->profileData = nssItem_Duplicate(profileData, arena, NULL);
00913     }
00914     return rvProfile;
00915 loser:
00916     if (object) nssPKIObject_Destroy(object);
00917     else if (arena)  nssArena_Destroy(arena);
00918     return (nssSMIMEProfile *)NULL;
00919 }
00920 
00921 /* execute a callback function on all members of a cert list */
00922 NSS_EXTERN PRStatus
00923 nssCertificateList_DoCallback (
00924   nssList *certList, 
00925   PRStatus (* callback)(NSSCertificate *c, void *arg),
00926   void *arg
00927 )
00928 {
00929     nssListIterator *certs;
00930     NSSCertificate *cert;
00931     PRStatus nssrv;
00932     certs = nssList_CreateIterator(certList);
00933     for (cert  = (NSSCertificate *)nssListIterator_Start(certs);
00934          cert != (NSSCertificate *)NULL;
00935          cert  = (NSSCertificate *)nssListIterator_Next(certs))
00936     {
00937        nssrv = (*callback)(cert, arg);
00938     }
00939     nssListIterator_Finish(certs);
00940     nssListIterator_Destroy(certs);
00941     return PR_SUCCESS;
00942 }
00943 
00944 static PRStatus add_ref_callback(NSSCertificate *c, void *a)
00945 {
00946     nssCertificate_AddRef(c);
00947     return PR_SUCCESS;
00948 }
00949 
00950 NSS_IMPLEMENT void
00951 nssCertificateList_AddReferences (
00952   nssList *certList
00953 )
00954 {
00955     (void)nssCertificateList_DoCallback(certList, add_ref_callback, NULL);
00956 }
00957 
00958 NSS_IMPLEMENT NSSTrust *
00959 nssTrust_Create (
00960   nssPKIObject *object,
00961   NSSItem *certData
00962 )
00963 {
00964     PRStatus status;
00965     PRUint32 i;
00966     PRUint32 lastTrustOrder, myTrustOrder;
00967     unsigned char sha1_hashcmp[SHA1_LENGTH];
00968     unsigned char sha1_hashin[SHA1_LENGTH];
00969     NSSItem sha1_hash;
00970     NSSTrust *rvt;
00971     nssCryptokiObject *instance;
00972     nssTrustLevel serverAuth, clientAuth, codeSigning, emailProtection;
00973     SECStatus rv; /* Should be stan flavor */
00974     PRBool stepUp;
00975 
00976     lastTrustOrder = 1<<16; /* just make it big */
00977     PR_ASSERT(object->instances != NULL && object->numInstances > 0);
00978     rvt = nss_ZNEW(object->arena, NSSTrust);
00979     if (!rvt) {
00980        return (NSSTrust *)NULL;
00981     }
00982     rvt->object = *object;
00983 
00984     /* should be stan flavor of Hashbuf */
00985     rv = PK11_HashBuf(SEC_OID_SHA1,sha1_hashcmp,certData->data,certData->size);
00986     if (rv != SECSuccess) {
00987        return (NSSTrust *)NULL;
00988     }
00989     sha1_hash.data = sha1_hashin;
00990     sha1_hash.size = sizeof (sha1_hashin);
00991     /* trust has to peek into the base object members */
00992     nssPKIObject_Lock(object);
00993     for (i=0; i<object->numInstances; i++) {
00994        instance = object->instances[i];
00995        myTrustOrder = nssToken_GetTrustOrder(instance->token);
00996        status = nssCryptokiTrust_GetAttributes(instance, NULL,
00997                                           &sha1_hash,
00998                                                &serverAuth,
00999                                                &clientAuth,
01000                                                &codeSigning,
01001                                                &emailProtection,
01002                                                &stepUp);
01003        if (status != PR_SUCCESS) {
01004            nssPKIObject_Unlock(object);
01005            return (NSSTrust *)NULL;
01006        }
01007        if (PORT_Memcmp(sha1_hashin,sha1_hashcmp,SHA1_LENGTH) != 0) {
01008            nssPKIObject_Unlock(object);
01009            return (NSSTrust *)NULL;
01010        }
01011        if (rvt->serverAuth == nssTrustLevel_Unknown ||
01012            myTrustOrder < lastTrustOrder) 
01013        {
01014            rvt->serverAuth = serverAuth;
01015        }
01016        if (rvt->clientAuth == nssTrustLevel_Unknown ||
01017            myTrustOrder < lastTrustOrder) 
01018        {
01019            rvt->clientAuth = clientAuth;
01020        }
01021        if (rvt->emailProtection == nssTrustLevel_Unknown ||
01022            myTrustOrder < lastTrustOrder) 
01023        {
01024            rvt->emailProtection = emailProtection;
01025        }
01026        if (rvt->codeSigning == nssTrustLevel_Unknown ||
01027            myTrustOrder < lastTrustOrder) 
01028        {
01029            rvt->codeSigning = codeSigning;
01030        }
01031        rvt->stepUpApproved = stepUp;
01032        lastTrustOrder = myTrustOrder;
01033     }
01034     nssPKIObject_Unlock(object);
01035     return rvt;
01036 }
01037 
01038 NSS_IMPLEMENT NSSTrust *
01039 nssTrust_AddRef (
01040   NSSTrust *trust
01041 )
01042 {
01043     if (trust) {
01044        nssPKIObject_AddRef(&trust->object);
01045     }
01046     return trust;
01047 }
01048 
01049 NSS_IMPLEMENT PRStatus
01050 nssTrust_Destroy (
01051   NSSTrust *trust
01052 )
01053 {
01054     if (trust) {
01055        (void)nssPKIObject_Destroy(&trust->object);
01056     }
01057     return PR_SUCCESS;
01058 }
01059 
01060 NSS_IMPLEMENT nssSMIMEProfile *
01061 nssSMIMEProfile_AddRef (
01062   nssSMIMEProfile *profile
01063 )
01064 {
01065     if (profile) {
01066        nssPKIObject_AddRef(&profile->object);
01067     }
01068     return profile;
01069 }
01070 
01071 NSS_IMPLEMENT PRStatus
01072 nssSMIMEProfile_Destroy (
01073   nssSMIMEProfile *profile
01074 )
01075 {
01076     if (profile) {
01077        (void)nssPKIObject_Destroy(&profile->object);
01078     }
01079     return PR_SUCCESS;
01080 }
01081 
01082 NSS_IMPLEMENT NSSCRL *
01083 nssCRL_Create (
01084   nssPKIObject *object
01085 )
01086 {
01087     PRStatus status;
01088     NSSCRL *rvCRL;
01089     NSSArena *arena = object->arena;
01090     PR_ASSERT(object->instances != NULL && object->numInstances > 0);
01091     rvCRL = nss_ZNEW(arena, NSSCRL);
01092     if (!rvCRL) {
01093        return (NSSCRL *)NULL;
01094     }
01095     rvCRL->object = *object;
01096     /* XXX should choose instance based on some criteria */
01097     status = nssCryptokiCRL_GetAttributes(object->instances[0],
01098                                           NULL,  /* XXX sessionOpt */
01099                                           arena,
01100                                           &rvCRL->encoding,
01101                                           NULL, /* subject */
01102                                           NULL, /* class */
01103                                           &rvCRL->url,
01104                                           &rvCRL->isKRL);
01105     if (status != PR_SUCCESS) {
01106        return (NSSCRL *)NULL;
01107     }
01108     return rvCRL;
01109 }
01110 
01111 NSS_IMPLEMENT NSSCRL *
01112 nssCRL_AddRef (
01113   NSSCRL *crl
01114 )
01115 {
01116     if (crl) {
01117        nssPKIObject_AddRef(&crl->object);
01118     }
01119     return crl;
01120 }
01121 
01122 NSS_IMPLEMENT PRStatus
01123 nssCRL_Destroy (
01124   NSSCRL *crl
01125 )
01126 {
01127     if (crl) {
01128        (void)nssPKIObject_Destroy(&crl->object);
01129     }
01130     return PR_SUCCESS;
01131 }
01132 
01133 NSS_IMPLEMENT PRStatus
01134 nssCRL_DeleteStoredObject (
01135   NSSCRL *crl,
01136   NSSCallback *uhh
01137 )
01138 {
01139     return nssPKIObject_DeleteStoredObject(&crl->object, uhh, PR_TRUE);
01140 }
01141 
01142 NSS_IMPLEMENT NSSDER *
01143 nssCRL_GetEncoding (
01144   NSSCRL *crl
01145 )
01146 {
01147     if (crl->encoding.data != NULL && crl->encoding.size > 0) {
01148        return &crl->encoding;
01149     } else {
01150        return (NSSDER *)NULL;
01151     }
01152 }