security/nss/lib/pki/certificate.c

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #ifndef NSSPKI_H
     6 #include "nsspki.h"
     7 #endif /* NSSPKI_H */
     9 #ifndef PKIT_H
    10 #include "pkit.h"
    11 #endif /* PKIT_H */
    13 #ifndef PKIM_H
    14 #include "pkim.h"
    15 #endif /* PKIM_H */
    17 #ifndef DEV_H
    18 #include "dev.h"
    19 #endif /* DEV_H */
    21 #include "pkistore.h"
    23 #include "pki3hack.h"
    24 #include "pk11func.h"
    25 #include "hasht.h"
    27 #ifndef BASE_H
    28 #include "base.h"
    29 #endif /* BASE_H */
    31 extern const NSSError NSS_ERROR_NOT_FOUND;
    33 /* Creates a certificate from a base object */
    34 NSS_IMPLEMENT NSSCertificate *
    35 nssCertificate_Create (
    36   nssPKIObject *object
    37 )
    38 {
    39     PRStatus status;
    40     NSSCertificate *rvCert;
    41     nssArenaMark * mark;
    42     NSSArena *arena = object->arena;
    43     PR_ASSERT(object->instances != NULL && object->numInstances > 0);
    44     PR_ASSERT(object->lockType == nssPKIMonitor);
    45     mark = nssArena_Mark(arena);
    46     rvCert = nss_ZNEW(arena, NSSCertificate);
    47     if (!rvCert) {
    48 	return (NSSCertificate *)NULL;
    49     }
    50     rvCert->object = *object;
    51     /* XXX should choose instance based on some criteria */
    52     status = nssCryptokiCertificate_GetAttributes(object->instances[0],
    53                                                   NULL,  /* XXX sessionOpt */
    54                                                   arena,
    55                                                   &rvCert->type,
    56                                                   &rvCert->id,
    57                                                   &rvCert->encoding,
    58                                                   &rvCert->issuer,
    59                                                   &rvCert->serial,
    60                                                   &rvCert->subject);
    61     if (status != PR_SUCCESS ||
    62 	!rvCert->encoding.data ||
    63 	!rvCert->encoding.size ||
    64 	!rvCert->issuer.data ||
    65 	!rvCert->issuer.size ||
    66 	!rvCert->serial.data ||
    67 	!rvCert->serial.size) {
    68 	if (mark)
    69 	    nssArena_Release(arena, mark);
    70 	return (NSSCertificate *)NULL;
    71     }
    72     if (mark)
    73 	nssArena_Unmark(arena, mark);
    74     return rvCert;
    75 }
    77 NSS_IMPLEMENT NSSCertificate *
    78 nssCertificate_AddRef (
    79   NSSCertificate *c
    80 )
    81 {
    82     if (c) {
    83 	nssPKIObject_AddRef(&c->object);
    84     }
    85     return c;
    86 }
    88 NSS_IMPLEMENT PRStatus
    89 nssCertificate_Destroy (
    90   NSSCertificate *c
    91 )
    92 {
    93     nssCertificateStoreTrace lockTrace = {NULL, NULL, PR_FALSE, PR_FALSE};
    94     nssCertificateStoreTrace unlockTrace = {NULL, NULL, PR_FALSE, PR_FALSE};
    96     if (c) {
    97 	PRUint32 i;
    98 	nssDecodedCert *dc = c->decoding;
    99 	NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
   100 	NSSCryptoContext *cc = c->object.cryptoContext;
   102 	PR_ASSERT(c->object.refCount > 0);
   104 	/* --- LOCK storage --- */
   105 	if (cc) {
   106 	    nssCertificateStore_Lock(cc->certStore, &lockTrace);
   107 	} else {
   108 	    nssTrustDomain_LockCertCache(td);
   109 	}
   110 	if (PR_ATOMIC_DECREMENT(&c->object.refCount) == 0) {
   111 	    /* --- remove cert and UNLOCK storage --- */
   112 	    if (cc) {
   113 		nssCertificateStore_RemoveCertLOCKED(cc->certStore, c);
   114 		nssCertificateStore_Unlock(cc->certStore, &lockTrace,
   115                                            &unlockTrace);
   116 	    } else {
   117 		nssTrustDomain_RemoveCertFromCacheLOCKED(td, c);
   118 		nssTrustDomain_UnlockCertCache(td);
   119 	    }
   120 	    /* free cert data */
   121 	    for (i=0; i<c->object.numInstances; i++) {
   122 		nssCryptokiObject_Destroy(c->object.instances[i]);
   123 	    }
   124 	    nssPKIObject_DestroyLock(&c->object);
   125 	    nssArena_Destroy(c->object.arena);
   126 	    nssDecodedCert_Destroy(dc);
   127 	} else {
   128 	    /* --- UNLOCK storage --- */
   129 	    if (cc) {
   130 		nssCertificateStore_Unlock(cc->certStore,
   131 					   &lockTrace,
   132 					   &unlockTrace);
   133 	    } else {
   134 		nssTrustDomain_UnlockCertCache(td);
   135 	    }
   136 	}
   137     }
   138     return PR_SUCCESS;
   139 }
   141 NSS_IMPLEMENT PRStatus
   142 NSSCertificate_Destroy (
   143   NSSCertificate *c
   144 )
   145 {
   146     return nssCertificate_Destroy(c);
   147 }
   149 NSS_IMPLEMENT NSSDER *
   150 nssCertificate_GetEncoding (
   151   NSSCertificate *c
   152 )
   153 {
   154     if (c->encoding.size > 0 && c->encoding.data) {
   155 	return &c->encoding;
   156     } else {
   157 	return (NSSDER *)NULL;
   158     }
   159 }
   161 NSS_IMPLEMENT NSSDER *
   162 nssCertificate_GetIssuer (
   163   NSSCertificate *c
   164 )
   165 {
   166     if (c->issuer.size > 0 && c->issuer.data) {
   167 	return &c->issuer;
   168     } else {
   169 	return (NSSDER *)NULL;
   170     }
   171 }
   173 NSS_IMPLEMENT NSSDER *
   174 nssCertificate_GetSerialNumber (
   175   NSSCertificate *c
   176 )
   177 {
   178     if (c->serial.size > 0 && c->serial.data) {
   179 	return &c->serial;
   180     } else {
   181 	return (NSSDER *)NULL;
   182     }
   183 }
   185 NSS_IMPLEMENT NSSDER *
   186 nssCertificate_GetSubject (
   187   NSSCertificate *c
   188 )
   189 {
   190     if (c->subject.size > 0 && c->subject.data) {
   191 	return &c->subject;
   192     } else {
   193 	return (NSSDER *)NULL;
   194     }
   195 }
   197 /* Returns a copy, Caller must free using nss_ZFreeIf */
   198 NSS_IMPLEMENT NSSUTF8 *
   199 nssCertificate_GetNickname (
   200   NSSCertificate *c,
   201   NSSToken *tokenOpt
   202 )
   203 {
   204     return nssPKIObject_GetNicknameForToken(&c->object, tokenOpt);
   205 }
   207 NSS_IMPLEMENT NSSASCII7 *
   208 nssCertificate_GetEmailAddress (
   209   NSSCertificate *c
   210 )
   211 {
   212     return c->email;
   213 }
   215 NSS_IMPLEMENT PRStatus
   216 NSSCertificate_DeleteStoredObject (
   217   NSSCertificate *c,
   218   NSSCallback *uhh
   219 )
   220 {
   221     return nssPKIObject_DeleteStoredObject(&c->object, uhh, PR_TRUE);
   222 }
   224 NSS_IMPLEMENT PRStatus
   225 NSSCertificate_Validate (
   226   NSSCertificate *c,
   227   NSSTime *timeOpt, /* NULL for "now" */
   228   NSSUsage *usage,
   229   NSSPolicies *policiesOpt /* NULL for none */
   230 )
   231 {
   232     nss_SetError(NSS_ERROR_NOT_FOUND);
   233     return PR_FAILURE;
   234 }
   236 NSS_IMPLEMENT void ** /* void *[] */
   237 NSSCertificate_ValidateCompletely (
   238   NSSCertificate *c,
   239   NSSTime *timeOpt, /* NULL for "now" */
   240   NSSUsage *usage,
   241   NSSPolicies *policiesOpt, /* NULL for none */
   242   void **rvOpt, /* NULL for allocate */
   243   PRUint32 rvLimit, /* zero for no limit */
   244   NSSArena *arenaOpt /* NULL for heap */
   245 )
   246 {
   247     nss_SetError(NSS_ERROR_NOT_FOUND);
   248     return NULL;
   249 }
   251 NSS_IMPLEMENT PRStatus
   252 NSSCertificate_ValidateAndDiscoverUsagesAndPolicies (
   253   NSSCertificate *c,
   254   NSSTime **notBeforeOutOpt,
   255   NSSTime **notAfterOutOpt,
   256   void *allowedUsages,
   257   void *disallowedUsages,
   258   void *allowedPolicies,
   259   void *disallowedPolicies,
   260   /* more args.. work on this fgmr */
   261   NSSArena *arenaOpt
   262 )
   263 {
   264     nss_SetError(NSS_ERROR_NOT_FOUND);
   265     return PR_FAILURE;
   266 }
   268 NSS_IMPLEMENT NSSDER *
   269 NSSCertificate_Encode (
   270   NSSCertificate *c,
   271   NSSDER *rvOpt,
   272   NSSArena *arenaOpt
   273 )
   274 {
   275     /* Item, DER, BER are all typedefs now... */
   276     return nssItem_Duplicate((NSSItem *)&c->encoding, arenaOpt, rvOpt);
   277 }
   279 NSS_IMPLEMENT nssDecodedCert *
   280 nssCertificate_GetDecoding (
   281   NSSCertificate *c
   282 )
   283 {
   284     nssDecodedCert* deco = NULL;
   285     if (c->type == NSSCertificateType_PKIX) {
   286         (void)STAN_GetCERTCertificate(c);
   287     }
   288     nssPKIObject_Lock(&c->object);
   289     if (!c->decoding) {
   290 	deco = nssDecodedCert_Create(NULL, &c->encoding, c->type);
   291     	PORT_Assert(!c->decoding); 
   292         c->decoding = deco;
   293     } else {
   294         deco = c->decoding;
   295     }
   296     nssPKIObject_Unlock(&c->object);
   297     return deco;
   298 }
   300 static NSSCertificate **
   301 filter_subject_certs_for_id (
   302   NSSCertificate **subjectCerts, 
   303   void *id
   304 )
   305 {
   306     NSSCertificate **si;
   307     nssDecodedCert *dcp;
   308     int nextOpenSlot = 0;
   309     int i;
   310     nssCertIDMatch matchLevel = nssCertIDMatch_Unknown;
   311     nssCertIDMatch match;
   313     /* walk the subject certs */
   314     for (si = subjectCerts; *si; si++) {
   315 	dcp = nssCertificate_GetDecoding(*si);
   316 	if (!dcp) {
   317 	    NSSCertificate_Destroy(*si);
   318 	    continue;
   319 	}
   320 	match = dcp->matchIdentifier(dcp, id);
   321 	switch (match) {
   322 	case nssCertIDMatch_Yes:
   323 	    if (matchLevel == nssCertIDMatch_Unknown) {
   324 		/* we have non-definitive matches, forget them */
   325 		for (i = 0; i < nextOpenSlot; i++) {
   326 		    NSSCertificate_Destroy(subjectCerts[i]);
   327 		    subjectCerts[i] = NULL;
   328 		}
   329 		nextOpenSlot = 0;
   330 		/* only keep definitive matches from now on */
   331 		matchLevel = nssCertIDMatch_Yes;
   332 	    }
   333 	    /* keep the cert */
   334 	    subjectCerts[nextOpenSlot++] = *si;
   335 	    break;
   336 	case nssCertIDMatch_Unknown:
   337 	    if (matchLevel == nssCertIDMatch_Unknown) {
   338 		/* only have non-definitive matches so far, keep it */
   339 		subjectCerts[nextOpenSlot++] = *si;
   340 		break;
   341 	    }
   342 	    /* else fall through, we have a definitive match already */
   343 	case nssCertIDMatch_No:
   344 	default:
   345 	    NSSCertificate_Destroy(*si);
   346 	    *si = NULL;
   347 	}
   348     }
   349     subjectCerts[nextOpenSlot] = NULL;
   350     return subjectCerts;
   351 }
   353 static NSSCertificate **
   354 filter_certs_for_valid_issuers (
   355   NSSCertificate **certs
   356 )
   357 {
   358     NSSCertificate **cp;
   359     nssDecodedCert *dcp;
   360     int nextOpenSlot = 0;
   362     for (cp = certs; *cp; cp++) {
   363 	dcp = nssCertificate_GetDecoding(*cp);
   364 	if (dcp && dcp->isValidIssuer(dcp)) {
   365 	    certs[nextOpenSlot++] = *cp;
   366 	} else {
   367 	    NSSCertificate_Destroy(*cp);
   368 	}
   369     }
   370     certs[nextOpenSlot] = NULL;
   371     return certs;
   372 }
   374 static NSSCertificate *
   375 find_cert_issuer (
   376   NSSCertificate *c,
   377   NSSTime *timeOpt,
   378   NSSUsage *usage,
   379   NSSPolicies *policiesOpt,
   380   NSSTrustDomain *td,
   381   NSSCryptoContext *cc
   382 )
   383 {
   384     NSSArena *arena;
   385     NSSCertificate **certs = NULL;
   386     NSSCertificate **ccIssuers = NULL;
   387     NSSCertificate **tdIssuers = NULL;
   388     NSSCertificate *issuer = NULL;
   390     if (!cc)
   391 	cc = c->object.cryptoContext;
   392     if (!td)
   393 	td = NSSCertificate_GetTrustDomain(c);
   394     arena = nssArena_Create();
   395     if (!arena) {
   396 	return (NSSCertificate *)NULL;
   397     }
   398     if (cc) {
   399 	ccIssuers = nssCryptoContext_FindCertificatesBySubject(cc,
   400 	                                                       &c->issuer,
   401 	                                                       NULL,
   402 	                                                       0,
   403 	                                                       arena);
   404     }
   405     if (td)
   406 	tdIssuers = nssTrustDomain_FindCertificatesBySubject(td,
   407                                                          &c->issuer,
   408                                                          NULL,
   409                                                          0,
   410                                                          arena);
   411     certs = nssCertificateArray_Join(ccIssuers, tdIssuers);
   412     if (certs) {
   413 	nssDecodedCert *dc = NULL;
   414 	void *issuerID = NULL;
   415 	dc = nssCertificate_GetDecoding(c);
   416 	if (dc) {
   417 	    issuerID = dc->getIssuerIdentifier(dc);
   418 	}
   419 	/* XXX review based on CERT_FindCertIssuer
   420 	 * this function is not using the authCertIssuer field as a fallback
   421 	 * if authority key id does not exist
   422 	 */
   423 	if (issuerID) {
   424 	    certs = filter_subject_certs_for_id(certs, issuerID);
   425 	}
   426 	certs = filter_certs_for_valid_issuers(certs);
   427 	issuer = nssCertificateArray_FindBestCertificate(certs,
   428 	                                                 timeOpt,
   429 	                                                 usage,
   430 	                                                 policiesOpt);
   431 	nssCertificateArray_Destroy(certs);
   432     }
   433     nssArena_Destroy(arena);
   434     return issuer;
   435 }
   437 /* This function returns the built chain, as far as it gets,
   438 ** even if/when it fails to find an issuer, and returns PR_FAILURE
   439 */
   440 NSS_IMPLEMENT NSSCertificate **
   441 nssCertificate_BuildChain (
   442   NSSCertificate *c,
   443   NSSTime *timeOpt,
   444   NSSUsage *usage,
   445   NSSPolicies *policiesOpt,
   446   NSSCertificate **rvOpt,
   447   PRUint32 rvLimit,
   448   NSSArena *arenaOpt,
   449   PRStatus *statusOpt,
   450   NSSTrustDomain *td,
   451   NSSCryptoContext *cc 
   452 )
   453 {
   454     NSSCertificate **rvChain = NULL;
   455     NSSUsage issuerUsage = *usage;
   456     nssPKIObjectCollection *collection = NULL;
   457     PRUint32  rvCount = 0;
   458     PRStatus  st;
   459     PRStatus  ret = PR_SUCCESS;
   461     if (!c || !cc ||
   462         (!td && (td = NSSCertificate_GetTrustDomain(c)) == NULL)) {
   463 	goto loser;
   464     }
   465     /* bump the usage up to CA level */
   466     issuerUsage.nss3lookingForCA = PR_TRUE;
   467     collection = nssCertificateCollection_Create(td, NULL);
   468     if (!collection)
   469 	goto loser;
   470     st = nssPKIObjectCollection_AddObject(collection, (nssPKIObject *)c);
   471     if (st != PR_SUCCESS)
   472     	goto loser;
   473     for (rvCount = 1; (!rvLimit || rvCount < rvLimit); ++rvCount) {
   474 	CERTCertificate *cCert = STAN_GetCERTCertificate(c);
   475 	if (cCert->isRoot) {
   476 	    /* not including the issuer of the self-signed cert, which is,
   477 	     * of course, itself
   478 	     */
   479 	    break;
   480 	}
   481 	c = find_cert_issuer(c, timeOpt, &issuerUsage, policiesOpt, td, cc);
   482 	if (!c) {
   483 	    ret = PR_FAILURE;
   484 	    break;
   485 	}
   486 	st = nssPKIObjectCollection_AddObject(collection, (nssPKIObject *)c);
   487 	nssCertificate_Destroy(c); /* collection has it */
   488 	if (st != PR_SUCCESS)
   489 	    goto loser;
   490     }
   491     rvChain = nssPKIObjectCollection_GetCertificates(collection, 
   492                                                      rvOpt, 
   493                                                      rvLimit, 
   494                                                      arenaOpt);
   495     if (rvChain) {
   496 	nssPKIObjectCollection_Destroy(collection);
   497 	if (statusOpt) 
   498 	    *statusOpt = ret;
   499 	if (ret != PR_SUCCESS)
   500 	    nss_SetError(NSS_ERROR_CERTIFICATE_ISSUER_NOT_FOUND);
   501 	return rvChain;
   502     }
   504 loser:
   505     if (collection)
   506 	nssPKIObjectCollection_Destroy(collection);
   507     if (statusOpt) 
   508 	*statusOpt = PR_FAILURE;
   509     nss_SetError(NSS_ERROR_CERTIFICATE_ISSUER_NOT_FOUND);
   510     return rvChain;
   511 }
   513 NSS_IMPLEMENT NSSCertificate **
   514 NSSCertificate_BuildChain (
   515   NSSCertificate *c,
   516   NSSTime *timeOpt,
   517   NSSUsage *usage,
   518   NSSPolicies *policiesOpt,
   519   NSSCertificate **rvOpt,
   520   PRUint32 rvLimit, /* zero for no limit */
   521   NSSArena *arenaOpt,
   522   PRStatus *statusOpt,
   523   NSSTrustDomain *td,
   524   NSSCryptoContext *cc 
   525 )
   526 {
   527     return nssCertificate_BuildChain(c, timeOpt, usage, policiesOpt,
   528                                      rvOpt, rvLimit, arenaOpt, statusOpt,
   529 				     td, cc);
   530 }
   532 NSS_IMPLEMENT NSSCryptoContext *
   533 nssCertificate_GetCryptoContext (
   534   NSSCertificate *c
   535 )
   536 {
   537     return c->object.cryptoContext;
   538 }
   540 NSS_IMPLEMENT NSSTrustDomain *
   541 nssCertificate_GetTrustDomain (
   542   NSSCertificate *c
   543 )
   544 {
   545     return c->object.trustDomain;
   546 }
   548 NSS_IMPLEMENT NSSTrustDomain *
   549 NSSCertificate_GetTrustDomain (
   550   NSSCertificate *c
   551 )
   552 {
   553     return nssCertificate_GetTrustDomain(c);
   554 }
   556 NSS_IMPLEMENT NSSToken *
   557 NSSCertificate_GetToken (
   558   NSSCertificate *c,
   559   PRStatus *statusOpt
   560 )
   561 {
   562     return (NSSToken *)NULL;
   563 }
   565 NSS_IMPLEMENT NSSSlot *
   566 NSSCertificate_GetSlot (
   567   NSSCertificate *c,
   568   PRStatus *statusOpt
   569 )
   570 {
   571     return (NSSSlot *)NULL;
   572 }
   574 NSS_IMPLEMENT NSSModule *
   575 NSSCertificate_GetModule (
   576   NSSCertificate *c,
   577   PRStatus *statusOpt
   578 )
   579 {
   580     return (NSSModule *)NULL;
   581 }
   583 NSS_IMPLEMENT NSSItem *
   584 NSSCertificate_Encrypt (
   585   NSSCertificate *c,
   586   NSSAlgorithmAndParameters *apOpt,
   587   NSSItem *data,
   588   NSSTime *timeOpt,
   589   NSSUsage *usage,
   590   NSSPolicies *policiesOpt,
   591   NSSCallback *uhh,
   592   NSSItem *rvOpt,
   593   NSSArena *arenaOpt
   594 )
   595 {
   596     nss_SetError(NSS_ERROR_NOT_FOUND);
   597     return NULL;
   598 }
   600 NSS_IMPLEMENT PRStatus
   601 NSSCertificate_Verify (
   602   NSSCertificate *c,
   603   NSSAlgorithmAndParameters *apOpt,
   604   NSSItem *data,
   605   NSSItem *signature,
   606   NSSTime *timeOpt,
   607   NSSUsage *usage,
   608   NSSPolicies *policiesOpt,
   609   NSSCallback *uhh
   610 )
   611 {
   612     nss_SetError(NSS_ERROR_NOT_FOUND);
   613     return PR_FAILURE;
   614 }
   616 NSS_IMPLEMENT NSSItem *
   617 NSSCertificate_VerifyRecover (
   618   NSSCertificate *c,
   619   NSSAlgorithmAndParameters *apOpt,
   620   NSSItem *signature,
   621   NSSTime *timeOpt,
   622   NSSUsage *usage,
   623   NSSPolicies *policiesOpt,
   624   NSSCallback *uhh,
   625   NSSItem *rvOpt,
   626   NSSArena *arenaOpt
   627 )
   628 {
   629     nss_SetError(NSS_ERROR_NOT_FOUND);
   630     return NULL;
   631 }
   633 NSS_IMPLEMENT NSSItem *
   634 NSSCertificate_WrapSymmetricKey (
   635   NSSCertificate *c,
   636   NSSAlgorithmAndParameters *apOpt,
   637   NSSSymmetricKey *keyToWrap,
   638   NSSTime *timeOpt,
   639   NSSUsage *usage,
   640   NSSPolicies *policiesOpt,
   641   NSSCallback *uhh,
   642   NSSItem *rvOpt,
   643   NSSArena *arenaOpt
   644 )
   645 {
   646     nss_SetError(NSS_ERROR_NOT_FOUND);
   647     return NULL;
   648 }
   650 NSS_IMPLEMENT NSSCryptoContext *
   651 NSSCertificate_CreateCryptoContext (
   652   NSSCertificate *c,
   653   NSSAlgorithmAndParameters *apOpt,
   654   NSSTime *timeOpt,
   655   NSSUsage *usage,
   656   NSSPolicies *policiesOpt,
   657   NSSCallback *uhh  
   658 )
   659 {
   660     nss_SetError(NSS_ERROR_NOT_FOUND);
   661     return NULL;
   662 }
   664 NSS_IMPLEMENT NSSPublicKey *
   665 NSSCertificate_GetPublicKey (
   666   NSSCertificate *c
   667 )
   668 {
   669 #if 0
   670     CK_ATTRIBUTE pubktemplate[] = {
   671 	{ CKA_CLASS,   NULL, 0 },
   672 	{ CKA_ID,      NULL, 0 },
   673 	{ CKA_SUBJECT, NULL, 0 }
   674     };
   675     PRStatus nssrv;
   676     CK_ULONG count = sizeof(pubktemplate) / sizeof(pubktemplate[0]);
   677     NSS_CK_SET_ATTRIBUTE_ITEM(pubktemplate, 0, &g_ck_class_pubkey);
   678     if (c->id.size > 0) {
   679 	/* CKA_ID */
   680 	NSS_CK_ITEM_TO_ATTRIBUTE(&c->id, &pubktemplate[1]);
   681     } else {
   682 	/* failure, yes? */
   683 	return (NSSPublicKey *)NULL;
   684     }
   685     if (c->subject.size > 0) {
   686 	/* CKA_SUBJECT */
   687 	NSS_CK_ITEM_TO_ATTRIBUTE(&c->subject, &pubktemplate[2]);
   688     } else {
   689 	/* failure, yes? */
   690 	return (NSSPublicKey *)NULL;
   691     }
   692     /* Try the cert's token first */
   693     if (c->token) {
   694 	nssrv = nssToken_FindObjectByTemplate(c->token, pubktemplate, count);
   695     }
   696 #endif
   697     /* Try all other key tokens */
   698     return (NSSPublicKey *)NULL;
   699 }
   701 NSS_IMPLEMENT NSSPrivateKey *
   702 NSSCertificate_FindPrivateKey (
   703   NSSCertificate *c,
   704   NSSCallback *uhh
   705 )
   706 {
   707     nss_SetError(NSS_ERROR_NOT_FOUND);
   708     return NULL;
   709 }
   711 NSS_IMPLEMENT PRBool
   712 NSSCertificate_IsPrivateKeyAvailable (
   713   NSSCertificate *c,
   714   NSSCallback *uhh,
   715   PRStatus *statusOpt
   716 )
   717 {
   718     PRBool isUser = PR_FALSE;
   719     nssCryptokiObject **ip;
   720     nssCryptokiObject **instances = nssPKIObject_GetInstances(&c->object);
   721     if (!instances) {
   722 	return PR_FALSE;
   723     }
   724     for (ip = instances; *ip; ip++) {
   725 	nssCryptokiObject *instance = *ip;
   726 	if (nssToken_IsPrivateKeyAvailable(instance->token, c, instance)) {
   727 	    isUser = PR_TRUE;
   728 	}
   729     }
   730     nssCryptokiObjectArray_Destroy(instances);
   731     return isUser;
   732 }
   734 /* sort the subject cert list from newest to oldest */
   735 PRIntn
   736 nssCertificate_SubjectListSort (
   737   void *v1,
   738   void *v2
   739 )
   740 {
   741     NSSCertificate *c1 = (NSSCertificate *)v1;
   742     NSSCertificate *c2 = (NSSCertificate *)v2;
   743     nssDecodedCert *dc1 = nssCertificate_GetDecoding(c1);
   744     nssDecodedCert *dc2 = nssCertificate_GetDecoding(c2);
   745     if (!dc1) {
   746 	return dc2 ? 1 : 0;
   747     } else if (!dc2) {
   748 	return -1;
   749     } else {
   750 	return dc1->isNewerThan(dc1, dc2) ? -1 : 1;
   751     }
   752 }
   754 NSS_IMPLEMENT PRBool
   755 NSSUserCertificate_IsStillPresent (
   756   NSSUserCertificate *uc,
   757   PRStatus *statusOpt
   758 )
   759 {
   760     nss_SetError(NSS_ERROR_NOT_FOUND);
   761     return PR_FALSE;
   762 }
   764 NSS_IMPLEMENT NSSItem *
   765 NSSUserCertificate_Decrypt (
   766   NSSUserCertificate *uc,
   767   NSSAlgorithmAndParameters *apOpt,
   768   NSSItem *data,
   769   NSSTime *timeOpt,
   770   NSSUsage *usage,
   771   NSSPolicies *policiesOpt,
   772   NSSCallback *uhh,
   773   NSSItem *rvOpt,
   774   NSSArena *arenaOpt
   775 )
   776 {
   777     nss_SetError(NSS_ERROR_NOT_FOUND);
   778     return NULL;
   779 }
   781 NSS_IMPLEMENT NSSItem *
   782 NSSUserCertificate_Sign (
   783   NSSUserCertificate *uc,
   784   NSSAlgorithmAndParameters *apOpt,
   785   NSSItem *data,
   786   NSSTime *timeOpt,
   787   NSSUsage *usage,
   788   NSSPolicies *policiesOpt,
   789   NSSCallback *uhh,
   790   NSSItem *rvOpt,
   791   NSSArena *arenaOpt
   792 )
   793 {
   794     nss_SetError(NSS_ERROR_NOT_FOUND);
   795     return NULL;
   796 }
   798 NSS_IMPLEMENT NSSItem *
   799 NSSUserCertificate_SignRecover (
   800   NSSUserCertificate *uc,
   801   NSSAlgorithmAndParameters *apOpt,
   802   NSSItem *data,
   803   NSSTime *timeOpt,
   804   NSSUsage *usage,
   805   NSSPolicies *policiesOpt,
   806   NSSCallback *uhh,
   807   NSSItem *rvOpt,
   808   NSSArena *arenaOpt
   809 )
   810 {
   811     nss_SetError(NSS_ERROR_NOT_FOUND);
   812     return NULL;
   813 }
   815 NSS_IMPLEMENT NSSSymmetricKey *
   816 NSSUserCertificate_UnwrapSymmetricKey (
   817   NSSUserCertificate *uc,
   818   NSSAlgorithmAndParameters *apOpt,
   819   NSSItem *wrappedKey,
   820   NSSTime *timeOpt,
   821   NSSUsage *usage,
   822   NSSPolicies *policiesOpt,
   823   NSSCallback *uhh,
   824   NSSItem *rvOpt,
   825   NSSArena *arenaOpt
   826 )
   827 {
   828     nss_SetError(NSS_ERROR_NOT_FOUND);
   829     return NULL;
   830 }
   832 NSS_IMPLEMENT NSSSymmetricKey *
   833 NSSUserCertificate_DeriveSymmetricKey (
   834   NSSUserCertificate *uc, /* provides private key */
   835   NSSCertificate *c, /* provides public key */
   836   NSSAlgorithmAndParameters *apOpt,
   837   NSSOID *target,
   838   PRUint32 keySizeOpt, /* zero for best allowed */
   839   NSSOperations operations,
   840   NSSCallback *uhh
   841 )
   842 {
   843     nss_SetError(NSS_ERROR_NOT_FOUND);
   844     return NULL;
   845 }
   847 NSS_IMPLEMENT nssSMIMEProfile *
   848 nssSMIMEProfile_Create (
   849   NSSCertificate *cert,
   850   NSSItem *profileTime,
   851   NSSItem *profileData
   852 )
   853 {
   854     NSSArena *arena;
   855     nssSMIMEProfile *rvProfile;
   856     nssPKIObject *object;
   857     NSSTrustDomain *td = nssCertificate_GetTrustDomain(cert);
   858     NSSCryptoContext *cc = nssCertificate_GetCryptoContext(cert);
   859     arena = nssArena_Create();
   860     if (!arena) {
   861 	return NULL;
   862     }
   863     object = nssPKIObject_Create(arena, NULL, td, cc, nssPKILock);
   864     if (!object) {
   865 	goto loser;
   866     }
   867     rvProfile = nss_ZNEW(arena, nssSMIMEProfile);
   868     if (!rvProfile) {
   869 	goto loser;
   870     }
   871     rvProfile->object = *object;
   872     rvProfile->certificate = cert;
   873     rvProfile->email = nssUTF8_Duplicate(cert->email, arena);
   874     rvProfile->subject = nssItem_Duplicate(&cert->subject, arena, NULL);
   875     if (profileTime) {
   876 	rvProfile->profileTime = nssItem_Duplicate(profileTime, arena, NULL);
   877     }
   878     if (profileData) {
   879 	rvProfile->profileData = nssItem_Duplicate(profileData, arena, NULL);
   880     }
   881     return rvProfile;
   882 loser:
   883     if (object) nssPKIObject_Destroy(object);
   884     else if (arena)  nssArena_Destroy(arena);
   885     return (nssSMIMEProfile *)NULL;
   886 }
   888 /* execute a callback function on all members of a cert list */
   889 NSS_EXTERN PRStatus
   890 nssCertificateList_DoCallback (
   891   nssList *certList, 
   892   PRStatus (* callback)(NSSCertificate *c, void *arg),
   893   void *arg
   894 )
   895 {
   896     nssListIterator *certs;
   897     NSSCertificate *cert;
   898     PRStatus nssrv;
   899     certs = nssList_CreateIterator(certList);
   900     if (!certs) {
   901         return PR_FAILURE;
   902     }
   903     for (cert  = (NSSCertificate *)nssListIterator_Start(certs);
   904          cert != (NSSCertificate *)NULL;
   905          cert  = (NSSCertificate *)nssListIterator_Next(certs))
   906     {
   907 	nssrv = (*callback)(cert, arg);
   908     }
   909     nssListIterator_Finish(certs);
   910     nssListIterator_Destroy(certs);
   911     return PR_SUCCESS;
   912 }
   914 static PRStatus add_ref_callback(NSSCertificate *c, void *a)
   915 {
   916     nssCertificate_AddRef(c);
   917     return PR_SUCCESS;
   918 }
   920 NSS_IMPLEMENT void
   921 nssCertificateList_AddReferences (
   922   nssList *certList
   923 )
   924 {
   925     (void)nssCertificateList_DoCallback(certList, add_ref_callback, NULL);
   926 }
   929 /*
   930  * Is this trust record safe to apply to all certs of the same issuer/SN 
   931  * independent of the cert matching the hash. This is only true is the trust 
   932  * is unknown or distrusted. In general this feature is only useful to 
   933  * explicitly distrusting certs. It is not safe to use to trust certs, so 
   934  * only allow unknown and untrusted trust types.
   935  */
   936 PRBool
   937 nssTrust_IsSafeToIgnoreCertHash(nssTrustLevel serverAuth, 
   938 		nssTrustLevel clientAuth, nssTrustLevel codeSigning, 
   939 		nssTrustLevel email, PRBool stepup)
   940 {
   941     /* step up is a trust type, if it's on, we must have a hash for the cert */
   942     if (stepup) {
   943 	return PR_FALSE;
   944     }
   945     if ((serverAuth != nssTrustLevel_Unknown) && 
   946 	(serverAuth != nssTrustLevel_NotTrusted)) {
   947 	return PR_FALSE;
   948     }
   949     if ((clientAuth != nssTrustLevel_Unknown) && 
   950 	(clientAuth != nssTrustLevel_NotTrusted)) {
   951 	return PR_FALSE;
   952     }
   953     if ((codeSigning != nssTrustLevel_Unknown) && 
   954 	(codeSigning != nssTrustLevel_NotTrusted)) {
   955 	return PR_FALSE;
   956     }
   957     if ((email != nssTrustLevel_Unknown) && 
   958 	(email != nssTrustLevel_NotTrusted)) {
   959 	return PR_FALSE;
   960     }
   961     /* record only has Unknown and Untrusted entries, ok to accept without a 
   962      * hash */
   963     return PR_TRUE;
   964 }
   966 NSS_IMPLEMENT NSSTrust *
   967 nssTrust_Create (
   968   nssPKIObject *object,
   969   NSSItem *certData
   970 )
   971 {
   972     PRStatus status;
   973     PRUint32 i;
   974     PRUint32 lastTrustOrder, myTrustOrder;
   975     unsigned char sha1_hashcmp[SHA1_LENGTH];
   976     unsigned char sha1_hashin[SHA1_LENGTH];
   977     NSSItem sha1_hash;
   978     NSSTrust *rvt;
   979     nssCryptokiObject *instance;
   980     nssTrustLevel serverAuth, clientAuth, codeSigning, emailProtection;
   981     SECStatus rv; /* Should be stan flavor */
   982     PRBool stepUp;
   984     lastTrustOrder = 1<<16; /* just make it big */
   985     PR_ASSERT(object->instances != NULL && object->numInstances > 0);
   986     rvt = nss_ZNEW(object->arena, NSSTrust);
   987     if (!rvt) {
   988 	return (NSSTrust *)NULL;
   989     }
   990     rvt->object = *object;
   992     /* should be stan flavor of Hashbuf */
   993     rv = PK11_HashBuf(SEC_OID_SHA1,sha1_hashcmp,certData->data,certData->size);
   994     if (rv != SECSuccess) {
   995 	return (NSSTrust *)NULL;
   996     }
   997     sha1_hash.data = sha1_hashin;
   998     sha1_hash.size = sizeof (sha1_hashin);
   999     /* trust has to peek into the base object members */
  1000     nssPKIObject_Lock(object);
  1001     for (i=0; i<object->numInstances; i++) {
  1002 	instance = object->instances[i];
  1003 	myTrustOrder = nssToken_GetTrustOrder(instance->token);
  1004 	status = nssCryptokiTrust_GetAttributes(instance, NULL,
  1005 						&sha1_hash,
  1006 	                                        &serverAuth,
  1007 	                                        &clientAuth,
  1008 	                                        &codeSigning,
  1009 	                                        &emailProtection,
  1010 	                                        &stepUp);
  1011 	if (status != PR_SUCCESS) {
  1012 	    nssPKIObject_Unlock(object);
  1013 	    return (NSSTrust *)NULL;
  1015 	/* if no hash is specified, then trust applies to all certs with
  1016 	 * this issuer/SN. NOTE: This is only true for entries that
  1017 	 * have distrust and unknown record */
  1018 	if (!(
  1019             /* we continue if there is no hash, and the trust type is
  1020 	     * safe to accept without a hash ... or ... */
  1021 	     ((sha1_hash.size == 0)  && 
  1022 		nssTrust_IsSafeToIgnoreCertHash(serverAuth,clientAuth,
  1023 		codeSigning, emailProtection,stepUp)) 
  1024 	   ||
  1025             /* we have a hash of the correct size, and it matches */
  1026             ((sha1_hash.size == SHA1_LENGTH) && (PORT_Memcmp(sha1_hashin,
  1027 	        sha1_hashcmp,SHA1_LENGTH) == 0))   )) {
  1028 	    nssPKIObject_Unlock(object);
  1029 	    return (NSSTrust *)NULL;
  1031 	if (rvt->serverAuth == nssTrustLevel_Unknown ||
  1032 	    myTrustOrder < lastTrustOrder) 
  1034 	    rvt->serverAuth = serverAuth;
  1036 	if (rvt->clientAuth == nssTrustLevel_Unknown ||
  1037 	    myTrustOrder < lastTrustOrder) 
  1039 	    rvt->clientAuth = clientAuth;
  1041 	if (rvt->emailProtection == nssTrustLevel_Unknown ||
  1042 	    myTrustOrder < lastTrustOrder) 
  1044 	    rvt->emailProtection = emailProtection;
  1046 	if (rvt->codeSigning == nssTrustLevel_Unknown ||
  1047 	    myTrustOrder < lastTrustOrder) 
  1049 	    rvt->codeSigning = codeSigning;
  1051 	rvt->stepUpApproved = stepUp;
  1052 	lastTrustOrder = myTrustOrder;
  1054     nssPKIObject_Unlock(object);
  1055     return rvt;
  1058 NSS_IMPLEMENT NSSTrust *
  1059 nssTrust_AddRef (
  1060   NSSTrust *trust
  1063     if (trust) {
  1064 	nssPKIObject_AddRef(&trust->object);
  1066     return trust;
  1069 NSS_IMPLEMENT PRStatus
  1070 nssTrust_Destroy (
  1071   NSSTrust *trust
  1074     if (trust) {
  1075 	(void)nssPKIObject_Destroy(&trust->object);
  1077     return PR_SUCCESS;
  1080 NSS_IMPLEMENT nssSMIMEProfile *
  1081 nssSMIMEProfile_AddRef (
  1082   nssSMIMEProfile *profile
  1085     if (profile) {
  1086 	nssPKIObject_AddRef(&profile->object);
  1088     return profile;
  1091 NSS_IMPLEMENT PRStatus
  1092 nssSMIMEProfile_Destroy (
  1093   nssSMIMEProfile *profile
  1096     if (profile) {
  1097 	(void)nssPKIObject_Destroy(&profile->object);
  1099     return PR_SUCCESS;
  1102 NSS_IMPLEMENT NSSCRL *
  1103 nssCRL_Create (
  1104   nssPKIObject *object
  1107     PRStatus status;
  1108     NSSCRL *rvCRL;
  1109     NSSArena *arena = object->arena;
  1110     PR_ASSERT(object->instances != NULL && object->numInstances > 0);
  1111     rvCRL = nss_ZNEW(arena, NSSCRL);
  1112     if (!rvCRL) {
  1113 	return (NSSCRL *)NULL;
  1115     rvCRL->object = *object;
  1116     /* XXX should choose instance based on some criteria */
  1117     status = nssCryptokiCRL_GetAttributes(object->instances[0],
  1118                                           NULL,  /* XXX sessionOpt */
  1119                                           arena,
  1120                                           &rvCRL->encoding,
  1121                                           NULL, /* subject */
  1122                                           NULL, /* class */
  1123                                           &rvCRL->url,
  1124                                           &rvCRL->isKRL);
  1125     if (status != PR_SUCCESS) {
  1126 	return (NSSCRL *)NULL;
  1128     return rvCRL;
  1131 NSS_IMPLEMENT NSSCRL *
  1132 nssCRL_AddRef (
  1133   NSSCRL *crl
  1136     if (crl) {
  1137 	nssPKIObject_AddRef(&crl->object);
  1139     return crl;
  1142 NSS_IMPLEMENT PRStatus
  1143 nssCRL_Destroy (
  1144   NSSCRL *crl
  1147     if (crl) {
  1148 	(void)nssPKIObject_Destroy(&crl->object);
  1150     return PR_SUCCESS;
  1153 NSS_IMPLEMENT PRStatus
  1154 nssCRL_DeleteStoredObject (
  1155   NSSCRL *crl,
  1156   NSSCallback *uhh
  1159     return nssPKIObject_DeleteStoredObject(&crl->object, uhh, PR_TRUE);
  1162 NSS_IMPLEMENT NSSDER *
  1163 nssCRL_GetEncoding (
  1164   NSSCRL *crl
  1167     if (crl && crl->encoding.data != NULL && crl->encoding.size > 0) {
  1168 	return &crl->encoding;
  1169     } else {
  1170 	return (NSSDER *)NULL;

mercurial