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/. */
4 /*
5 * pkix_pl_cert.c
6 *
7 * Certificate Object Functions
8 *
9 */
10
11 #include "pkix_pl_cert.h"
12
13 extern PKIX_PL_HashTable *cachedCertSigTable;
14
15 /* --Private-Cert-Functions------------------------------------- */
16
17 /*
18 * FUNCTION: pkix_pl_Cert_IsExtensionCritical
19 * DESCRIPTION:
20 *
21 * Checks the Cert specified by "cert" to determine whether the extension
22 * whose tag is the UInt32 value given by "tag" is marked as a critical
23 * extension, and stores the result in "pCritical".
24 *
25 * Tags are the index into the table "oids" of SECOidData defined in the
26 * file secoid.c. Constants, such as SEC_OID_X509_CERTIFICATE_POLICIES, are
27 * are defined in secoidt.h for most of the table entries.
28 *
29 * If the specified tag is invalid (not in the list of tags) or if the
30 * extension is not found in the certificate, PKIX_FALSE is stored.
31 *
32 * PARAMETERS
33 * "cert"
34 * Address of Cert whose extensions are to be examined. Must be non-NULL.
35 * "tag"
36 * The UInt32 value of the tag for the extension whose criticality is
37 * to be determined
38 * "pCritical"
39 * Address where the Boolean value will be stored. Must be non-NULL.
40 * "plContext"
41 * Platform-specific context pointer.
42 * THREAD SAFETY:
43 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
44 * RETURNS:
45 * Returns NULL if the function succeeds.
46 * Returns a Fatal Error if the function fails in an unrecoverable way.
47 */
48 static PKIX_Error *
pkix_pl_Cert_IsExtensionCritical(PKIX_PL_Cert * cert,PKIX_UInt32 tag,PKIX_Boolean * pCritical,void * plContext)49 pkix_pl_Cert_IsExtensionCritical(
50 PKIX_PL_Cert *cert,
51 PKIX_UInt32 tag,
52 PKIX_Boolean *pCritical,
53 void *plContext)
54 {
55 PKIX_Boolean criticality = PKIX_FALSE;
56 CERTCertExtension **extensions = NULL;
57 SECStatus rv;
58
59 PKIX_ENTER(CERT, "pkix_pl_Cert_IsExtensionCritical");
60 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pCritical);
61
62 extensions = cert->nssCert->extensions;
63 PKIX_NULLCHECK_ONE(extensions);
64
65 PKIX_CERT_DEBUG("\t\tCalling CERT_GetExtenCriticality).\n");
66 rv = CERT_GetExtenCriticality(extensions, tag, &criticality);
67 if (SECSuccess == rv) {
68 *pCritical = criticality;
69 } else {
70 *pCritical = PKIX_FALSE;
71 }
72
73 PKIX_RETURN(CERT);
74 }
75
76 /*
77 * FUNCTION: pkix_pl_Cert_DecodePolicyInfo
78 * DESCRIPTION:
79 *
80 * Decodes the contents of the CertificatePolicy extension in the
81 * CERTCertificate pointed to by "nssCert", to create a List of
82 * CertPolicyInfos, which is stored at the address "pCertPolicyInfos".
83 * A CERTCertificate contains the DER representation of the Cert.
84 * If this certificate does not have a CertificatePolicy extension,
85 * NULL will be stored. If a List is returned, it will be immutable.
86 *
87 * PARAMETERS
88 * "nssCert"
89 * Address of the Cert data whose extension is to be examined. Must be
90 * non-NULL.
91 * "pCertPolicyInfos"
92 * Address where the List of CertPolicyInfos will be stored. Must be
93 * non-NULL.
94 * "plContext"
95 * Platform-specific context pointer.
96 * THREAD SAFETY:
97 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
98 * RETURNS:
99 * Returns NULL if the function succeeds.
100 * Returns a Cert Error if the function fails in a non-fatal way.
101 * Returns a Fatal Error if the function fails in an unrecoverable way.
102 */
103 static PKIX_Error *
pkix_pl_Cert_DecodePolicyInfo(CERTCertificate * nssCert,PKIX_List ** pCertPolicyInfos,void * plContext)104 pkix_pl_Cert_DecodePolicyInfo(
105 CERTCertificate *nssCert,
106 PKIX_List **pCertPolicyInfos,
107 void *plContext)
108 {
109
110 SECStatus rv;
111 SECItem encodedCertPolicyInfo;
112
113 /* Allocated in the arena; freed in CERT_Destroy... */
114 CERTCertificatePolicies *certPol = NULL;
115 CERTPolicyInfo **policyInfos = NULL;
116
117 /* Holder for the return value */
118 PKIX_List *infos = NULL;
119
120 PKIX_PL_OID *pkixOID = NULL;
121 PKIX_List *qualifiers = NULL;
122 PKIX_PL_CertPolicyInfo *certPolicyInfo = NULL;
123 PKIX_PL_CertPolicyQualifier *certPolicyQualifier = NULL;
124 PKIX_PL_ByteArray *qualifierArray = NULL;
125
126 PKIX_ENTER(CERT, "pkix_pl_Cert_DecodePolicyInfo");
127 PKIX_NULLCHECK_TWO(nssCert, pCertPolicyInfos);
128
129 /* get PolicyInfo as a SECItem */
130 PKIX_CERT_DEBUG("\t\tCERT_FindCertExtension).\n");
131 rv = CERT_FindCertExtension
132 (nssCert,
133 SEC_OID_X509_CERTIFICATE_POLICIES,
134 &encodedCertPolicyInfo);
135 if (SECSuccess != rv) {
136 *pCertPolicyInfos = NULL;
137 goto cleanup;
138 }
139
140 /* translate PolicyInfo to CERTCertificatePolicies */
141 PKIX_CERT_DEBUG("\t\tCERT_DecodeCertificatePoliciesExtension).\n");
142 certPol = CERT_DecodeCertificatePoliciesExtension
143 (&encodedCertPolicyInfo);
144
145 PORT_Free(encodedCertPolicyInfo.data);
146
147 if (NULL == certPol) {
148 PKIX_ERROR(PKIX_CERTDECODECERTIFICATEPOLICIESEXTENSIONFAILED);
149 }
150
151 /*
152 * Check whether there are any policyInfos, so we can
153 * avoid creating an unnecessary List
154 */
155 policyInfos = certPol->policyInfos;
156 if (!policyInfos) {
157 *pCertPolicyInfos = NULL;
158 goto cleanup;
159 }
160
161 /* create a List of CertPolicyInfo Objects */
162 PKIX_CHECK(PKIX_List_Create(&infos, plContext),
163 PKIX_LISTCREATEFAILED);
164
165 /*
166 * Traverse the CERTCertificatePolicies structure,
167 * building each PKIX_PL_CertPolicyInfo object in turn
168 */
169 while (*policyInfos != NULL) {
170 CERTPolicyInfo *policyInfo = *policyInfos;
171 CERTPolicyQualifier **policyQualifiers =
172 policyInfo->policyQualifiers;
173 if (policyQualifiers) {
174 /* create a PKIX_List of PKIX_PL_CertPolicyQualifiers */
175 PKIX_CHECK(PKIX_List_Create(&qualifiers, plContext),
176 PKIX_LISTCREATEFAILED);
177
178 while (*policyQualifiers != NULL) {
179 CERTPolicyQualifier *policyQualifier =
180 *policyQualifiers;
181
182 /* create the qualifier's OID object */
183 PKIX_CHECK(PKIX_PL_OID_CreateBySECItem
184 (&policyQualifier->qualifierID,
185 &pkixOID, plContext),
186 PKIX_OIDCREATEFAILED);
187
188 /* create qualifier's ByteArray object */
189
190 PKIX_CHECK(PKIX_PL_ByteArray_Create
191 (policyQualifier->qualifierValue.data,
192 policyQualifier->qualifierValue.len,
193 &qualifierArray,
194 plContext),
195 PKIX_BYTEARRAYCREATEFAILED);
196
197 /* create a CertPolicyQualifier object */
198
199 PKIX_CHECK(pkix_pl_CertPolicyQualifier_Create
200 (pkixOID,
201 qualifierArray,
202 &certPolicyQualifier,
203 plContext),
204 PKIX_CERTPOLICYQUALIFIERCREATEFAILED);
205
206 PKIX_CHECK(PKIX_List_AppendItem
207 (qualifiers,
208 (PKIX_PL_Object *)certPolicyQualifier,
209 plContext),
210 PKIX_LISTAPPENDITEMFAILED);
211
212 PKIX_DECREF(pkixOID);
213 PKIX_DECREF(qualifierArray);
214 PKIX_DECREF(certPolicyQualifier);
215
216 policyQualifiers++;
217 }
218
219 PKIX_CHECK(PKIX_List_SetImmutable
220 (qualifiers, plContext),
221 PKIX_LISTSETIMMUTABLEFAILED);
222 }
223
224
225 /*
226 * Create an OID object pkixOID from policyInfo->policyID.
227 * (The CERTPolicyInfo structure has an oid field, but it
228 * is of type SECOidTag. This function wants a SECItem.)
229 */
230 PKIX_CHECK(PKIX_PL_OID_CreateBySECItem
231 (&policyInfo->policyID, &pkixOID, plContext),
232 PKIX_OIDCREATEFAILED);
233
234 /* Create a CertPolicyInfo object */
235 PKIX_CHECK(pkix_pl_CertPolicyInfo_Create
236 (pkixOID, qualifiers, &certPolicyInfo, plContext),
237 PKIX_CERTPOLICYINFOCREATEFAILED);
238
239 /* Append the new CertPolicyInfo object to the list */
240 PKIX_CHECK(PKIX_List_AppendItem
241 (infos, (PKIX_PL_Object *)certPolicyInfo, plContext),
242 PKIX_LISTAPPENDITEMFAILED);
243
244 PKIX_DECREF(pkixOID);
245 PKIX_DECREF(qualifiers);
246 PKIX_DECREF(certPolicyInfo);
247
248 policyInfos++;
249 }
250
251 /*
252 * If there were no policies, we went straight to
253 * cleanup, so we don't have to NULLCHECK infos.
254 */
255 PKIX_CHECK(PKIX_List_SetImmutable(infos, plContext),
256 PKIX_LISTSETIMMUTABLEFAILED);
257
258 *pCertPolicyInfos = infos;
259 infos = NULL;
260
261 cleanup:
262 if (certPol) {
263 PKIX_CERT_DEBUG
264 ("\t\tCalling CERT_DestroyCertificatePoliciesExtension).\n");
265 CERT_DestroyCertificatePoliciesExtension(certPol);
266 }
267
268 PKIX_DECREF(infos);
269 PKIX_DECREF(pkixOID);
270 PKIX_DECREF(qualifiers);
271 PKIX_DECREF(certPolicyInfo);
272 PKIX_DECREF(certPolicyQualifier);
273 PKIX_DECREF(qualifierArray);
274
275 PKIX_RETURN(CERT);
276 }
277
278 /*
279 * FUNCTION: pkix_pl_Cert_DecodePolicyMapping
280 * DESCRIPTION:
281 *
282 * Decodes the contents of the PolicyMapping extension of the CERTCertificate
283 * pointed to by "nssCert", storing the resulting List of CertPolicyMaps at
284 * the address pointed to by "pCertPolicyMaps". If this certificate does not
285 * have a PolicyMapping extension, NULL will be stored. If a List is returned,
286 * it will be immutable.
287 *
288 * PARAMETERS
289 * "nssCert"
290 * Address of the Cert data whose extension is to be examined. Must be
291 * non-NULL.
292 * "pCertPolicyMaps"
293 * Address where the List of CertPolicyMaps will be stored. Must be
294 * non-NULL.
295 * "plContext"
296 * Platform-specific context pointer.
297 * THREAD SAFETY:
298 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
299 * RETURNS:
300 * Returns NULL if the function succeeds.
301 * Returns a Cert Error if the function fails in a non-fatal way.
302 * Returns a Fatal Error if the function fails in an unrecoverable way.
303 */
304 static PKIX_Error *
pkix_pl_Cert_DecodePolicyMapping(CERTCertificate * nssCert,PKIX_List ** pCertPolicyMaps,void * plContext)305 pkix_pl_Cert_DecodePolicyMapping(
306 CERTCertificate *nssCert,
307 PKIX_List **pCertPolicyMaps,
308 void *plContext)
309 {
310 SECStatus rv;
311 SECItem encodedCertPolicyMaps;
312
313 /* Allocated in the arena; freed in CERT_Destroy... */
314 CERTCertificatePolicyMappings *certPolMaps = NULL;
315 CERTPolicyMap **policyMaps = NULL;
316
317 /* Holder for the return value */
318 PKIX_List *maps = NULL;
319
320 PKIX_PL_OID *issuerDomainOID = NULL;
321 PKIX_PL_OID *subjectDomainOID = NULL;
322 PKIX_PL_CertPolicyMap *certPolicyMap = NULL;
323
324 PKIX_ENTER(CERT, "pkix_pl_Cert_DecodePolicyMapping");
325 PKIX_NULLCHECK_TWO(nssCert, pCertPolicyMaps);
326
327 /* get PolicyMappings as a SECItem */
328 PKIX_CERT_DEBUG("\t\tCERT_FindCertExtension).\n");
329 rv = CERT_FindCertExtension
330 (nssCert, SEC_OID_X509_POLICY_MAPPINGS, &encodedCertPolicyMaps);
331 if (SECSuccess != rv) {
332 *pCertPolicyMaps = NULL;
333 goto cleanup;
334 }
335
336 /* translate PolicyMaps to CERTCertificatePolicyMappings */
337 certPolMaps = CERT_DecodePolicyMappingsExtension
338 (&encodedCertPolicyMaps);
339
340 PORT_Free(encodedCertPolicyMaps.data);
341
342 if (!certPolMaps) {
343 PKIX_ERROR(PKIX_CERTDECODEPOLICYMAPPINGSEXTENSIONFAILED);
344 }
345
346 PKIX_NULLCHECK_ONE(certPolMaps->policyMaps);
347
348 policyMaps = certPolMaps->policyMaps;
349
350 /* create a List of CertPolicyMap Objects */
351 PKIX_CHECK(PKIX_List_Create(&maps, plContext),
352 PKIX_LISTCREATEFAILED);
353
354 /*
355 * Traverse the CERTCertificatePolicyMappings structure,
356 * building each CertPolicyMap object in turn
357 */
358 do {
359 CERTPolicyMap *policyMap = *policyMaps;
360
361 /* create the OID for the issuer Domain Policy */
362 PKIX_CHECK(PKIX_PL_OID_CreateBySECItem
363 (&policyMap->issuerDomainPolicy,
364 &issuerDomainOID, plContext),
365 PKIX_OIDCREATEFAILED);
366
367 /* create the OID for the subject Domain Policy */
368 PKIX_CHECK(PKIX_PL_OID_CreateBySECItem
369 (&policyMap->subjectDomainPolicy,
370 &subjectDomainOID, plContext),
371 PKIX_OIDCREATEFAILED);
372
373 /* create the CertPolicyMap */
374
375 PKIX_CHECK(pkix_pl_CertPolicyMap_Create
376 (issuerDomainOID,
377 subjectDomainOID,
378 &certPolicyMap,
379 plContext),
380 PKIX_CERTPOLICYMAPCREATEFAILED);
381
382 PKIX_CHECK(PKIX_List_AppendItem
383 (maps, (PKIX_PL_Object *)certPolicyMap, plContext),
384 PKIX_LISTAPPENDITEMFAILED);
385
386 PKIX_DECREF(issuerDomainOID);
387 PKIX_DECREF(subjectDomainOID);
388 PKIX_DECREF(certPolicyMap);
389
390 policyMaps++;
391 } while (*policyMaps != NULL);
392
393 PKIX_CHECK(PKIX_List_SetImmutable(maps, plContext),
394 PKIX_LISTSETIMMUTABLEFAILED);
395
396 *pCertPolicyMaps = maps;
397 maps = NULL;
398
399 cleanup:
400 if (certPolMaps) {
401 PKIX_CERT_DEBUG
402 ("\t\tCalling CERT_DestroyPolicyMappingsExtension).\n");
403 CERT_DestroyPolicyMappingsExtension(certPolMaps);
404 }
405
406 PKIX_DECREF(maps);
407 PKIX_DECREF(issuerDomainOID);
408 PKIX_DECREF(subjectDomainOID);
409 PKIX_DECREF(certPolicyMap);
410
411 PKIX_RETURN(CERT);
412 }
413
414 /*
415 * FUNCTION: pkix_pl_Cert_DecodePolicyConstraints
416 * DESCRIPTION:
417 *
418 * Decodes the contents of the PolicyConstraints extension in the
419 * CERTCertificate pointed to by "nssCert", to obtain SkipCerts values
420 * which are stored at the addresses "pExplicitPolicySkipCerts" and
421 * "pInhibitMappingSkipCerts", respectively. If this certificate does
422 * not have an PolicyConstraints extension, or if either of the optional
423 * components is not supplied, this function stores a value of -1 for any
424 * missing component.
425 *
426 * PARAMETERS
427 * "nssCert"
428 * Address of the Cert data whose extension is to be examined. Must be
429 * non-NULL.
430 * "pExplicitPolicySkipCerts"
431 * Address where the SkipCert value for the requireExplicitPolicy
432 * component will be stored. Must be non-NULL.
433 * "pInhibitMappingSkipCerts"
434 * Address where the SkipCert value for the inhibitPolicyMapping
435 * component will be stored. Must be non-NULL.
436 * "plContext"
437 * Platform-specific context pointer.
438 * THREAD SAFETY:
439 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
440 * RETURNS:
441 * Returns NULL if the function succeeds.
442 * Returns a Cert Error if the function fails in a non-fatal way.
443 * Returns a Fatal Error if the function fails in an unrecoverable way.
444 */
445 static PKIX_Error *
pkix_pl_Cert_DecodePolicyConstraints(CERTCertificate * nssCert,PKIX_Int32 * pExplicitPolicySkipCerts,PKIX_Int32 * pInhibitMappingSkipCerts,void * plContext)446 pkix_pl_Cert_DecodePolicyConstraints(
447 CERTCertificate *nssCert,
448 PKIX_Int32 *pExplicitPolicySkipCerts,
449 PKIX_Int32 *pInhibitMappingSkipCerts,
450 void *plContext)
451 {
452 CERTCertificatePolicyConstraints policyConstraints;
453 SECStatus rv;
454 SECItem encodedCertPolicyConstraints;
455 PKIX_Int32 explicitPolicySkipCerts = -1;
456 PKIX_Int32 inhibitMappingSkipCerts = -1;
457
458 PKIX_ENTER(CERT, "pkix_pl_Cert_DecodePolicyConstraints");
459 PKIX_NULLCHECK_THREE
460 (nssCert, pExplicitPolicySkipCerts, pInhibitMappingSkipCerts);
461
462 /* get the two skipCert values as SECItems */
463 PKIX_CERT_DEBUG("\t\tCalling CERT_FindCertExtension).\n");
464 rv = CERT_FindCertExtension
465 (nssCert,
466 SEC_OID_X509_POLICY_CONSTRAINTS,
467 &encodedCertPolicyConstraints);
468
469 if (rv == SECSuccess) {
470
471 policyConstraints.explicitPolicySkipCerts.data =
472 (unsigned char *)&explicitPolicySkipCerts;
473 policyConstraints.inhibitMappingSkipCerts.data =
474 (unsigned char *)&inhibitMappingSkipCerts;
475
476 /* translate DER to CERTCertificatePolicyConstraints */
477 rv = CERT_DecodePolicyConstraintsExtension
478 (&policyConstraints, &encodedCertPolicyConstraints);
479
480 PORT_Free(encodedCertPolicyConstraints.data);
481
482 if (rv != SECSuccess) {
483 PKIX_ERROR
484 (PKIX_CERTDECODEPOLICYCONSTRAINTSEXTENSIONFAILED);
485 }
486 }
487
488 *pExplicitPolicySkipCerts = explicitPolicySkipCerts;
489 *pInhibitMappingSkipCerts = inhibitMappingSkipCerts;
490
491 cleanup:
492 PKIX_RETURN(CERT);
493 }
494
495 /*
496 * FUNCTION: pkix_pl_Cert_DecodeInhibitAnyPolicy
497 * DESCRIPTION:
498 *
499 * Decodes the contents of the InhibitAnyPolicy extension in the
500 * CERTCertificate pointed to by "nssCert", to obtain a SkipCerts value,
501 * which is stored at the address "pSkipCerts". If this certificate does
502 * not have an InhibitAnyPolicy extension, -1 will be stored.
503 *
504 * PARAMETERS
505 * "nssCert"
506 * Address of the Cert data whose InhibitAnyPolicy extension is to be
507 * processed. Must be non-NULL.
508 * "pSkipCerts"
509 * Address where the SkipCert value from the InhibitAnyPolicy extension
510 * will be stored. Must be non-NULL.
511 * "plContext"
512 * Platform-specific context pointer.
513 * THREAD SAFETY:
514 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
515 * RETURNS:
516 * Returns NULL if the function succeeds.
517 * Returns a Cert Error if the function fails in a non-fatal way.
518 * Returns a Fatal Error if the function fails in an unrecoverable way.
519 */
520 PKIX_Error *
pkix_pl_Cert_DecodeInhibitAnyPolicy(CERTCertificate * nssCert,PKIX_Int32 * pSkipCerts,void * plContext)521 pkix_pl_Cert_DecodeInhibitAnyPolicy(
522 CERTCertificate *nssCert,
523 PKIX_Int32 *pSkipCerts,
524 void *plContext)
525 {
526 CERTCertificateInhibitAny inhibitAny;
527 SECStatus rv;
528 SECItem encodedCertInhibitAny;
529 PKIX_Int32 skipCerts = -1;
530
531 PKIX_ENTER(CERT, "pkix_pl_Cert_DecodeInhibitAnyPolicy");
532 PKIX_NULLCHECK_TWO(nssCert, pSkipCerts);
533
534 /* get InhibitAny as a SECItem */
535 PKIX_CERT_DEBUG("\t\tCalling CERT_FindCertExtension).\n");
536 rv = CERT_FindCertExtension
537 (nssCert, SEC_OID_X509_INHIBIT_ANY_POLICY, &encodedCertInhibitAny);
538
539 if (rv == SECSuccess) {
540 inhibitAny.inhibitAnySkipCerts.data =
541 (unsigned char *)&skipCerts;
542
543 /* translate DER to CERTCertificateInhibitAny */
544 rv = CERT_DecodeInhibitAnyExtension
545 (&inhibitAny, &encodedCertInhibitAny);
546
547 PORT_Free(encodedCertInhibitAny.data);
548
549 if (rv != SECSuccess) {
550 PKIX_ERROR(PKIX_CERTDECODEINHIBITANYEXTENSIONFAILED);
551 }
552 }
553
554 *pSkipCerts = skipCerts;
555
556 cleanup:
557 PKIX_RETURN(CERT);
558 }
559
560 /*
561 * FUNCTION: pkix_pl_Cert_GetNssSubjectAltNames
562 * DESCRIPTION:
563 *
564 * Retrieves the Subject Alternative Names of the certificate specified by
565 * "cert" and stores it at "pNssSubjAltNames". If the Subject Alternative
566 * Name extension is not present, NULL is returned at "pNssSubjAltNames".
567 * If the Subject Alternative Names has not been previously decoded, it is
568 * decoded here with lock on the "cert" unless the flag "hasLock" indicates
569 * the lock had been obtained at a higher call level.
570 *
571 * PARAMETERS
572 * "cert"
573 * Address of the certificate whose Subject Alternative Names extensions
574 * is retrieved. Must be non-NULL.
575 * "hasLock"
576 * Boolean indicates caller has acquired a lock.
577 * Must be non-NULL.
578 * "pNssSubjAltNames"
579 * Address where the returned Subject Alternative Names will be stored.
580 * Must be non-NULL.
581 * "plContext"
582 * Platform-specific context pointer.
583 * THREAD SAFETY:
584 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
585 * RETURNS:
586 * Returns NULL if the function succeeds.
587 * Returns a Cert Error if the function fails in a non-fatal way.
588 * Returns a Fatal Error if the function fails in an unrecoverable way.
589 */
590 static PKIX_Error *
pkix_pl_Cert_GetNssSubjectAltNames(PKIX_PL_Cert * cert,PKIX_Boolean hasLock,CERTGeneralName ** pNssSubjAltNames,void * plContext)591 pkix_pl_Cert_GetNssSubjectAltNames(
592 PKIX_PL_Cert *cert,
593 PKIX_Boolean hasLock,
594 CERTGeneralName **pNssSubjAltNames,
595 void *plContext)
596 {
597 CERTCertificate *nssCert = NULL;
598 CERTGeneralName *nssOriginalAltName = NULL;
599 PLArenaPool *arena = NULL;
600 SECItem altNameExtension = {siBuffer, NULL, 0};
601 SECStatus rv = SECFailure;
602
603 PKIX_ENTER(CERT, "pkix_pl_Cert_GetNssSubjectAltNames");
604 PKIX_NULLCHECK_THREE(cert, pNssSubjAltNames, cert->nssCert);
605
606 nssCert = cert->nssCert;
607
608 if ((cert->nssSubjAltNames == NULL) && (!cert->subjAltNamesAbsent)){
609
610 if (!hasLock) {
611 PKIX_OBJECT_LOCK(cert);
612 }
613
614 if ((cert->nssSubjAltNames == NULL) &&
615 (!cert->subjAltNamesAbsent)){
616
617 PKIX_PL_NSSCALLRV(CERT, rv, CERT_FindCertExtension,
618 (nssCert,
619 SEC_OID_X509_SUBJECT_ALT_NAME,
620 &altNameExtension));
621
622 if (rv != SECSuccess) {
623 *pNssSubjAltNames = NULL;
624 cert->subjAltNamesAbsent = PKIX_TRUE;
625 goto cleanup;
626 }
627
628 if (cert->arenaNameConstraints == NULL) {
629 PKIX_PL_NSSCALLRV(CERT, arena, PORT_NewArena,
630 (DER_DEFAULT_CHUNKSIZE));
631
632 if (arena == NULL) {
633 PKIX_ERROR(PKIX_OUTOFMEMORY);
634 }
635 cert->arenaNameConstraints = arena;
636 }
637
638 PKIX_PL_NSSCALLRV
639 (CERT,
640 nssOriginalAltName,
641 (CERTGeneralName *) CERT_DecodeAltNameExtension,
642 (cert->arenaNameConstraints, &altNameExtension));
643
644 PKIX_PL_NSSCALL(CERT, PORT_Free, (altNameExtension.data));
645
646 if (nssOriginalAltName == NULL) {
647 PKIX_ERROR(PKIX_CERTDECODEALTNAMEEXTENSIONFAILED);
648 }
649 cert->nssSubjAltNames = nssOriginalAltName;
650
651 }
652
653 if (!hasLock) {
654 PKIX_OBJECT_UNLOCK(cert);
655 }
656 }
657
658 *pNssSubjAltNames = cert->nssSubjAltNames;
659
660 cleanup:
661 PKIX_OBJECT_UNLOCK(lockedObject);
662 PKIX_RETURN(CERT);
663 }
664
665 /*
666 * FUNCTION: pkix_pl_Cert_CheckExtendKeyUsage
667 * DESCRIPTION:
668 *
669 * For each of the ON bit in "requiredExtendedKeyUsages" that represents its
670 * SECCertUsageEnum type, this function checks "cert"'s certType (extended
671 * key usage) and key usage with what is required for SECCertUsageEnum type.
672 *
673 * PARAMETERS
674 * "cert"
675 * Address of the certificate whose Extended Key Usage extensions
676 * is retrieved. Must be non-NULL.
677 * "requiredExtendedKeyUsages"
678 * An unsigned integer, its bit location is ON based on the required key
679 * usage value representing in SECCertUsageEnum.
680 * "pPass"
681 * Address where the return value, indicating key usage check passed, is
682 * stored. Must be non-NULL.
683 * "plContext"
684 * Platform-specific context pointer.
685 * THREAD SAFETY:
686 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
687 * RETURNS:
688 * Returns NULL if the function succeeds.
689 * Returns a Cert Error if the function fails in a non-fatal way.
690 * Returns a Fatal Error if the function fails in an unrecoverable way.
691 */
692 PKIX_Error *
pkix_pl_Cert_CheckExtendedKeyUsage(PKIX_PL_Cert * cert,PKIX_UInt32 requiredExtendedKeyUsages,PKIX_Boolean * pPass,void * plContext)693 pkix_pl_Cert_CheckExtendedKeyUsage(
694 PKIX_PL_Cert *cert,
695 PKIX_UInt32 requiredExtendedKeyUsages,
696 PKIX_Boolean *pPass,
697 void *plContext)
698 {
699 PKIX_PL_CertBasicConstraints *basicConstraints = NULL;
700 PKIX_UInt32 certType = 0;
701 PKIX_UInt32 requiredKeyUsage = 0;
702 PKIX_UInt32 requiredCertType = 0;
703 PKIX_UInt32 requiredExtendedKeyUsage = 0;
704 PKIX_UInt32 i;
705 PKIX_Boolean isCA = PKIX_FALSE;
706 SECStatus rv = SECFailure;
707
708 PKIX_ENTER(CERT, "pkix_pl_Cert_CheckExtendKeyUsage");
709 PKIX_NULLCHECK_THREE(cert, pPass, cert->nssCert);
710
711 *pPass = PKIX_FALSE;
712
713 PKIX_CERT_DEBUG("\t\tCalling cert_GetCertType).\n");
714 cert_GetCertType(cert->nssCert);
715 certType = cert->nssCert->nsCertType;
716
717 PKIX_CHECK(PKIX_PL_Cert_GetBasicConstraints
718 (cert,
719 &basicConstraints,
720 plContext),
721 PKIX_CERTGETBASICCONSTRAINTFAILED);
722
723 if (basicConstraints != NULL) {
724 PKIX_CHECK(PKIX_PL_BasicConstraints_GetCAFlag
725 (basicConstraints, &isCA, plContext),
726 PKIX_BASICCONSTRAINTSGETCAFLAGFAILED);
727 }
728
729 i = 0;
730 while (requiredExtendedKeyUsages != 0) {
731
732 /* Find the bit location of the right-most non-zero bit */
733 while (requiredExtendedKeyUsages != 0) {
734 if (((1 << i) & requiredExtendedKeyUsages) != 0) {
735 requiredExtendedKeyUsage = 1 << i;
736 break;
737 }
738 i++;
739 }
740 requiredExtendedKeyUsages ^= requiredExtendedKeyUsage;
741
742 requiredExtendedKeyUsage = i;
743
744 PKIX_PL_NSSCALLRV(CERT, rv, CERT_KeyUsageAndTypeForCertUsage,
745 (requiredExtendedKeyUsage,
746 isCA,
747 &requiredKeyUsage,
748 &requiredCertType));
749
750 if (!(certType & requiredCertType)) {
751 goto cleanup;
752 }
753
754 PKIX_PL_NSSCALLRV(CERT, rv, CERT_CheckKeyUsage,
755 (cert->nssCert, requiredKeyUsage));
756 if (rv != SECSuccess) {
757 goto cleanup;
758 }
759 i++;
760
761 }
762
763 *pPass = PKIX_TRUE;
764
765 cleanup:
766 PKIX_DECREF(basicConstraints);
767 PKIX_RETURN(CERT);
768 }
769
770 /*
771 * FUNCTION: pkix_pl_Cert_ToString_Helper
772 * DESCRIPTION:
773 *
774 * Helper function that creates a string representation of the Cert pointed
775 * to by "cert" and stores it at "pString", where the value of
776 * "partialString" determines whether a full or partial representation of
777 * the Cert is stored.
778 *
779 * PARAMETERS
780 * "cert"
781 * Address of Cert whose string representation is desired.
782 * Must be non-NULL.
783 * "partialString"
784 * Boolean indicating whether a partial Cert representation is desired.
785 * "pString"
786 * Address where object pointer will be stored. Must be non-NULL.
787 * "plContext"
788 * Platform-specific context pointer.
789 * THREAD SAFETY:
790 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
791 * RETURNS:
792 * Returns NULL if the function succeeds.
793 * Returns a Cert Error if the function fails in a non-fatal way.
794 * Returns a Fatal Error if the function fails in an unrecoverable way.
795 */
796 PKIX_Error *
pkix_pl_Cert_ToString_Helper(PKIX_PL_Cert * cert,PKIX_Boolean partialString,PKIX_PL_String ** pString,void * plContext)797 pkix_pl_Cert_ToString_Helper(
798 PKIX_PL_Cert *cert,
799 PKIX_Boolean partialString,
800 PKIX_PL_String **pString,
801 void *plContext)
802 {
803 PKIX_PL_String *certString = NULL;
804 char *asciiFormat = NULL;
805 PKIX_PL_String *formatString = NULL;
806 PKIX_UInt32 certVersion;
807 PKIX_PL_BigInt *certSN = NULL;
808 PKIX_PL_String *certSNString = NULL;
809 PKIX_PL_X500Name *certIssuer = NULL;
810 PKIX_PL_String *certIssuerString = NULL;
811 PKIX_PL_X500Name *certSubject = NULL;
812 PKIX_PL_String *certSubjectString = NULL;
813 PKIX_PL_String *notBeforeString = NULL;
814 PKIX_PL_String *notAfterString = NULL;
815 PKIX_List *subjAltNames = NULL;
816 PKIX_PL_String *subjAltNamesString = NULL;
817 PKIX_PL_ByteArray *authKeyId = NULL;
818 PKIX_PL_String *authKeyIdString = NULL;
819 PKIX_PL_ByteArray *subjKeyId = NULL;
820 PKIX_PL_String *subjKeyIdString = NULL;
821 PKIX_PL_PublicKey *nssPubKey = NULL;
822 PKIX_PL_String *nssPubKeyString = NULL;
823 PKIX_List *critExtOIDs = NULL;
824 PKIX_PL_String *critExtOIDsString = NULL;
825 PKIX_List *extKeyUsages = NULL;
826 PKIX_PL_String *extKeyUsagesString = NULL;
827 PKIX_PL_CertBasicConstraints *basicConstraint = NULL;
828 PKIX_PL_String *certBasicConstraintsString = NULL;
829 PKIX_List *policyInfo = NULL;
830 PKIX_PL_String *certPolicyInfoString = NULL;
831 PKIX_List *certPolicyMappings = NULL;
832 PKIX_PL_String *certPolicyMappingsString = NULL;
833 PKIX_Int32 certExplicitPolicy = 0;
834 PKIX_Int32 certInhibitMapping = 0;
835 PKIX_Int32 certInhibitAnyPolicy = 0;
836 PKIX_PL_CertNameConstraints *nameConstraints = NULL;
837 PKIX_PL_String *nameConstraintsString = NULL;
838 PKIX_List *authorityInfoAccess = NULL;
839 PKIX_PL_String *authorityInfoAccessString = NULL;
840 PKIX_List *subjectInfoAccess = NULL;
841 PKIX_PL_String *subjectInfoAccessString = NULL;
842
843 PKIX_ENTER(CERT, "pkix_pl_Cert_ToString_Helper");
844 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pString);
845
846 /*
847 * XXX Add to this format as certificate components are developed.
848 */
849
850 if (partialString){
851 asciiFormat =
852 "\t[Issuer: %s\n"
853 "\t Subject: %s]";
854 } else {
855 asciiFormat =
856 "[\n"
857 "\tVersion: v%d\n"
858 "\tSerialNumber: %s\n"
859 "\tIssuer: %s\n"
860 "\tSubject: %s\n"
861 "\tValidity: [From: %s\n"
862 "\t To: %s]\n"
863 "\tSubjectAltNames: %s\n"
864 "\tAuthorityKeyId: %s\n"
865 "\tSubjectKeyId: %s\n"
866 "\tSubjPubKeyAlgId: %s\n"
867 "\tCritExtOIDs: %s\n"
868 "\tExtKeyUsages: %s\n"
869 "\tBasicConstraint: %s\n"
870 "\tCertPolicyInfo: %s\n"
871 "\tPolicyMappings: %s\n"
872 "\tExplicitPolicy: %d\n"
873 "\tInhibitMapping: %d\n"
874 "\tInhibitAnyPolicy:%d\n"
875 "\tNameConstraints: %s\n"
876 "\tAuthorityInfoAccess: %s\n"
877 "\tSubjectInfoAccess: %s\n"
878 "\tCacheFlag: %d\n"
879 "]\n";
880 }
881
882
883
884 PKIX_CHECK(PKIX_PL_String_Create
885 (PKIX_ESCASCII, asciiFormat, 0, &formatString, plContext),
886 PKIX_STRINGCREATEFAILED);
887
888 /* Issuer */
889 PKIX_CHECK(PKIX_PL_Cert_GetIssuer
890 (cert, &certIssuer, plContext),
891 PKIX_CERTGETISSUERFAILED);
892
893 PKIX_CHECK(PKIX_PL_Object_ToString
894 ((PKIX_PL_Object *)certIssuer, &certIssuerString, plContext),
895 PKIX_X500NAMETOSTRINGFAILED);
896
897 /* Subject */
898 PKIX_CHECK(PKIX_PL_Cert_GetSubject(cert, &certSubject, plContext),
899 PKIX_CERTGETSUBJECTFAILED);
900
901 PKIX_TOSTRING(certSubject, &certSubjectString, plContext,
902 PKIX_X500NAMETOSTRINGFAILED);
903
904 if (partialString){
905 PKIX_CHECK(PKIX_PL_Sprintf
906 (&certString,
907 plContext,
908 formatString,
909 certIssuerString,
910 certSubjectString),
911 PKIX_SPRINTFFAILED);
912
913 *pString = certString;
914 goto cleanup;
915 }
916
917 /* Version */
918 PKIX_CHECK(PKIX_PL_Cert_GetVersion(cert, &certVersion, plContext),
919 PKIX_CERTGETVERSIONFAILED);
920
921 /* SerialNumber */
922 PKIX_CHECK(PKIX_PL_Cert_GetSerialNumber(cert, &certSN, plContext),
923 PKIX_CERTGETSERIALNUMBERFAILED);
924
925 PKIX_CHECK(PKIX_PL_Object_ToString
926 ((PKIX_PL_Object *)certSN, &certSNString, plContext),
927 PKIX_BIGINTTOSTRINGFAILED);
928
929 /* Validity: NotBefore */
930 PKIX_CHECK(pkix_pl_Date_ToString_Helper
931 (&(cert->nssCert->validity.notBefore),
932 ¬BeforeString,
933 plContext),
934 PKIX_DATETOSTRINGHELPERFAILED);
935
936 /* Validity: NotAfter */
937 PKIX_CHECK(pkix_pl_Date_ToString_Helper
938 (&(cert->nssCert->validity.notAfter),
939 ¬AfterString,
940 plContext),
941 PKIX_DATETOSTRINGHELPERFAILED);
942
943 /* SubjectAltNames */
944 PKIX_CHECK(PKIX_PL_Cert_GetSubjectAltNames
945 (cert, &subjAltNames, plContext),
946 PKIX_CERTGETSUBJECTALTNAMESFAILED);
947
948 PKIX_TOSTRING(subjAltNames, &subjAltNamesString, plContext,
949 PKIX_LISTTOSTRINGFAILED);
950
951 /* AuthorityKeyIdentifier */
952 PKIX_CHECK(PKIX_PL_Cert_GetAuthorityKeyIdentifier
953 (cert, &authKeyId, plContext),
954 PKIX_CERTGETAUTHORITYKEYIDENTIFIERFAILED);
955
956 PKIX_TOSTRING(authKeyId, &authKeyIdString, plContext,
957 PKIX_BYTEARRAYTOSTRINGFAILED);
958
959 /* SubjectKeyIdentifier */
960 PKIX_CHECK(PKIX_PL_Cert_GetSubjectKeyIdentifier
961 (cert, &subjKeyId, plContext),
962 PKIX_CERTGETSUBJECTKEYIDENTIFIERFAILED);
963
964 PKIX_TOSTRING(subjKeyId, &subjKeyIdString, plContext,
965 PKIX_BYTEARRAYTOSTRINGFAILED);
966
967 /* SubjectPublicKey */
968 PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey
969 (cert, &nssPubKey, plContext),
970 PKIX_CERTGETSUBJECTPUBLICKEYFAILED);
971
972 PKIX_CHECK(PKIX_PL_Object_ToString
973 ((PKIX_PL_Object *)nssPubKey, &nssPubKeyString, plContext),
974 PKIX_PUBLICKEYTOSTRINGFAILED);
975
976 /* CriticalExtensionOIDs */
977 PKIX_CHECK(PKIX_PL_Cert_GetCriticalExtensionOIDs
978 (cert, &critExtOIDs, plContext),
979 PKIX_CERTGETCRITICALEXTENSIONOIDSFAILED);
980
981 PKIX_TOSTRING(critExtOIDs, &critExtOIDsString, plContext,
982 PKIX_LISTTOSTRINGFAILED);
983
984 /* ExtendedKeyUsages */
985 PKIX_CHECK(PKIX_PL_Cert_GetExtendedKeyUsage
986 (cert, &extKeyUsages, plContext),
987 PKIX_CERTGETEXTENDEDKEYUSAGEFAILED);
988
989 PKIX_TOSTRING(extKeyUsages, &extKeyUsagesString, plContext,
990 PKIX_LISTTOSTRINGFAILED);
991
992 /* CertBasicConstraints */
993 PKIX_CHECK(PKIX_PL_Cert_GetBasicConstraints
994 (cert, &basicConstraint, plContext),
995 PKIX_CERTGETBASICCONSTRAINTSFAILED);
996
997 PKIX_TOSTRING(basicConstraint, &certBasicConstraintsString, plContext,
998 PKIX_CERTBASICCONSTRAINTSTOSTRINGFAILED);
999
1000 /* CertPolicyInfo */
1001 PKIX_CHECK(PKIX_PL_Cert_GetPolicyInformation
1002 (cert, &policyInfo, plContext),
1003 PKIX_CERTGETPOLICYINFORMATIONFAILED);
1004
1005 PKIX_TOSTRING(policyInfo, &certPolicyInfoString, plContext,
1006 PKIX_LISTTOSTRINGFAILED);
1007
1008 /* Advanced Policies */
1009 PKIX_CHECK(PKIX_PL_Cert_GetPolicyMappings
1010 (cert, &certPolicyMappings, plContext),
1011 PKIX_CERTGETPOLICYMAPPINGSFAILED);
1012
1013 PKIX_TOSTRING(certPolicyMappings, &certPolicyMappingsString, plContext,
1014 PKIX_LISTTOSTRINGFAILED);
1015
1016 PKIX_CHECK(PKIX_PL_Cert_GetRequireExplicitPolicy
1017 (cert, &certExplicitPolicy, plContext),
1018 PKIX_CERTGETREQUIREEXPLICITPOLICYFAILED);
1019
1020 PKIX_CHECK(PKIX_PL_Cert_GetPolicyMappingInhibited
1021 (cert, &certInhibitMapping, plContext),
1022 PKIX_CERTGETPOLICYMAPPINGINHIBITEDFAILED);
1023
1024 PKIX_CHECK(PKIX_PL_Cert_GetInhibitAnyPolicy
1025 (cert, &certInhibitAnyPolicy, plContext),
1026 PKIX_CERTGETINHIBITANYPOLICYFAILED);
1027
1028 /* Name Constraints */
1029 PKIX_CHECK(PKIX_PL_Cert_GetNameConstraints
1030 (cert, &nameConstraints, plContext),
1031 PKIX_CERTGETNAMECONSTRAINTSFAILED);
1032
1033 PKIX_TOSTRING(nameConstraints, &nameConstraintsString, plContext,
1034 PKIX_LISTTOSTRINGFAILED);
1035
1036 /* Authority Information Access */
1037 PKIX_CHECK(PKIX_PL_Cert_GetAuthorityInfoAccess
1038 (cert, &authorityInfoAccess, plContext),
1039 PKIX_CERTGETAUTHORITYINFOACCESSFAILED);
1040
1041 PKIX_TOSTRING(authorityInfoAccess, &authorityInfoAccessString, plContext,
1042 PKIX_LISTTOSTRINGFAILED);
1043
1044 /* Subject Information Access */
1045 PKIX_CHECK(PKIX_PL_Cert_GetSubjectInfoAccess
1046 (cert, &subjectInfoAccess, plContext),
1047 PKIX_CERTGETSUBJECTINFOACCESSFAILED);
1048
1049 PKIX_TOSTRING(subjectInfoAccess, &subjectInfoAccessString, plContext,
1050 PKIX_LISTTOSTRINGFAILED);
1051
1052 PKIX_CHECK(PKIX_PL_Sprintf
1053 (&certString,
1054 plContext,
1055 formatString,
1056 certVersion + 1,
1057 certSNString,
1058 certIssuerString,
1059 certSubjectString,
1060 notBeforeString,
1061 notAfterString,
1062 subjAltNamesString,
1063 authKeyIdString,
1064 subjKeyIdString,
1065 nssPubKeyString,
1066 critExtOIDsString,
1067 extKeyUsagesString,
1068 certBasicConstraintsString,
1069 certPolicyInfoString,
1070 certPolicyMappingsString,
1071 certExplicitPolicy, /* an Int32, not a String */
1072 certInhibitMapping, /* an Int32, not a String */
1073 certInhibitAnyPolicy, /* an Int32, not a String */
1074 nameConstraintsString,
1075 authorityInfoAccessString,
1076 subjectInfoAccessString,
1077 cert->cacheFlag), /* a boolean */
1078 PKIX_SPRINTFFAILED);
1079
1080 *pString = certString;
1081
1082 cleanup:
1083 PKIX_DECREF(certSN);
1084 PKIX_DECREF(certSNString);
1085 PKIX_DECREF(certIssuer);
1086 PKIX_DECREF(certIssuerString);
1087 PKIX_DECREF(certSubject);
1088 PKIX_DECREF(certSubjectString);
1089 PKIX_DECREF(notBeforeString);
1090 PKIX_DECREF(notAfterString);
1091 PKIX_DECREF(subjAltNames);
1092 PKIX_DECREF(subjAltNamesString);
1093 PKIX_DECREF(authKeyId);
1094 PKIX_DECREF(authKeyIdString);
1095 PKIX_DECREF(subjKeyId);
1096 PKIX_DECREF(subjKeyIdString);
1097 PKIX_DECREF(nssPubKey);
1098 PKIX_DECREF(nssPubKeyString);
1099 PKIX_DECREF(critExtOIDs);
1100 PKIX_DECREF(critExtOIDsString);
1101 PKIX_DECREF(extKeyUsages);
1102 PKIX_DECREF(extKeyUsagesString);
1103 PKIX_DECREF(basicConstraint);
1104 PKIX_DECREF(certBasicConstraintsString);
1105 PKIX_DECREF(policyInfo);
1106 PKIX_DECREF(certPolicyInfoString);
1107 PKIX_DECREF(certPolicyMappings);
1108 PKIX_DECREF(certPolicyMappingsString);
1109 PKIX_DECREF(nameConstraints);
1110 PKIX_DECREF(nameConstraintsString);
1111 PKIX_DECREF(authorityInfoAccess);
1112 PKIX_DECREF(authorityInfoAccessString);
1113 PKIX_DECREF(subjectInfoAccess);
1114 PKIX_DECREF(subjectInfoAccessString);
1115 PKIX_DECREF(formatString);
1116
1117 PKIX_RETURN(CERT);
1118 }
1119
1120 /*
1121 * FUNCTION: pkix_pl_Cert_Destroy
1122 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
1123 */
1124 static PKIX_Error *
pkix_pl_Cert_Destroy(PKIX_PL_Object * object,void * plContext)1125 pkix_pl_Cert_Destroy(
1126 PKIX_PL_Object *object,
1127 void *plContext)
1128 {
1129 PKIX_PL_Cert *cert = NULL;
1130
1131 PKIX_ENTER(CERT, "pkix_pl_Cert_Destroy");
1132 PKIX_NULLCHECK_ONE(object);
1133
1134 PKIX_CHECK(pkix_CheckType(object, PKIX_CERT_TYPE, plContext),
1135 PKIX_OBJECTNOTCERT);
1136
1137 cert = (PKIX_PL_Cert*)object;
1138
1139 PKIX_DECREF(cert->subject);
1140 PKIX_DECREF(cert->issuer);
1141 PKIX_DECREF(cert->subjAltNames);
1142 PKIX_DECREF(cert->publicKeyAlgId);
1143 PKIX_DECREF(cert->publicKey);
1144 PKIX_DECREF(cert->serialNumber);
1145 PKIX_DECREF(cert->critExtOids);
1146 PKIX_DECREF(cert->authKeyId);
1147 PKIX_DECREF(cert->subjKeyId);
1148 PKIX_DECREF(cert->extKeyUsages);
1149 PKIX_DECREF(cert->certBasicConstraints);
1150 PKIX_DECREF(cert->certPolicyInfos);
1151 PKIX_DECREF(cert->certPolicyMappings);
1152 PKIX_DECREF(cert->nameConstraints);
1153 PKIX_DECREF(cert->store);
1154 PKIX_DECREF(cert->authorityInfoAccess);
1155 PKIX_DECREF(cert->subjectInfoAccess);
1156 PKIX_DECREF(cert->crldpList);
1157
1158 if (cert->arenaNameConstraints){
1159 /* This arena was allocated for SubjectAltNames */
1160 PKIX_PL_NSSCALL(CERT, PORT_FreeArena,
1161 (cert->arenaNameConstraints, PR_FALSE));
1162
1163 cert->arenaNameConstraints = NULL;
1164 cert->nssSubjAltNames = NULL;
1165 }
1166
1167 CERT_DestroyCertificate(cert->nssCert);
1168 cert->nssCert = NULL;
1169
1170 cleanup:
1171 PKIX_RETURN(CERT);
1172 }
1173
1174 /*
1175 * FUNCTION: pkix_pl_Cert_ToString
1176 * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
1177 */
1178 static PKIX_Error *
pkix_pl_Cert_ToString(PKIX_PL_Object * object,PKIX_PL_String ** pString,void * plContext)1179 pkix_pl_Cert_ToString(
1180 PKIX_PL_Object *object,
1181 PKIX_PL_String **pString,
1182 void *plContext)
1183 {
1184 PKIX_PL_String *certString = NULL;
1185 PKIX_PL_Cert *pkixCert = NULL;
1186
1187 PKIX_ENTER(CERT, "pkix_pl_Cert_toString");
1188 PKIX_NULLCHECK_TWO(object, pString);
1189
1190 PKIX_CHECK(pkix_CheckType(object, PKIX_CERT_TYPE, plContext),
1191 PKIX_OBJECTNOTCERT);
1192
1193 pkixCert = (PKIX_PL_Cert *)object;
1194
1195 PKIX_CHECK(pkix_pl_Cert_ToString_Helper
1196 (pkixCert, PKIX_FALSE, &certString, plContext),
1197 PKIX_CERTTOSTRINGHELPERFAILED);
1198
1199 *pString = certString;
1200
1201 cleanup:
1202 PKIX_RETURN(CERT);
1203 }
1204
1205 /*
1206 * FUNCTION: pkix_pl_Cert_Hashcode
1207 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
1208 */
1209 static PKIX_Error *
pkix_pl_Cert_Hashcode(PKIX_PL_Object * object,PKIX_UInt32 * pHashcode,void * plContext)1210 pkix_pl_Cert_Hashcode(
1211 PKIX_PL_Object *object,
1212 PKIX_UInt32 *pHashcode,
1213 void *plContext)
1214 {
1215 PKIX_PL_Cert *pkixCert = NULL;
1216 CERTCertificate *nssCert = NULL;
1217 unsigned char *derBytes = NULL;
1218 PKIX_UInt32 derLength;
1219 PKIX_UInt32 certHash;
1220
1221 PKIX_ENTER(CERT, "pkix_pl_Cert_Hashcode");
1222 PKIX_NULLCHECK_TWO(object, pHashcode);
1223
1224 PKIX_CHECK(pkix_CheckType(object, PKIX_CERT_TYPE, plContext),
1225 PKIX_OBJECTNOTCERT);
1226
1227 pkixCert = (PKIX_PL_Cert *)object;
1228
1229 nssCert = pkixCert->nssCert;
1230 derBytes = (nssCert->derCert).data;
1231 derLength = (nssCert->derCert).len;
1232
1233 PKIX_CHECK(pkix_hash(derBytes, derLength, &certHash, plContext),
1234 PKIX_HASHFAILED);
1235
1236 *pHashcode = certHash;
1237
1238 cleanup:
1239 PKIX_RETURN(CERT);
1240 }
1241
1242
1243 /*
1244 * FUNCTION: pkix_pl_Cert_Equals
1245 * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
1246 */
1247 static PKIX_Error *
pkix_pl_Cert_Equals(PKIX_PL_Object * firstObject,PKIX_PL_Object * secondObject,PKIX_Boolean * pResult,void * plContext)1248 pkix_pl_Cert_Equals(
1249 PKIX_PL_Object *firstObject,
1250 PKIX_PL_Object *secondObject,
1251 PKIX_Boolean *pResult,
1252 void *plContext)
1253 {
1254 CERTCertificate *firstCert = NULL;
1255 CERTCertificate *secondCert = NULL;
1256 PKIX_UInt32 secondType;
1257 PKIX_Boolean cmpResult;
1258
1259 PKIX_ENTER(CERT, "pkix_pl_Cert_Equals");
1260 PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
1261
1262 /* test that firstObject is a Cert */
1263 PKIX_CHECK(pkix_CheckType(firstObject, PKIX_CERT_TYPE, plContext),
1264 PKIX_FIRSTOBJECTNOTCERT);
1265
1266 /*
1267 * Since we know firstObject is a Cert, if both references are
1268 * identical, they must be equal
1269 */
1270 if (firstObject == secondObject){
1271 *pResult = PKIX_TRUE;
1272 goto cleanup;
1273 }
1274
1275 /*
1276 * If secondObject isn't a Cert, we don't throw an error.
1277 * We simply return a Boolean result of FALSE
1278 */
1279 *pResult = PKIX_FALSE;
1280 PKIX_CHECK(PKIX_PL_Object_GetType
1281 (secondObject, &secondType, plContext),
1282 PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
1283 if (secondType != PKIX_CERT_TYPE) goto cleanup;
1284
1285 firstCert = ((PKIX_PL_Cert *)firstObject)->nssCert;
1286 secondCert = ((PKIX_PL_Cert *)secondObject)->nssCert;
1287
1288 PKIX_NULLCHECK_TWO(firstCert, secondCert);
1289
1290 /* CERT_CompareCerts does byte comparison on DER encodings of certs */
1291 PKIX_CERT_DEBUG("\t\tCalling CERT_CompareCerts).\n");
1292 cmpResult = CERT_CompareCerts(firstCert, secondCert);
1293
1294 *pResult = cmpResult;
1295
1296 cleanup:
1297 PKIX_RETURN(CERT);
1298 }
1299
1300 /*
1301 * FUNCTION: pkix_pl_Cert_RegisterSelf
1302 * DESCRIPTION:
1303 * Registers PKIX_CERT_TYPE and its related functions with systemClasses[]
1304 * THREAD SAFETY:
1305 * Not Thread Safe - for performance and complexity reasons
1306 *
1307 * Since this function is only called by PKIX_PL_Initialize, which should
1308 * only be called once, it is acceptable that this function is not
1309 * thread-safe.
1310 */
1311 PKIX_Error *
pkix_pl_Cert_RegisterSelf(void * plContext)1312 pkix_pl_Cert_RegisterSelf(void *plContext)
1313 {
1314
1315 extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
1316 pkix_ClassTable_Entry entry;
1317
1318 PKIX_ENTER(CERT, "pkix_pl_Cert_RegisterSelf");
1319
1320 entry.description = "Cert";
1321 entry.objCounter = 0;
1322 entry.typeObjectSize = sizeof(PKIX_PL_Cert);
1323 entry.destructor = pkix_pl_Cert_Destroy;
1324 entry.equalsFunction = pkix_pl_Cert_Equals;
1325 entry.hashcodeFunction = pkix_pl_Cert_Hashcode;
1326 entry.toStringFunction = pkix_pl_Cert_ToString;
1327 entry.comparator = NULL;
1328 entry.duplicateFunction = pkix_duplicateImmutable;
1329
1330 systemClasses[PKIX_CERT_TYPE] = entry;
1331
1332 PKIX_RETURN(CERT);
1333 }
1334
1335 /*
1336 * FUNCTION: pkix_pl_Cert_CreateWithNSSCert
1337 * DESCRIPTION:
1338 *
1339 * Creates a new certificate using the CERTCertificate pointed to by "nssCert"
1340 * and stores it at "pCert". Once created, a Cert is immutable.
1341 *
1342 * This function is primarily used as a convenience function for the
1343 * performance tests that have easy access to a CERTCertificate.
1344 *
1345 * PARAMETERS:
1346 * "nssCert"
1347 * Address of CERTCertificate representing the NSS certificate.
1348 * Must be non-NULL.
1349 * "pCert"
1350 * Address where object pointer will be stored. Must be non-NULL.
1351 * "plContext"
1352 * Platform-specific context pointer.
1353 * THREAD SAFETY:
1354 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
1355 * RETURNS:
1356 * Returns NULL if the function succeeds.
1357 * Returns a Cert Error if the function fails in a non-fatal way.
1358 * Returns a Fatal Error if the function fails in an unrecoverable way.
1359 */
1360 PKIX_Error *
pkix_pl_Cert_CreateWithNSSCert(CERTCertificate * nssCert,PKIX_PL_Cert ** pCert,void * plContext)1361 pkix_pl_Cert_CreateWithNSSCert(
1362 CERTCertificate *nssCert,
1363 PKIX_PL_Cert **pCert,
1364 void *plContext)
1365 {
1366 PKIX_PL_Cert *cert = NULL;
1367
1368 PKIX_ENTER(CERT, "pkix_pl_Cert_CreateWithNSSCert");
1369 PKIX_NULLCHECK_TWO(pCert, nssCert);
1370
1371 /* create a PKIX_PL_Cert object */
1372 PKIX_CHECK(PKIX_PL_Object_Alloc
1373 (PKIX_CERT_TYPE,
1374 sizeof (PKIX_PL_Cert),
1375 (PKIX_PL_Object **)&cert,
1376 plContext),
1377 PKIX_COULDNOTCREATEOBJECT);
1378
1379 /* populate the nssCert field */
1380 cert->nssCert = nssCert;
1381
1382 /* initialize remaining fields */
1383 /*
1384 * Fields ending with Absent are initialized to PKIX_FALSE so that the
1385 * first time we need the value we will look for it. If we find it is
1386 * actually absent, the flag will at that time be set to PKIX_TRUE to
1387 * prevent searching for it later.
1388 * Fields ending with Processed are those where a value is defined
1389 * for the Absent case, and a value of zero is possible. When the
1390 * flag is still true we have to look for the field, set the default
1391 * value if necessary, and set the Processed flag to PKIX_TRUE.
1392 */
1393 cert->subject = NULL;
1394 cert->issuer = NULL;
1395 cert->subjAltNames = NULL;
1396 cert->subjAltNamesAbsent = PKIX_FALSE;
1397 cert->publicKeyAlgId = NULL;
1398 cert->publicKey = NULL;
1399 cert->serialNumber = NULL;
1400 cert->critExtOids = NULL;
1401 cert->subjKeyId = NULL;
1402 cert->subjKeyIdAbsent = PKIX_FALSE;
1403 cert->authKeyId = NULL;
1404 cert->authKeyIdAbsent = PKIX_FALSE;
1405 cert->extKeyUsages = NULL;
1406 cert->extKeyUsagesAbsent = PKIX_FALSE;
1407 cert->certBasicConstraints = NULL;
1408 cert->basicConstraintsAbsent = PKIX_FALSE;
1409 cert->certPolicyInfos = NULL;
1410 cert->policyInfoAbsent = PKIX_FALSE;
1411 cert->policyMappingsAbsent = PKIX_FALSE;
1412 cert->certPolicyMappings = NULL;
1413 cert->policyConstraintsProcessed = PKIX_FALSE;
1414 cert->policyConstraintsExplicitPolicySkipCerts = 0;
1415 cert->policyConstraintsInhibitMappingSkipCerts = 0;
1416 cert->inhibitAnyPolicyProcessed = PKIX_FALSE;
1417 cert->inhibitAnySkipCerts = 0;
1418 cert->nameConstraints = NULL;
1419 cert->nameConstraintsAbsent = PKIX_FALSE;
1420 cert->arenaNameConstraints = NULL;
1421 cert->nssSubjAltNames = NULL;
1422 cert->cacheFlag = PKIX_FALSE;
1423 cert->store = NULL;
1424 cert->authorityInfoAccess = NULL;
1425 cert->subjectInfoAccess = NULL;
1426 cert->isUserTrustAnchor = PKIX_FALSE;
1427 cert->crldpList = NULL;
1428
1429 *pCert = cert;
1430
1431 cleanup:
1432 PKIX_RETURN(CERT);
1433 }
1434
1435 /*
1436 * FUNCTION: pkix_pl_Cert_CreateToList
1437 * DESCRIPTION:
1438 *
1439 * Creates a new certificate using the DER-encoding pointed to by "derCertItem"
1440 * and appends it to the list pointed to by "certList". If Cert creation fails,
1441 * the function returns with certList unchanged, but any decoding Error is
1442 * discarded.
1443 *
1444 * PARAMETERS:
1445 * "derCertItem"
1446 * Address of SECItem containing the DER representation of a certificate.
1447 * Must be non-NULL.
1448 * "certList"
1449 * Address of List to which the Cert will be appended, if successfully
1450 * created. May be empty, but must be non-NULL.
1451 * "plContext"
1452 * Platform-specific context pointer.
1453 * THREAD SAFETY:
1454 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
1455 * RETURNS:
1456 * Returns NULL if the function succeeds.
1457 * Returns a Cert Error if the function fails in a non-fatal way.
1458 * Returns a Fatal Error if the function fails in an unrecoverable way.
1459 */
1460 PKIX_Error *
pkix_pl_Cert_CreateToList(SECItem * derCertItem,PKIX_List * certList,void * plContext)1461 pkix_pl_Cert_CreateToList(
1462 SECItem *derCertItem,
1463 PKIX_List *certList,
1464 void *plContext)
1465 {
1466 CERTCertificate *nssCert = NULL;
1467 PKIX_PL_Cert *cert = NULL;
1468 CERTCertDBHandle *handle;
1469
1470 PKIX_ENTER(CERT, "pkix_pl_Cert_CreateToList");
1471 PKIX_NULLCHECK_TWO(derCertItem, certList);
1472
1473 handle = CERT_GetDefaultCertDB();
1474 nssCert = CERT_NewTempCertificate(handle, derCertItem,
1475 /* nickname */ NULL,
1476 /* isPerm */ PR_FALSE,
1477 /* copyDer */ PR_TRUE);
1478 if (!nssCert) {
1479 goto cleanup;
1480 }
1481
1482 PKIX_CHECK(pkix_pl_Cert_CreateWithNSSCert
1483 (nssCert, &cert, plContext),
1484 PKIX_CERTCREATEWITHNSSCERTFAILED);
1485
1486 nssCert = NULL;
1487
1488 PKIX_CHECK(PKIX_List_AppendItem
1489 (certList, (PKIX_PL_Object *) cert, plContext),
1490 PKIX_LISTAPPENDITEMFAILED);
1491
1492 cleanup:
1493 if (nssCert) {
1494 CERT_DestroyCertificate(nssCert);
1495 }
1496
1497 PKIX_DECREF(cert);
1498 PKIX_RETURN(CERT);
1499 }
1500
1501 /* --Public-Functions------------------------------------------------------- */
1502
1503 /*
1504 * FUNCTION: PKIX_PL_Cert_Create (see comments in pkix_pl_pki.h)
1505 * XXX We may want to cache the cert after parsing it, so it can be reused
1506 * XXX Are the NSS/NSPR functions thread safe
1507 */
1508 PKIX_Error *
PKIX_PL_Cert_Create(PKIX_PL_ByteArray * byteArray,PKIX_PL_Cert ** pCert,void * plContext)1509 PKIX_PL_Cert_Create(
1510 PKIX_PL_ByteArray *byteArray,
1511 PKIX_PL_Cert **pCert,
1512 void *plContext)
1513 {
1514 CERTCertificate *nssCert = NULL;
1515 SECItem *derCertItem = NULL;
1516 void *derBytes = NULL;
1517 PKIX_UInt32 derLength;
1518 PKIX_PL_Cert *cert = NULL;
1519 CERTCertDBHandle *handle;
1520
1521 PKIX_ENTER(CERT, "PKIX_PL_Cert_Create");
1522 PKIX_NULLCHECK_TWO(pCert, byteArray);
1523
1524 PKIX_CHECK(PKIX_PL_ByteArray_GetPointer
1525 (byteArray, &derBytes, plContext),
1526 PKIX_BYTEARRAYGETPOINTERFAILED);
1527
1528 PKIX_CHECK(PKIX_PL_ByteArray_GetLength
1529 (byteArray, &derLength, plContext),
1530 PKIX_BYTEARRAYGETLENGTHFAILED);
1531
1532 derCertItem = SECITEM_AllocItem(NULL, NULL, derLength);
1533 if (derCertItem == NULL){
1534 PKIX_ERROR(PKIX_OUTOFMEMORY);
1535 }
1536
1537 (void) PORT_Memcpy(derCertItem->data, derBytes, derLength);
1538
1539 /*
1540 * setting copyDER to true forces NSS to make its own copy of the DER,
1541 * allowing us to free our copy without worrying about whether NSS
1542 * is still using it
1543 */
1544 handle = CERT_GetDefaultCertDB();
1545 nssCert = CERT_NewTempCertificate(handle, derCertItem,
1546 /* nickname */ NULL,
1547 /* isPerm */ PR_FALSE,
1548 /* copyDer */ PR_TRUE);
1549 if (!nssCert){
1550 PKIX_ERROR(PKIX_CERTDECODEDERCERTIFICATEFAILED);
1551 }
1552
1553 PKIX_CHECK(pkix_pl_Cert_CreateWithNSSCert
1554 (nssCert, &cert, plContext),
1555 PKIX_CERTCREATEWITHNSSCERTFAILED);
1556
1557 *pCert = cert;
1558
1559 cleanup:
1560 if (derCertItem){
1561 SECITEM_FreeItem(derCertItem, PKIX_TRUE);
1562 }
1563
1564 if (nssCert && PKIX_ERROR_RECEIVED){
1565 PKIX_CERT_DEBUG("\t\tCalling CERT_DestroyCertificate).\n");
1566 CERT_DestroyCertificate(nssCert);
1567 nssCert = NULL;
1568 }
1569
1570 PKIX_FREE(derBytes);
1571 PKIX_RETURN(CERT);
1572 }
1573
1574
1575 /*
1576 * FUNCTION: PKIX_PL_Cert_CreateFromCERTCertificate
1577 * (see comments in pkix_pl_pki.h)
1578 */
1579 PKIX_Error *
PKIX_PL_Cert_CreateFromCERTCertificate(const CERTCertificate * nssCert,PKIX_PL_Cert ** pCert,void * plContext)1580 PKIX_PL_Cert_CreateFromCERTCertificate(
1581 const CERTCertificate *nssCert,
1582 PKIX_PL_Cert **pCert,
1583 void *plContext)
1584 {
1585 void *buf = NULL;
1586 PKIX_UInt32 len;
1587 PKIX_PL_ByteArray *byteArray = NULL;
1588
1589 PKIX_ENTER(CERT, "PKIX_PL_Cert_CreateWithNssCert");
1590 PKIX_NULLCHECK_TWO(pCert, nssCert);
1591
1592 buf = (void*)nssCert->derCert.data;
1593 len = nssCert->derCert.len;
1594
1595 PKIX_CHECK(
1596 PKIX_PL_ByteArray_Create(buf, len, &byteArray, plContext),
1597 PKIX_BYTEARRAYCREATEFAILED);
1598
1599 PKIX_CHECK(
1600 PKIX_PL_Cert_Create(byteArray, pCert, plContext),
1601 PKIX_CERTCREATEWITHNSSCERTFAILED);
1602
1603 #ifdef PKIX_UNDEF
1604 /* will be tested and used as a patch for bug 391612 */
1605 nssCert = CERT_DupCertificate(nssInCert);
1606
1607 PKIX_CHECK(pkix_pl_Cert_CreateWithNSSCert
1608 (nssCert, &cert, plContext),
1609 PKIX_CERTCREATEWITHNSSCERTFAILED);
1610 #endif /* PKIX_UNDEF */
1611
1612 cleanup:
1613
1614 #ifdef PKIX_UNDEF
1615 if (nssCert && PKIX_ERROR_RECEIVED){
1616 PKIX_CERT_DEBUG("\t\tCalling CERT_DestroyCertificate).\n");
1617 CERT_DestroyCertificate(nssCert);
1618 nssCert = NULL;
1619 }
1620 #endif /* PKIX_UNDEF */
1621
1622 PKIX_DECREF(byteArray);
1623 PKIX_RETURN(CERT);
1624 }
1625
1626
1627 /*
1628 * FUNCTION: PKIX_PL_Cert_GetVersion (see comments in pkix_pl_pki.h)
1629 */
1630 PKIX_Error *
PKIX_PL_Cert_GetVersion(PKIX_PL_Cert * cert,PKIX_UInt32 * pVersion,void * plContext)1631 PKIX_PL_Cert_GetVersion(
1632 PKIX_PL_Cert *cert,
1633 PKIX_UInt32 *pVersion,
1634 void *plContext)
1635 {
1636 CERTCertificate *nssCert = NULL;
1637 PKIX_UInt32 myVersion = 0; /* v1 */
1638
1639 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetVersion");
1640 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pVersion);
1641
1642 nssCert = cert->nssCert;
1643 if (nssCert->version.len != 0) {
1644 myVersion = *(nssCert->version.data);
1645 }
1646
1647 if (myVersion > 2){
1648 PKIX_ERROR(PKIX_VERSIONVALUEMUSTBEV1V2ORV3);
1649 }
1650
1651 *pVersion = myVersion;
1652
1653 cleanup:
1654 PKIX_RETURN(CERT);
1655 }
1656
1657 /*
1658 * FUNCTION: PKIX_PL_Cert_GetSerialNumber (see comments in pkix_pl_pki.h)
1659 */
1660 PKIX_Error *
PKIX_PL_Cert_GetSerialNumber(PKIX_PL_Cert * cert,PKIX_PL_BigInt ** pSerialNumber,void * plContext)1661 PKIX_PL_Cert_GetSerialNumber(
1662 PKIX_PL_Cert *cert,
1663 PKIX_PL_BigInt **pSerialNumber,
1664 void *plContext)
1665 {
1666 CERTCertificate *nssCert = NULL;
1667 SECItem serialNumItem;
1668 PKIX_PL_BigInt *serialNumber = NULL;
1669 char *bytes = NULL;
1670 PKIX_UInt32 length;
1671
1672 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSerialNumber");
1673 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSerialNumber);
1674
1675 if (cert->serialNumber == NULL){
1676
1677 PKIX_OBJECT_LOCK(cert);
1678
1679 if (cert->serialNumber == NULL){
1680
1681 nssCert = cert->nssCert;
1682 serialNumItem = nssCert->serialNumber;
1683
1684 length = serialNumItem.len;
1685 bytes = (char *)serialNumItem.data;
1686
1687 PKIX_CHECK(pkix_pl_BigInt_CreateWithBytes
1688 (bytes, length, &serialNumber, plContext),
1689 PKIX_BIGINTCREATEWITHBYTESFAILED);
1690
1691 /* save a cached copy in case it is asked for again */
1692 cert->serialNumber = serialNumber;
1693 }
1694
1695 PKIX_OBJECT_UNLOCK(cert);
1696 }
1697
1698 PKIX_INCREF(cert->serialNumber);
1699 *pSerialNumber = cert->serialNumber;
1700
1701 cleanup:
1702 PKIX_OBJECT_UNLOCK(lockedObject);
1703 PKIX_RETURN(CERT);
1704 }
1705
1706 /*
1707 * FUNCTION: PKIX_PL_Cert_GetSubject (see comments in pkix_pl_pki.h)
1708 */
1709 PKIX_Error *
PKIX_PL_Cert_GetSubject(PKIX_PL_Cert * cert,PKIX_PL_X500Name ** pCertSubject,void * plContext)1710 PKIX_PL_Cert_GetSubject(
1711 PKIX_PL_Cert *cert,
1712 PKIX_PL_X500Name **pCertSubject,
1713 void *plContext)
1714 {
1715 PKIX_PL_X500Name *pkixSubject = NULL;
1716 CERTName *subjName = NULL;
1717 SECItem *derSubjName = NULL;
1718
1719 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubject");
1720 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pCertSubject);
1721
1722 /* if we don't have a cached copy from before, we create one */
1723 if (cert->subject == NULL){
1724
1725 PKIX_OBJECT_LOCK(cert);
1726
1727 if (cert->subject == NULL){
1728
1729 subjName = &cert->nssCert->subject;
1730 derSubjName = &cert->nssCert->derSubject;
1731
1732 /* if there is no subject name */
1733 if (derSubjName->data == NULL) {
1734
1735 pkixSubject = NULL;
1736
1737 } else {
1738 PKIX_CHECK(PKIX_PL_X500Name_CreateFromCERTName
1739 (derSubjName, subjName, &pkixSubject,
1740 plContext),
1741 PKIX_X500NAMECREATEFROMCERTNAMEFAILED);
1742
1743 }
1744 /* save a cached copy in case it is asked for again */
1745 cert->subject = pkixSubject;
1746 }
1747
1748 PKIX_OBJECT_UNLOCK(cert);
1749 }
1750
1751 PKIX_INCREF(cert->subject);
1752 *pCertSubject = cert->subject;
1753
1754 cleanup:
1755 PKIX_OBJECT_UNLOCK(lockedObject);
1756 PKIX_RETURN(CERT);
1757 }
1758
1759 /*
1760 * FUNCTION: PKIX_PL_Cert_GetIssuer (see comments in pkix_pl_pki.h)
1761 */
1762 PKIX_Error *
PKIX_PL_Cert_GetIssuer(PKIX_PL_Cert * cert,PKIX_PL_X500Name ** pCertIssuer,void * plContext)1763 PKIX_PL_Cert_GetIssuer(
1764 PKIX_PL_Cert *cert,
1765 PKIX_PL_X500Name **pCertIssuer,
1766 void *plContext)
1767 {
1768 PKIX_PL_X500Name *pkixIssuer = NULL;
1769 SECItem *derIssuerName = NULL;
1770 CERTName *issuerName = NULL;
1771
1772 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetIssuer");
1773 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pCertIssuer);
1774
1775 /* if we don't have a cached copy from before, we create one */
1776 if (cert->issuer == NULL){
1777
1778 PKIX_OBJECT_LOCK(cert);
1779
1780 if (cert->issuer == NULL){
1781
1782 issuerName = &cert->nssCert->issuer;
1783 derIssuerName = &cert->nssCert->derIssuer;
1784
1785 /* if there is no subject name */
1786 PKIX_CHECK(PKIX_PL_X500Name_CreateFromCERTName
1787 (derIssuerName, issuerName,
1788 &pkixIssuer, plContext),
1789 PKIX_X500NAMECREATEFROMCERTNAMEFAILED);
1790
1791 /* save a cached copy in case it is asked for again */
1792 cert->issuer = pkixIssuer;
1793 }
1794
1795 PKIX_OBJECT_UNLOCK(cert);
1796 }
1797
1798 PKIX_INCREF(cert->issuer);
1799 *pCertIssuer = cert->issuer;
1800
1801 cleanup:
1802 PKIX_RETURN(CERT);
1803 }
1804
1805 /*
1806 * FUNCTION: PKIX_PL_Cert_GetSubjectAltNames (see comments in pkix_pl_pki.h)
1807 */
1808 PKIX_Error *
PKIX_PL_Cert_GetSubjectAltNames(PKIX_PL_Cert * cert,PKIX_List ** pSubjectAltNames,void * plContext)1809 PKIX_PL_Cert_GetSubjectAltNames(
1810 PKIX_PL_Cert *cert,
1811 PKIX_List **pSubjectAltNames, /* list of PKIX_PL_GeneralName */
1812 void *plContext)
1813 {
1814 PKIX_PL_GeneralName *pkixAltName = NULL;
1815 PKIX_List *altNamesList = NULL;
1816
1817 CERTGeneralName *nssOriginalAltName = NULL;
1818 CERTGeneralName *nssTempAltName = NULL;
1819
1820 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectAltNames");
1821 PKIX_NULLCHECK_TWO(cert, pSubjectAltNames);
1822
1823 /* if we don't have a cached copy from before, we create one */
1824 if ((cert->subjAltNames == NULL) && (!cert->subjAltNamesAbsent)){
1825
1826 PKIX_OBJECT_LOCK(cert);
1827
1828 if ((cert->subjAltNames == NULL) &&
1829 (!cert->subjAltNamesAbsent)){
1830
1831 PKIX_CHECK(pkix_pl_Cert_GetNssSubjectAltNames
1832 (cert,
1833 PKIX_TRUE,
1834 &nssOriginalAltName,
1835 plContext),
1836 PKIX_CERTGETNSSSUBJECTALTNAMESFAILED);
1837
1838 if (nssOriginalAltName == NULL) {
1839 cert->subjAltNamesAbsent = PKIX_TRUE;
1840 pSubjectAltNames = NULL;
1841 goto cleanup;
1842 }
1843
1844 nssTempAltName = nssOriginalAltName;
1845
1846 PKIX_CHECK(PKIX_List_Create(&altNamesList, plContext),
1847 PKIX_LISTCREATEFAILED);
1848
1849 do {
1850 PKIX_CHECK(pkix_pl_GeneralName_Create
1851 (nssTempAltName, &pkixAltName, plContext),
1852 PKIX_GENERALNAMECREATEFAILED);
1853
1854 PKIX_CHECK(PKIX_List_AppendItem
1855 (altNamesList,
1856 (PKIX_PL_Object *)pkixAltName,
1857 plContext),
1858 PKIX_LISTAPPENDITEMFAILED);
1859
1860 PKIX_DECREF(pkixAltName);
1861
1862 PKIX_CERT_DEBUG
1863 ("\t\tCalling CERT_GetNextGeneralName).\n");
1864 nssTempAltName = CERT_GetNextGeneralName
1865 (nssTempAltName);
1866
1867 } while (nssTempAltName != nssOriginalAltName);
1868
1869 /* save a cached copy in case it is asked for again */
1870 cert->subjAltNames = altNamesList;
1871 PKIX_CHECK(PKIX_List_SetImmutable
1872 (cert->subjAltNames, plContext),
1873 PKIX_LISTSETIMMUTABLEFAILED);
1874
1875 }
1876
1877 PKIX_OBJECT_UNLOCK(cert);
1878 }
1879
1880 PKIX_INCREF(cert->subjAltNames);
1881
1882 *pSubjectAltNames = cert->subjAltNames;
1883
1884 cleanup:
1885 PKIX_DECREF(pkixAltName);
1886 if (PKIX_ERROR_RECEIVED){
1887 PKIX_DECREF(altNamesList);
1888 }
1889 PKIX_RETURN(CERT);
1890 }
1891
1892 /*
1893 * FUNCTION: PKIX_PL_Cert_GetAllSubjectNames (see comments in pkix_pl_pki.h)
1894 */
1895 PKIX_Error *
PKIX_PL_Cert_GetAllSubjectNames(PKIX_PL_Cert * cert,PKIX_List ** pAllSubjectNames,void * plContext)1896 PKIX_PL_Cert_GetAllSubjectNames(
1897 PKIX_PL_Cert *cert,
1898 PKIX_List **pAllSubjectNames, /* list of PKIX_PL_GeneralName */
1899 void *plContext)
1900 {
1901 CERTGeneralName *nssOriginalSubjectName = NULL;
1902 CERTGeneralName *nssTempSubjectName = NULL;
1903 PKIX_List *allSubjectNames = NULL;
1904 PKIX_PL_GeneralName *pkixSubjectName = NULL;
1905 PLArenaPool *arena = NULL;
1906
1907 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetAllSubjectNames");
1908 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pAllSubjectNames);
1909
1910
1911 if (cert->nssCert->subjectName == NULL){
1912 /* if there is no subject DN, just get altnames */
1913
1914 PKIX_CHECK(pkix_pl_Cert_GetNssSubjectAltNames
1915 (cert,
1916 PKIX_FALSE, /* hasLock */
1917 &nssOriginalSubjectName,
1918 plContext),
1919 PKIX_CERTGETNSSSUBJECTALTNAMESFAILED);
1920
1921 } else { /* get subject DN and altnames */
1922
1923 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1924 if (arena == NULL) {
1925 PKIX_ERROR(PKIX_OUTOFMEMORY);
1926 }
1927
1928 /* This NSS call returns both Subject and Subject Alt Names */
1929 PKIX_CERT_DEBUG("\t\tCalling CERT_GetCertificateNames\n");
1930 nssOriginalSubjectName =
1931 CERT_GetCertificateNames(cert->nssCert, arena);
1932 }
1933
1934 if (nssOriginalSubjectName == NULL) {
1935 pAllSubjectNames = NULL;
1936 goto cleanup;
1937 }
1938
1939 nssTempSubjectName = nssOriginalSubjectName;
1940
1941 PKIX_CHECK(PKIX_List_Create(&allSubjectNames, plContext),
1942 PKIX_LISTCREATEFAILED);
1943
1944 do {
1945 PKIX_CHECK(pkix_pl_GeneralName_Create
1946 (nssTempSubjectName, &pkixSubjectName, plContext),
1947 PKIX_GENERALNAMECREATEFAILED);
1948
1949 PKIX_CHECK(PKIX_List_AppendItem
1950 (allSubjectNames,
1951 (PKIX_PL_Object *)pkixSubjectName,
1952 plContext),
1953 PKIX_LISTAPPENDITEMFAILED);
1954
1955 PKIX_DECREF(pkixSubjectName);
1956
1957 PKIX_CERT_DEBUG
1958 ("\t\tCalling CERT_GetNextGeneralName).\n");
1959 nssTempSubjectName = CERT_GetNextGeneralName
1960 (nssTempSubjectName);
1961 } while (nssTempSubjectName != nssOriginalSubjectName);
1962
1963 *pAllSubjectNames = allSubjectNames;
1964
1965 cleanup:
1966 if (PKIX_ERROR_RECEIVED){
1967 PKIX_DECREF(allSubjectNames);
1968 }
1969
1970 if (arena){
1971 PORT_FreeArena(arena, PR_FALSE);
1972 }
1973 PKIX_DECREF(pkixSubjectName);
1974 PKIX_RETURN(CERT);
1975 }
1976
1977 /*
1978 * FUNCTION: PKIX_PL_Cert_GetSubjectPublicKeyAlgId
1979 * (see comments in pkix_pl_pki.h)
1980 */
1981 PKIX_Error *
PKIX_PL_Cert_GetSubjectPublicKeyAlgId(PKIX_PL_Cert * cert,PKIX_PL_OID ** pSubjKeyAlgId,void * plContext)1982 PKIX_PL_Cert_GetSubjectPublicKeyAlgId(
1983 PKIX_PL_Cert *cert,
1984 PKIX_PL_OID **pSubjKeyAlgId,
1985 void *plContext)
1986 {
1987 PKIX_PL_OID *pubKeyAlgId = NULL;
1988
1989 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectPublicKeyAlgId");
1990 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSubjKeyAlgId);
1991
1992 /* if we don't have a cached copy from before, we create one */
1993 if (cert->publicKeyAlgId == NULL){
1994 PKIX_OBJECT_LOCK(cert);
1995 if (cert->publicKeyAlgId == NULL){
1996 CERTCertificate *nssCert = cert->nssCert;
1997 SECAlgorithmID *algorithm;
1998 SECItem *algBytes;
1999
2000 algorithm = &nssCert->subjectPublicKeyInfo.algorithm;
2001 algBytes = &algorithm->algorithm;
2002 if (!algBytes->data || !algBytes->len) {
2003 PKIX_ERROR_FATAL(PKIX_ALGORITHMBYTESLENGTH0);
2004 }
2005 PKIX_CHECK(PKIX_PL_OID_CreateBySECItem
2006 (algBytes, &pubKeyAlgId, plContext),
2007 PKIX_OIDCREATEFAILED);
2008
2009 /* save a cached copy in case it is asked for again */
2010 cert->publicKeyAlgId = pubKeyAlgId;
2011 pubKeyAlgId = NULL;
2012 }
2013 PKIX_OBJECT_UNLOCK(cert);
2014 }
2015
2016 PKIX_INCREF(cert->publicKeyAlgId);
2017 *pSubjKeyAlgId = cert->publicKeyAlgId;
2018
2019 cleanup:
2020 PKIX_DECREF(pubKeyAlgId);
2021 PKIX_RETURN(CERT);
2022 }
2023
2024 /*
2025 * FUNCTION: PKIX_PL_Cert_GetSubjectPublicKey (see comments in pkix_pl_pki.h)
2026 */
2027 PKIX_Error *
PKIX_PL_Cert_GetSubjectPublicKey(PKIX_PL_Cert * cert,PKIX_PL_PublicKey ** pPublicKey,void * plContext)2028 PKIX_PL_Cert_GetSubjectPublicKey(
2029 PKIX_PL_Cert *cert,
2030 PKIX_PL_PublicKey **pPublicKey,
2031 void *plContext)
2032 {
2033 PKIX_PL_PublicKey *pkixPubKey = NULL;
2034 SECStatus rv;
2035
2036 CERTSubjectPublicKeyInfo *from = NULL;
2037 CERTSubjectPublicKeyInfo *to = NULL;
2038 SECItem *fromItem = NULL;
2039 SECItem *toItem = NULL;
2040
2041 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectPublicKey");
2042 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pPublicKey);
2043
2044 /* if we don't have a cached copy from before, we create one */
2045 if (cert->publicKey == NULL){
2046
2047 PKIX_OBJECT_LOCK(cert);
2048
2049 if (cert->publicKey == NULL){
2050
2051 /* create a PKIX_PL_PublicKey object */
2052 PKIX_CHECK(PKIX_PL_Object_Alloc
2053 (PKIX_PUBLICKEY_TYPE,
2054 sizeof (PKIX_PL_PublicKey),
2055 (PKIX_PL_Object **)&pkixPubKey,
2056 plContext),
2057 PKIX_COULDNOTCREATEOBJECT);
2058
2059 /* initialize fields */
2060 pkixPubKey->nssSPKI = NULL;
2061
2062 /* populate the SPKI field */
2063 PKIX_CHECK(PKIX_PL_Malloc
2064 (sizeof (CERTSubjectPublicKeyInfo),
2065 (void **)&pkixPubKey->nssSPKI,
2066 plContext),
2067 PKIX_MALLOCFAILED);
2068
2069 to = pkixPubKey->nssSPKI;
2070 from = &cert->nssCert->subjectPublicKeyInfo;
2071
2072 PKIX_NULLCHECK_TWO(to, from);
2073
2074 PKIX_CERT_DEBUG
2075 ("\t\tCalling SECOID_CopyAlgorithmID).\n");
2076 rv = SECOID_CopyAlgorithmID
2077 (NULL, &to->algorithm, &from->algorithm);
2078 if (rv != SECSuccess) {
2079 PKIX_ERROR(PKIX_SECOIDCOPYALGORITHMIDFAILED);
2080 }
2081
2082 /*
2083 * NSS stores the length of subjectPublicKey in bits.
2084 * Therefore, we use that length converted to bytes
2085 * using ((length+7)>>3) before calling PORT_Memcpy
2086 * in order to avoid "read from uninitialized memory"
2087 * errors.
2088 */
2089
2090 toItem = &to->subjectPublicKey;
2091 fromItem = &from->subjectPublicKey;
2092
2093 PKIX_NULLCHECK_TWO(toItem, fromItem);
2094
2095 toItem->type = fromItem->type;
2096
2097 toItem->data =
2098 (unsigned char*) PORT_ZAlloc(fromItem->len);
2099 if (!toItem->data){
2100 PKIX_ERROR(PKIX_OUTOFMEMORY);
2101 }
2102
2103 (void) PORT_Memcpy(toItem->data,
2104 fromItem->data,
2105 (fromItem->len + 7)>>3);
2106 toItem->len = fromItem->len;
2107
2108 /* save a cached copy in case it is asked for again */
2109 cert->publicKey = pkixPubKey;
2110 }
2111
2112 PKIX_OBJECT_UNLOCK(cert);
2113 }
2114
2115 PKIX_INCREF(cert->publicKey);
2116 *pPublicKey = cert->publicKey;
2117
2118 cleanup:
2119
2120 if (PKIX_ERROR_RECEIVED && pkixPubKey){
2121 PKIX_DECREF(pkixPubKey);
2122 cert->publicKey = NULL;
2123 }
2124 PKIX_RETURN(CERT);
2125 }
2126
2127 /*
2128 * FUNCTION: PKIX_PL_Cert_GetCriticalExtensionOIDs
2129 * (see comments in pkix_pl_pki.h)
2130 */
2131 PKIX_Error *
PKIX_PL_Cert_GetCriticalExtensionOIDs(PKIX_PL_Cert * cert,PKIX_List ** pList,void * plContext)2132 PKIX_PL_Cert_GetCriticalExtensionOIDs(
2133 PKIX_PL_Cert *cert,
2134 PKIX_List **pList, /* list of PKIX_PL_OID */
2135 void *plContext)
2136 {
2137 PKIX_List *oidsList = NULL;
2138 CERTCertExtension **extensions = NULL;
2139 CERTCertificate *nssCert = NULL;
2140
2141 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetCriticalExtensionOIDs");
2142 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pList);
2143
2144 /* if we don't have a cached copy from before, we create one */
2145 if (cert->critExtOids == NULL) {
2146
2147 PKIX_OBJECT_LOCK(cert);
2148
2149 if (cert->critExtOids == NULL) {
2150
2151 nssCert = cert->nssCert;
2152
2153 /*
2154 * ASN.1 for Extension
2155 *
2156 * Extension ::= SEQUENCE {
2157 * extnID OBJECT IDENTIFIER,
2158 * critical BOOLEAN DEFAULT FALSE,
2159 * extnValue OCTET STRING }
2160 *
2161 */
2162
2163 extensions = nssCert->extensions;
2164
2165 PKIX_CHECK(pkix_pl_OID_GetCriticalExtensionOIDs
2166 (extensions, &oidsList, plContext),
2167 PKIX_GETCRITICALEXTENSIONOIDSFAILED);
2168
2169 /* save a cached copy in case it is asked for again */
2170 cert->critExtOids = oidsList;
2171 }
2172
2173 PKIX_OBJECT_UNLOCK(cert);
2174 }
2175
2176 /* We should return a copy of the List since this list changes */
2177 PKIX_DUPLICATE(cert->critExtOids, pList, plContext,
2178 PKIX_OBJECTDUPLICATELISTFAILED);
2179
2180 cleanup:
2181 PKIX_OBJECT_UNLOCK(lockedObject);
2182 PKIX_RETURN(CERT);
2183 }
2184
2185 /*
2186 * FUNCTION: PKIX_PL_Cert_GetAuthorityKeyIdentifier
2187 * (see comments in pkix_pl_pki.h)
2188 */
2189 PKIX_Error *
PKIX_PL_Cert_GetAuthorityKeyIdentifier(PKIX_PL_Cert * cert,PKIX_PL_ByteArray ** pAuthKeyId,void * plContext)2190 PKIX_PL_Cert_GetAuthorityKeyIdentifier(
2191 PKIX_PL_Cert *cert,
2192 PKIX_PL_ByteArray **pAuthKeyId,
2193 void *plContext)
2194 {
2195 PKIX_PL_ByteArray *authKeyId = NULL;
2196 CERTCertificate *nssCert = NULL;
2197 CERTAuthKeyID *authKeyIdExtension = NULL;
2198 PLArenaPool *arena = NULL;
2199 SECItem retItem;
2200
2201 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetAuthorityKeyIdentifier");
2202 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pAuthKeyId);
2203
2204 /* if we don't have a cached copy from before, we create one */
2205 if ((cert->authKeyId == NULL) && (!cert->authKeyIdAbsent)){
2206
2207 PKIX_OBJECT_LOCK(cert);
2208
2209 if ((cert->authKeyId == NULL) && (!cert->authKeyIdAbsent)){
2210
2211 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2212 if (arena == NULL) {
2213 PKIX_ERROR(PKIX_OUTOFMEMORY);
2214 }
2215
2216 nssCert = cert->nssCert;
2217
2218 authKeyIdExtension =
2219 CERT_FindAuthKeyIDExten(arena, nssCert);
2220 if (authKeyIdExtension == NULL){
2221 cert->authKeyIdAbsent = PKIX_TRUE;
2222 *pAuthKeyId = NULL;
2223 goto cleanup;
2224 }
2225
2226 retItem = authKeyIdExtension->keyID;
2227
2228 if (retItem.len == 0){
2229 cert->authKeyIdAbsent = PKIX_TRUE;
2230 *pAuthKeyId = NULL;
2231 goto cleanup;
2232 }
2233
2234 PKIX_CHECK(PKIX_PL_ByteArray_Create
2235 (retItem.data,
2236 retItem.len,
2237 &authKeyId,
2238 plContext),
2239 PKIX_BYTEARRAYCREATEFAILED);
2240
2241 /* save a cached copy in case it is asked for again */
2242 cert->authKeyId = authKeyId;
2243 }
2244
2245 PKIX_OBJECT_UNLOCK(cert);
2246 }
2247
2248 PKIX_INCREF(cert->authKeyId);
2249 *pAuthKeyId = cert->authKeyId;
2250
2251 cleanup:
2252 PKIX_OBJECT_UNLOCK(lockedObject);
2253 if (arena){
2254 PORT_FreeArena(arena, PR_FALSE);
2255 }
2256 PKIX_RETURN(CERT);
2257 }
2258
2259 /*
2260 * FUNCTION: PKIX_PL_Cert_GetSubjectKeyIdentifier
2261 * (see comments in pkix_pl_pki.h)
2262 */
2263 PKIX_Error *
PKIX_PL_Cert_GetSubjectKeyIdentifier(PKIX_PL_Cert * cert,PKIX_PL_ByteArray ** pSubjKeyId,void * plContext)2264 PKIX_PL_Cert_GetSubjectKeyIdentifier(
2265 PKIX_PL_Cert *cert,
2266 PKIX_PL_ByteArray **pSubjKeyId,
2267 void *plContext)
2268 {
2269 PKIX_PL_ByteArray *subjKeyId = NULL;
2270 CERTCertificate *nssCert = NULL;
2271 SECItem *retItem = NULL;
2272 SECStatus status;
2273
2274 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectKeyIdentifier");
2275 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSubjKeyId);
2276
2277 /* if we don't have a cached copy from before, we create one */
2278 if ((cert->subjKeyId == NULL) && (!cert->subjKeyIdAbsent)){
2279
2280 PKIX_OBJECT_LOCK(cert);
2281
2282 if ((cert->subjKeyId == NULL) && (!cert->subjKeyIdAbsent)){
2283
2284 retItem = SECITEM_AllocItem(NULL, NULL, 0);
2285 if (retItem == NULL){
2286 PKIX_ERROR(PKIX_OUTOFMEMORY);
2287 }
2288
2289 nssCert = cert->nssCert;
2290
2291 status = CERT_FindSubjectKeyIDExtension
2292 (nssCert, retItem);
2293 if (status != SECSuccess) {
2294 cert->subjKeyIdAbsent = PKIX_TRUE;
2295 *pSubjKeyId = NULL;
2296 goto cleanup;
2297 }
2298
2299 PKIX_CHECK(PKIX_PL_ByteArray_Create
2300 (retItem->data,
2301 retItem->len,
2302 &subjKeyId,
2303 plContext),
2304 PKIX_BYTEARRAYCREATEFAILED);
2305
2306 /* save a cached copy in case it is asked for again */
2307 cert->subjKeyId = subjKeyId;
2308 }
2309
2310 PKIX_OBJECT_UNLOCK(cert);
2311 }
2312
2313 PKIX_INCREF(cert->subjKeyId);
2314 *pSubjKeyId = cert->subjKeyId;
2315
2316 cleanup:
2317 PKIX_OBJECT_UNLOCK(lockedObject);
2318 if (retItem){
2319 SECITEM_FreeItem(retItem, PKIX_TRUE);
2320 }
2321 PKIX_RETURN(CERT);
2322 }
2323
2324 /*
2325 * FUNCTION: PKIX_PL_Cert_GetExtendedKeyUsage (see comments in pkix_pl_pki.h)
2326 */
2327 PKIX_Error *
PKIX_PL_Cert_GetExtendedKeyUsage(PKIX_PL_Cert * cert,PKIX_List ** pKeyUsage,void * plContext)2328 PKIX_PL_Cert_GetExtendedKeyUsage(
2329 PKIX_PL_Cert *cert,
2330 PKIX_List **pKeyUsage, /* list of PKIX_PL_OID */
2331 void *plContext)
2332 {
2333 CERTOidSequence *extKeyUsage = NULL;
2334 CERTCertificate *nssCert = NULL;
2335 PKIX_PL_OID *pkixOID = NULL;
2336 PKIX_List *oidsList = NULL;
2337 SECItem **oids = NULL;
2338 SECItem encodedExtKeyUsage;
2339 SECStatus rv;
2340
2341 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetExtendedKeyUsage");
2342 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pKeyUsage);
2343
2344 /* if we don't have a cached copy from before, we create one */
2345 if ((cert->extKeyUsages == NULL) && (!cert->extKeyUsagesAbsent)){
2346
2347 PKIX_OBJECT_LOCK(cert);
2348
2349 if ((cert->extKeyUsages == NULL) &&
2350 (!cert->extKeyUsagesAbsent)){
2351
2352 nssCert = cert->nssCert;
2353
2354 rv = CERT_FindCertExtension
2355 (nssCert, SEC_OID_X509_EXT_KEY_USAGE,
2356 &encodedExtKeyUsage);
2357 if (rv != SECSuccess){
2358 cert->extKeyUsagesAbsent = PKIX_TRUE;
2359 *pKeyUsage = NULL;
2360 goto cleanup;
2361 }
2362
2363 extKeyUsage =
2364 CERT_DecodeOidSequence(&encodedExtKeyUsage);
2365 if (extKeyUsage == NULL){
2366 PKIX_ERROR(PKIX_CERTDECODEOIDSEQUENCEFAILED);
2367 }
2368
2369 PORT_Free(encodedExtKeyUsage.data);
2370
2371 oids = extKeyUsage->oids;
2372
2373 if (!oids){
2374 /* no extended key usage extensions found */
2375 cert->extKeyUsagesAbsent = PKIX_TRUE;
2376 *pKeyUsage = NULL;
2377 goto cleanup;
2378 }
2379
2380 PKIX_CHECK(PKIX_List_Create(&oidsList, plContext),
2381 PKIX_LISTCREATEFAILED);
2382
2383 while (*oids){
2384 SECItem *oid = *oids++;
2385
2386 PKIX_CHECK(PKIX_PL_OID_CreateBySECItem
2387 (oid, &pkixOID, plContext),
2388 PKIX_OIDCREATEFAILED);
2389
2390 PKIX_CHECK(PKIX_List_AppendItem
2391 (oidsList,
2392 (PKIX_PL_Object *)pkixOID,
2393 plContext),
2394 PKIX_LISTAPPENDITEMFAILED);
2395 PKIX_DECREF(pkixOID);
2396 }
2397
2398 PKIX_CHECK(PKIX_List_SetImmutable
2399 (oidsList, plContext),
2400 PKIX_LISTSETIMMUTABLEFAILED);
2401
2402 /* save a cached copy in case it is asked for again */
2403 cert->extKeyUsages = oidsList;
2404 oidsList = NULL;
2405 }
2406
2407 PKIX_OBJECT_UNLOCK(cert);
2408 }
2409
2410 PKIX_INCREF(cert->extKeyUsages);
2411 *pKeyUsage = cert->extKeyUsages;
2412
2413 cleanup:
2414 PKIX_OBJECT_UNLOCK(lockedObject);
2415
2416 PKIX_DECREF(pkixOID);
2417 PKIX_DECREF(oidsList);
2418 CERT_DestroyOidSequence(extKeyUsage);
2419
2420 PKIX_RETURN(CERT);
2421 }
2422
2423 /*
2424 * FUNCTION: PKIX_PL_Cert_GetBasicConstraints
2425 * (see comments in pkix_pl_pki.h)
2426 */
2427 PKIX_Error *
PKIX_PL_Cert_GetBasicConstraints(PKIX_PL_Cert * cert,PKIX_PL_CertBasicConstraints ** pBasicConstraints,void * plContext)2428 PKIX_PL_Cert_GetBasicConstraints(
2429 PKIX_PL_Cert *cert,
2430 PKIX_PL_CertBasicConstraints **pBasicConstraints,
2431 void *plContext)
2432 {
2433 CERTCertificate *nssCert = NULL;
2434 CERTBasicConstraints nssBasicConstraint;
2435 SECStatus rv;
2436 PKIX_PL_CertBasicConstraints *basic;
2437 PKIX_Int32 pathLen = 0;
2438 PKIX_Boolean isCA = PKIX_FALSE;
2439 enum {
2440 realBC, synthBC, absentBC
2441 } constraintSource = absentBC;
2442
2443 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetBasicConstraints");
2444 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pBasicConstraints);
2445
2446 /* if we don't have a cached copy from before, we create one */
2447 if ((cert->certBasicConstraints == NULL) &&
2448 (!cert->basicConstraintsAbsent)) {
2449
2450 PKIX_OBJECT_LOCK(cert);
2451
2452 if ((cert->certBasicConstraints == NULL) &&
2453 (!cert->basicConstraintsAbsent)) {
2454
2455 nssCert = cert->nssCert;
2456
2457 PKIX_CERT_DEBUG(
2458 "\t\tCalling Cert_FindBasicConstraintExten\n");
2459 rv = CERT_FindBasicConstraintExten
2460 (nssCert, &nssBasicConstraint);
2461 if (rv == SECSuccess) {
2462 constraintSource = realBC;
2463 }
2464
2465 if (constraintSource == absentBC) {
2466 /* can we deduce it's a CA and create a
2467 synthetic constraint?
2468 */
2469 CERTCertTrust trust;
2470 rv = CERT_GetCertTrust(nssCert, &trust);
2471 if (rv == SECSuccess) {
2472 int anyWantedFlag = CERTDB_TRUSTED_CA | CERTDB_VALID_CA;
2473 if ((trust.sslFlags & anyWantedFlag)
2474 || (trust.emailFlags & anyWantedFlag)
2475 || (trust.objectSigningFlags & anyWantedFlag)) {
2476
2477 constraintSource = synthBC;
2478 }
2479 }
2480 }
2481
2482 if (constraintSource == absentBC) {
2483 cert->basicConstraintsAbsent = PKIX_TRUE;
2484 *pBasicConstraints = NULL;
2485 goto cleanup;
2486 }
2487 }
2488
2489 if (constraintSource == synthBC) {
2490 isCA = PKIX_TRUE;
2491 pathLen = PKIX_UNLIMITED_PATH_CONSTRAINT;
2492 } else {
2493 isCA = (nssBasicConstraint.isCA)?PKIX_TRUE:PKIX_FALSE;
2494
2495 /* The pathLen has meaning only for CAs */
2496 if (isCA) {
2497 if (CERT_UNLIMITED_PATH_CONSTRAINT ==
2498 nssBasicConstraint.pathLenConstraint) {
2499 pathLen = PKIX_UNLIMITED_PATH_CONSTRAINT;
2500 } else {
2501 pathLen = nssBasicConstraint.pathLenConstraint;
2502 }
2503 }
2504 }
2505
2506 PKIX_CHECK(pkix_pl_CertBasicConstraints_Create
2507 (isCA, pathLen, &basic, plContext),
2508 PKIX_CERTBASICCONSTRAINTSCREATEFAILED);
2509
2510 /* save a cached copy in case it is asked for again */
2511 cert->certBasicConstraints = basic;
2512 }
2513
2514 PKIX_INCREF(cert->certBasicConstraints);
2515 *pBasicConstraints = cert->certBasicConstraints;
2516
2517 cleanup:
2518 PKIX_OBJECT_UNLOCK(lockedObject);
2519 PKIX_RETURN(CERT);
2520 }
2521
2522 /*
2523 * FUNCTION: PKIX_PL_Cert_GetPolicyInformation
2524 * (see comments in pkix_pl_pki.h)
2525 */
2526 PKIX_Error *
PKIX_PL_Cert_GetPolicyInformation(PKIX_PL_Cert * cert,PKIX_List ** pPolicyInfo,void * plContext)2527 PKIX_PL_Cert_GetPolicyInformation(
2528 PKIX_PL_Cert *cert,
2529 PKIX_List **pPolicyInfo,
2530 void *plContext)
2531 {
2532 PKIX_List *policyList = NULL;
2533
2534 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetPolicyInformation");
2535 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pPolicyInfo);
2536
2537 /* if we don't have a cached copy from before, we create one */
2538 if ((cert->certPolicyInfos == NULL) &&
2539 (!cert->policyInfoAbsent)) {
2540
2541 PKIX_OBJECT_LOCK(cert);
2542
2543 if ((cert->certPolicyInfos == NULL) &&
2544 (!cert->policyInfoAbsent)) {
2545
2546 PKIX_CHECK(pkix_pl_Cert_DecodePolicyInfo
2547 (cert->nssCert, &policyList, plContext),
2548 PKIX_CERTDECODEPOLICYINFOFAILED);
2549
2550 if (!policyList) {
2551 cert->policyInfoAbsent = PKIX_TRUE;
2552 *pPolicyInfo = NULL;
2553 goto cleanup;
2554 }
2555 }
2556
2557 PKIX_OBJECT_UNLOCK(cert);
2558
2559 /* save a cached copy in case it is asked for again */
2560 cert->certPolicyInfos = policyList;
2561 policyList = NULL;
2562 }
2563
2564 PKIX_INCREF(cert->certPolicyInfos);
2565 *pPolicyInfo = cert->certPolicyInfos;
2566
2567 cleanup:
2568 PKIX_OBJECT_UNLOCK(lockedObject);
2569
2570 PKIX_DECREF(policyList);
2571 PKIX_RETURN(CERT);
2572 }
2573
2574 /*
2575 * FUNCTION: PKIX_PL_Cert_GetPolicyMappings (see comments in pkix_pl_pki.h)
2576 */
2577 PKIX_Error *
PKIX_PL_Cert_GetPolicyMappings(PKIX_PL_Cert * cert,PKIX_List ** pPolicyMappings,void * plContext)2578 PKIX_PL_Cert_GetPolicyMappings(
2579 PKIX_PL_Cert *cert,
2580 PKIX_List **pPolicyMappings, /* list of PKIX_PL_CertPolicyMap */
2581 void *plContext)
2582 {
2583 PKIX_List *policyMappings = NULL; /* list of PKIX_PL_CertPolicyMap */
2584
2585 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetPolicyMappings");
2586 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pPolicyMappings);
2587
2588 /* if we don't have a cached copy from before, we create one */
2589 if (!(cert->certPolicyMappings) && !(cert->policyMappingsAbsent)) {
2590
2591 PKIX_OBJECT_LOCK(cert);
2592
2593 if (!(cert->certPolicyMappings) &&
2594 !(cert->policyMappingsAbsent)) {
2595
2596 PKIX_CHECK(pkix_pl_Cert_DecodePolicyMapping
2597 (cert->nssCert, &policyMappings, plContext),
2598 PKIX_CERTDECODEPOLICYMAPPINGFAILED);
2599
2600 if (!policyMappings) {
2601 cert->policyMappingsAbsent = PKIX_TRUE;
2602 *pPolicyMappings = NULL;
2603 goto cleanup;
2604 }
2605 }
2606
2607 PKIX_OBJECT_UNLOCK(cert);
2608
2609 /* save a cached copy in case it is asked for again */
2610 cert->certPolicyMappings = policyMappings;
2611 policyMappings = NULL;
2612 }
2613
2614 PKIX_INCREF(cert->certPolicyMappings);
2615 *pPolicyMappings = cert->certPolicyMappings;
2616
2617 cleanup:
2618 PKIX_OBJECT_UNLOCK(lockedObject);
2619
2620 PKIX_DECREF(policyMappings);
2621 PKIX_RETURN(CERT);
2622 }
2623
2624 /*
2625 * FUNCTION: PKIX_PL_Cert_GetRequireExplicitPolicy
2626 * (see comments in pkix_pl_pki.h)
2627 */
2628 PKIX_Error *
PKIX_PL_Cert_GetRequireExplicitPolicy(PKIX_PL_Cert * cert,PKIX_Int32 * pSkipCerts,void * plContext)2629 PKIX_PL_Cert_GetRequireExplicitPolicy(
2630 PKIX_PL_Cert *cert,
2631 PKIX_Int32 *pSkipCerts,
2632 void *plContext)
2633 {
2634 PKIX_Int32 explicitPolicySkipCerts = 0;
2635 PKIX_Int32 inhibitMappingSkipCerts = 0;
2636
2637 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetRequireExplicitPolicy");
2638 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSkipCerts);
2639
2640 if (!(cert->policyConstraintsProcessed)) {
2641 PKIX_OBJECT_LOCK(cert);
2642
2643 if (!(cert->policyConstraintsProcessed)) {
2644
2645 /*
2646 * If we can't process it now, we probably will be
2647 * unable to process it later. Set the default value.
2648 */
2649 cert->policyConstraintsProcessed = PKIX_TRUE;
2650 cert->policyConstraintsExplicitPolicySkipCerts = -1;
2651 cert->policyConstraintsInhibitMappingSkipCerts = -1;
2652
2653 PKIX_CHECK(pkix_pl_Cert_DecodePolicyConstraints
2654 (cert->nssCert,
2655 &explicitPolicySkipCerts,
2656 &inhibitMappingSkipCerts,
2657 plContext),
2658 PKIX_CERTDECODEPOLICYCONSTRAINTSFAILED);
2659
2660 cert->policyConstraintsExplicitPolicySkipCerts =
2661 explicitPolicySkipCerts;
2662 cert->policyConstraintsInhibitMappingSkipCerts =
2663 inhibitMappingSkipCerts;
2664 }
2665
2666 PKIX_OBJECT_UNLOCK(cert);
2667 }
2668
2669 *pSkipCerts = cert->policyConstraintsExplicitPolicySkipCerts;
2670
2671 cleanup:
2672 PKIX_OBJECT_UNLOCK(lockedObject);
2673 PKIX_RETURN(CERT);
2674 }
2675
2676 /*
2677 * FUNCTION: PKIX_PL_Cert_GetPolicyMappingInhibited
2678 * (see comments in pkix_pl_pki.h)
2679 */
2680 PKIX_Error *
PKIX_PL_Cert_GetPolicyMappingInhibited(PKIX_PL_Cert * cert,PKIX_Int32 * pSkipCerts,void * plContext)2681 PKIX_PL_Cert_GetPolicyMappingInhibited(
2682 PKIX_PL_Cert *cert,
2683 PKIX_Int32 *pSkipCerts,
2684 void *plContext)
2685 {
2686 PKIX_Int32 explicitPolicySkipCerts = 0;
2687 PKIX_Int32 inhibitMappingSkipCerts = 0;
2688
2689 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetPolicyMappingInhibited");
2690 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSkipCerts);
2691
2692 if (!(cert->policyConstraintsProcessed)) {
2693 PKIX_OBJECT_LOCK(cert);
2694
2695 if (!(cert->policyConstraintsProcessed)) {
2696
2697 /*
2698 * If we can't process it now, we probably will be
2699 * unable to process it later. Set the default value.
2700 */
2701 cert->policyConstraintsProcessed = PKIX_TRUE;
2702 cert->policyConstraintsExplicitPolicySkipCerts = -1;
2703 cert->policyConstraintsInhibitMappingSkipCerts = -1;
2704
2705 PKIX_CHECK(pkix_pl_Cert_DecodePolicyConstraints
2706 (cert->nssCert,
2707 &explicitPolicySkipCerts,
2708 &inhibitMappingSkipCerts,
2709 plContext),
2710 PKIX_CERTDECODEPOLICYCONSTRAINTSFAILED);
2711
2712 cert->policyConstraintsExplicitPolicySkipCerts =
2713 explicitPolicySkipCerts;
2714 cert->policyConstraintsInhibitMappingSkipCerts =
2715 inhibitMappingSkipCerts;
2716 }
2717
2718 PKIX_OBJECT_UNLOCK(cert);
2719 }
2720
2721 *pSkipCerts = cert->policyConstraintsInhibitMappingSkipCerts;
2722
2723 cleanup:
2724 PKIX_OBJECT_UNLOCK(lockedObject);
2725 PKIX_RETURN(CERT);
2726 }
2727
2728 /*
2729 * FUNCTION: PKIX_PL_Cert_GetInhibitAnyPolicy (see comments in pkix_pl_pki.h)
2730 */
2731 PKIX_Error *
PKIX_PL_Cert_GetInhibitAnyPolicy(PKIX_PL_Cert * cert,PKIX_Int32 * pSkipCerts,void * plContext)2732 PKIX_PL_Cert_GetInhibitAnyPolicy(
2733 PKIX_PL_Cert *cert,
2734 PKIX_Int32 *pSkipCerts,
2735 void *plContext)
2736 {
2737 PKIX_Int32 skipCerts = 0;
2738
2739 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetInhibitAnyPolicy");
2740 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSkipCerts);
2741
2742 if (!(cert->inhibitAnyPolicyProcessed)) {
2743
2744 PKIX_OBJECT_LOCK(cert);
2745
2746 if (!(cert->inhibitAnyPolicyProcessed)) {
2747
2748 /*
2749 * If we can't process it now, we probably will be
2750 * unable to process it later. Set the default value.
2751 */
2752 cert->inhibitAnyPolicyProcessed = PKIX_TRUE;
2753 cert->inhibitAnySkipCerts = -1;
2754
2755 PKIX_CHECK(pkix_pl_Cert_DecodeInhibitAnyPolicy
2756 (cert->nssCert, &skipCerts, plContext),
2757 PKIX_CERTDECODEINHIBITANYPOLICYFAILED);
2758
2759 cert->inhibitAnySkipCerts = skipCerts;
2760 }
2761
2762 PKIX_OBJECT_UNLOCK(cert);
2763 }
2764
2765 cleanup:
2766 PKIX_OBJECT_UNLOCK(lockedObject);
2767 *pSkipCerts = cert->inhibitAnySkipCerts;
2768 PKIX_RETURN(CERT);
2769 }
2770
2771 /*
2772 * FUNCTION: PKIX_PL_Cert_AreCertPoliciesCritical
2773 * (see comments in pkix_pl_pki.h)
2774 */
2775 PKIX_Error *
PKIX_PL_Cert_AreCertPoliciesCritical(PKIX_PL_Cert * cert,PKIX_Boolean * pCritical,void * plContext)2776 PKIX_PL_Cert_AreCertPoliciesCritical(
2777 PKIX_PL_Cert *cert,
2778 PKIX_Boolean *pCritical,
2779 void *plContext)
2780 {
2781 PKIX_Boolean criticality = PKIX_FALSE;
2782
2783 PKIX_ENTER(CERT, "PKIX_PL_Cert_AreCertPoliciesCritical");
2784 PKIX_NULLCHECK_TWO(cert, pCritical);
2785
2786 PKIX_CHECK(pkix_pl_Cert_IsExtensionCritical(
2787 cert,
2788 SEC_OID_X509_CERTIFICATE_POLICIES,
2789 &criticality,
2790 plContext),
2791 PKIX_CERTISEXTENSIONCRITICALFAILED);
2792
2793 *pCritical = criticality;
2794
2795 cleanup:
2796 PKIX_RETURN(CERT);
2797 }
2798
2799 /*
2800 * FUNCTION: PKIX_PL_Cert_VerifySignature (see comments in pkix_pl_pki.h)
2801 */
2802 PKIX_Error *
PKIX_PL_Cert_VerifySignature(PKIX_PL_Cert * cert,PKIX_PL_PublicKey * pubKey,void * plContext)2803 PKIX_PL_Cert_VerifySignature(
2804 PKIX_PL_Cert *cert,
2805 PKIX_PL_PublicKey *pubKey,
2806 void *plContext)
2807 {
2808 CERTCertificate *nssCert = NULL;
2809 SECKEYPublicKey *nssPubKey = NULL;
2810 CERTSignedData *tbsCert = NULL;
2811 PKIX_PL_Cert *cachedCert = NULL;
2812 PKIX_Error *verifySig = NULL;
2813 PKIX_Error *cachedSig = NULL;
2814 PKIX_Error *checkSig = NULL;
2815 SECStatus status;
2816 PKIX_Boolean certEqual = PKIX_FALSE;
2817 PKIX_Boolean certInHash = PKIX_FALSE;
2818 PKIX_Boolean checkCertSig = PKIX_TRUE;
2819 void* wincx = NULL;
2820
2821 PKIX_ENTER(CERT, "PKIX_PL_Cert_VerifySignature");
2822 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pubKey);
2823
2824 /* if the cert check flag is off, skip the check */
2825 checkSig = pkix_pl_NssContext_GetCertSignatureCheck(
2826 (PKIX_PL_NssContext *)plContext, &checkCertSig);
2827 if ((checkCertSig == PKIX_FALSE) && (checkSig == NULL)) {
2828 goto cleanup;
2829 }
2830
2831 verifySig = PKIX_PL_HashTable_Lookup
2832 (cachedCertSigTable,
2833 (PKIX_PL_Object *) pubKey,
2834 (PKIX_PL_Object **) &cachedCert,
2835 plContext);
2836
2837 if (cachedCert != NULL && verifySig == NULL) {
2838 /* Cached Signature Table lookup succeed */
2839 PKIX_EQUALS(cert, cachedCert, &certEqual, plContext,
2840 PKIX_OBJECTEQUALSFAILED);
2841 if (certEqual == PKIX_TRUE) {
2842 goto cleanup;
2843 }
2844 /* Different PubKey may hash to same value, skip add */
2845 certInHash = PKIX_TRUE;
2846 }
2847
2848 nssCert = cert->nssCert;
2849 tbsCert = &nssCert->signatureWrap;
2850
2851 PKIX_CERT_DEBUG("\t\tCalling SECKEY_ExtractPublicKey).\n");
2852 nssPubKey = SECKEY_ExtractPublicKey(pubKey->nssSPKI);
2853 if (!nssPubKey){
2854 PKIX_ERROR(PKIX_SECKEYEXTRACTPUBLICKEYFAILED);
2855 }
2856
2857 PKIX_CERT_DEBUG("\t\tCalling CERT_VerifySignedDataWithPublicKey).\n");
2858
2859 PKIX_CHECK(pkix_pl_NssContext_GetWincx
2860 ((PKIX_PL_NssContext *)plContext, &wincx),
2861 PKIX_NSSCONTEXTGETWINCXFAILED);
2862
2863 status = CERT_VerifySignedDataWithPublicKey(tbsCert, nssPubKey, wincx);
2864
2865 if (status != SECSuccess) {
2866 if (PORT_GetError() != SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED) {
2867 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
2868 }
2869 PKIX_ERROR(PKIX_SIGNATUREDIDNOTVERIFYWITHTHEPUBLICKEY);
2870 }
2871
2872 if (certInHash == PKIX_FALSE) {
2873 cachedSig = PKIX_PL_HashTable_Add
2874 (cachedCertSigTable,
2875 (PKIX_PL_Object *) pubKey,
2876 (PKIX_PL_Object *) cert,
2877 plContext);
2878
2879 if (cachedSig != NULL) {
2880 PKIX_DEBUG("PKIX_PL_HashTable_Add skipped: entry existed\n");
2881 }
2882 }
2883
2884 cleanup:
2885 if (nssPubKey){
2886 PKIX_CERT_DEBUG("\t\tCalling SECKEY_DestroyPublicKey).\n");
2887 SECKEY_DestroyPublicKey(nssPubKey);
2888 }
2889
2890 PKIX_DECREF(cachedCert);
2891 PKIX_DECREF(checkSig);
2892 PKIX_DECREF(verifySig);
2893 PKIX_DECREF(cachedSig);
2894
2895 PKIX_RETURN(CERT);
2896 }
2897
2898 /*
2899 * FUNCTION: PKIX_PL_Cert_CheckValidity (see comments in pkix_pl_pki.h)
2900 */
2901 PKIX_Error *
PKIX_PL_Cert_CheckValidity(PKIX_PL_Cert * cert,PKIX_PL_Date * date,void * plContext)2902 PKIX_PL_Cert_CheckValidity(
2903 PKIX_PL_Cert *cert,
2904 PKIX_PL_Date *date,
2905 void *plContext)
2906 {
2907 SECCertTimeValidity val;
2908 PRTime timeToCheck;
2909 PKIX_Boolean allowOverride;
2910 SECCertificateUsage requiredUsages;
2911
2912 PKIX_ENTER(CERT, "PKIX_PL_Cert_CheckValidity");
2913 PKIX_NULLCHECK_ONE(cert);
2914
2915 /* if the caller supplies a date, we use it; else, use current time */
2916 if (date != NULL){
2917 PKIX_CHECK(pkix_pl_Date_GetPRTime
2918 (date, &timeToCheck, plContext),
2919 PKIX_DATEGETPRTIMEFAILED);
2920 } else {
2921 timeToCheck = PR_Now();
2922 }
2923
2924 requiredUsages = ((PKIX_PL_NssContext*)plContext)->certificateUsage;
2925 allowOverride =
2926 (PRBool)((requiredUsages & certificateUsageSSLServer) ||
2927 (requiredUsages & certificateUsageSSLServerWithStepUp) ||
2928 (requiredUsages & certificateUsageIPsec));
2929 val = CERT_CheckCertValidTimes(cert->nssCert, timeToCheck, allowOverride);
2930 if (val != secCertTimeValid){
2931 PKIX_ERROR(PKIX_CERTCHECKCERTVALIDTIMESFAILED);
2932 }
2933
2934 cleanup:
2935 PKIX_RETURN(CERT);
2936 }
2937
2938 /*
2939 * FUNCTION: PKIX_PL_Cert_GetValidityNotAfter (see comments in pkix_pl_pki.h)
2940 */
2941 PKIX_Error *
PKIX_PL_Cert_GetValidityNotAfter(PKIX_PL_Cert * cert,PKIX_PL_Date ** pDate,void * plContext)2942 PKIX_PL_Cert_GetValidityNotAfter(
2943 PKIX_PL_Cert *cert,
2944 PKIX_PL_Date **pDate,
2945 void *plContext)
2946 {
2947 PRTime prtime;
2948 SECStatus rv = SECFailure;
2949
2950 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetValidityNotAfter");
2951 PKIX_NULLCHECK_TWO(cert, pDate);
2952
2953 PKIX_DATE_DEBUG("\t\tCalling DER_DecodeTimeChoice).\n");
2954 rv = DER_DecodeTimeChoice(&prtime, &(cert->nssCert->validity.notAfter));
2955 if (rv != SECSuccess){
2956 PKIX_ERROR(PKIX_DERDECODETIMECHOICEFAILED);
2957 }
2958
2959 PKIX_CHECK(pkix_pl_Date_CreateFromPRTime
2960 (prtime, pDate, plContext),
2961 PKIX_DATECREATEFROMPRTIMEFAILED);
2962
2963 cleanup:
2964 PKIX_RETURN(CERT);
2965 }
2966
2967 /*
2968 * FUNCTION: PKIX_PL_Cert_VerifyCertAndKeyType (see comments in pkix_pl_pki.h)
2969 */
2970 PKIX_Error *
PKIX_PL_Cert_VerifyCertAndKeyType(PKIX_PL_Cert * cert,PKIX_Boolean isChainCert,void * plContext)2971 PKIX_PL_Cert_VerifyCertAndKeyType(
2972 PKIX_PL_Cert *cert,
2973 PKIX_Boolean isChainCert,
2974 void *plContext)
2975 {
2976 PKIX_PL_CertBasicConstraints *basicConstraints = NULL;
2977 SECCertificateUsage certificateUsage;
2978 SECCertUsage certUsage = 0;
2979 unsigned int requiredKeyUsage;
2980 unsigned int requiredCertType;
2981 unsigned int certType;
2982 SECStatus rv = SECSuccess;
2983
2984 PKIX_ENTER(CERT, "PKIX_PL_Cert_VerifyCertType");
2985 PKIX_NULLCHECK_TWO(cert, plContext);
2986
2987 certificateUsage = ((PKIX_PL_NssContext*)plContext)->certificateUsage;
2988
2989 /* ensure we obtained a single usage bit only */
2990 PORT_Assert(!(certificateUsage & (certificateUsage - 1)));
2991
2992 /* convert SECertificateUsage (bit mask) to SECCertUsage (enum) */
2993 while (0 != (certificateUsage = certificateUsage >> 1)) { certUsage++; }
2994
2995 /* check key usage and netscape cert type */
2996 cert_GetCertType(cert->nssCert);
2997 certType = cert->nssCert->nsCertType;
2998 if (isChainCert ||
2999 (certUsage != certUsageVerifyCA && certUsage != certUsageAnyCA)) {
3000 rv = CERT_KeyUsageAndTypeForCertUsage(certUsage, isChainCert,
3001 &requiredKeyUsage,
3002 &requiredCertType);
3003 if (rv == SECFailure) {
3004 PKIX_ERROR(PKIX_UNSUPPORTEDCERTUSAGE);
3005 }
3006 } else {
3007 /* use this key usage and cert type for certUsageAnyCA and
3008 * certUsageVerifyCA. */
3009 requiredKeyUsage = KU_KEY_CERT_SIGN;
3010 requiredCertType = NS_CERT_TYPE_CA;
3011 }
3012 if (CERT_CheckKeyUsage(cert->nssCert, requiredKeyUsage) != SECSuccess) {
3013 PKIX_ERROR(PKIX_CERTCHECKKEYUSAGEFAILED);
3014 }
3015 if (!(certType & requiredCertType)) {
3016 PKIX_ERROR(PKIX_CERTCHECKCERTTYPEFAILED);
3017 }
3018 cleanup:
3019 PKIX_DECREF(basicConstraints);
3020 PKIX_RETURN(CERT);
3021 }
3022
3023 /*
3024 * FUNCTION: PKIX_PL_Cert_VerifyKeyUsage (see comments in pkix_pl_pki.h)
3025 */
3026 PKIX_Error *
PKIX_PL_Cert_VerifyKeyUsage(PKIX_PL_Cert * cert,PKIX_UInt32 keyUsage,void * plContext)3027 PKIX_PL_Cert_VerifyKeyUsage(
3028 PKIX_PL_Cert *cert,
3029 PKIX_UInt32 keyUsage,
3030 void *plContext)
3031 {
3032 CERTCertificate *nssCert = NULL;
3033 PKIX_UInt32 nssKeyUsage = 0;
3034 SECStatus status;
3035
3036 PKIX_ENTER(CERT, "PKIX_PL_Cert_VerifyKeyUsage");
3037 PKIX_NULLCHECK_TWO(cert, cert->nssCert);
3038
3039 nssCert = cert->nssCert;
3040
3041 /* if cert doesn't have keyUsage extension, all keyUsages are valid */
3042 if (!nssCert->keyUsagePresent){
3043 goto cleanup;
3044 }
3045
3046 if (keyUsage & PKIX_DIGITAL_SIGNATURE){
3047 nssKeyUsage = nssKeyUsage | KU_DIGITAL_SIGNATURE;
3048 }
3049
3050 if (keyUsage & PKIX_NON_REPUDIATION){
3051 nssKeyUsage = nssKeyUsage | KU_NON_REPUDIATION;
3052 }
3053
3054 if (keyUsage & PKIX_KEY_ENCIPHERMENT){
3055 nssKeyUsage = nssKeyUsage | KU_KEY_ENCIPHERMENT;
3056 }
3057
3058 if (keyUsage & PKIX_DATA_ENCIPHERMENT){
3059 nssKeyUsage = nssKeyUsage | KU_DATA_ENCIPHERMENT;
3060 }
3061
3062 if (keyUsage & PKIX_KEY_AGREEMENT){
3063 nssKeyUsage = nssKeyUsage | KU_KEY_AGREEMENT;
3064 }
3065
3066 if (keyUsage & PKIX_KEY_CERT_SIGN){
3067 nssKeyUsage = nssKeyUsage | KU_KEY_CERT_SIGN;
3068 }
3069
3070 if (keyUsage & PKIX_CRL_SIGN){
3071 nssKeyUsage = nssKeyUsage | KU_CRL_SIGN;
3072 }
3073
3074 if (keyUsage & PKIX_ENCIPHER_ONLY){
3075 nssKeyUsage = nssKeyUsage | 0x01;
3076 }
3077
3078 if (keyUsage & PKIX_DECIPHER_ONLY){
3079 /* XXX we should support this once it is fixed in NSS */
3080 PKIX_ERROR(PKIX_DECIPHERONLYKEYUSAGENOTSUPPORTED);
3081 }
3082
3083 status = CERT_CheckKeyUsage(nssCert, nssKeyUsage);
3084 if (status != SECSuccess) {
3085 PKIX_ERROR(PKIX_CERTCHECKKEYUSAGEFAILED);
3086 }
3087
3088 cleanup:
3089 PKIX_RETURN(CERT);
3090 }
3091
3092 /*
3093 * FUNCTION: PKIX_PL_Cert_GetNameConstraints
3094 * (see comments in pkix_pl_pki.h)
3095 */
3096 PKIX_Error *
PKIX_PL_Cert_GetNameConstraints(PKIX_PL_Cert * cert,PKIX_PL_CertNameConstraints ** pNameConstraints,void * plContext)3097 PKIX_PL_Cert_GetNameConstraints(
3098 PKIX_PL_Cert *cert,
3099 PKIX_PL_CertNameConstraints **pNameConstraints,
3100 void *plContext)
3101 {
3102 PKIX_PL_CertNameConstraints *nameConstraints = NULL;
3103
3104 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetNameConstraints");
3105 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pNameConstraints);
3106
3107 /* if we don't have a cached copy from before, we create one */
3108 if (cert->nameConstraints == NULL && !cert->nameConstraintsAbsent) {
3109
3110 PKIX_OBJECT_LOCK(cert);
3111
3112 if (cert->nameConstraints == NULL &&
3113 !cert->nameConstraintsAbsent) {
3114
3115 PKIX_CHECK(pkix_pl_CertNameConstraints_Create
3116 (cert->nssCert, &nameConstraints, plContext),
3117 PKIX_CERTNAMECONSTRAINTSCREATEFAILED);
3118
3119 if (nameConstraints == NULL) {
3120 cert->nameConstraintsAbsent = PKIX_TRUE;
3121 }
3122
3123 cert->nameConstraints = nameConstraints;
3124 }
3125
3126 PKIX_OBJECT_UNLOCK(cert);
3127
3128 }
3129
3130 PKIX_INCREF(cert->nameConstraints);
3131
3132 *pNameConstraints = cert->nameConstraints;
3133
3134 cleanup:
3135 PKIX_OBJECT_UNLOCK(lockedObject);
3136 PKIX_RETURN(CERT);
3137 }
3138
3139 /*
3140 * FUNCTION: PKIX_PL_Cert_CheckNameConstraints
3141 * (see comments in pkix_pl_pki.h)
3142 */
3143 PKIX_Error *
PKIX_PL_Cert_CheckNameConstraints(PKIX_PL_Cert * cert,PKIX_PL_CertNameConstraints * nameConstraints,PKIX_Boolean treatCommonNameAsDNSName,void * plContext)3144 PKIX_PL_Cert_CheckNameConstraints(
3145 PKIX_PL_Cert *cert,
3146 PKIX_PL_CertNameConstraints *nameConstraints,
3147 PKIX_Boolean treatCommonNameAsDNSName,
3148 void *plContext)
3149 {
3150 PKIX_Boolean checkPass = PKIX_TRUE;
3151 CERTGeneralName *nssSubjectNames = NULL;
3152 PLArenaPool *arena = NULL;
3153
3154 PKIX_ENTER(CERT, "PKIX_PL_Cert_CheckNameConstraints");
3155 PKIX_NULLCHECK_ONE(cert);
3156
3157 if (nameConstraints != NULL) {
3158
3159 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
3160 if (arena == NULL) {
3161 PKIX_ERROR(PKIX_OUTOFMEMORY);
3162 }
3163 /* only check common Name if the usage requires it */
3164 if (treatCommonNameAsDNSName) {
3165 SECCertificateUsage certificateUsage;
3166 certificateUsage = ((PKIX_PL_NssContext*)plContext)->certificateUsage;
3167 if ((certificateUsage != certificateUsageSSLServer) &&
3168 (certificateUsage != certificateUsageIPsec)) {
3169 treatCommonNameAsDNSName = PKIX_FALSE;
3170 }
3171 }
3172
3173 /* This NSS call returns Subject Alt Names. If
3174 * treatCommonNameAsDNSName is true, it also returns the
3175 * Subject Common Name
3176 */
3177 PKIX_CERT_DEBUG
3178 ("\t\tCalling CERT_GetConstrainedCertificateNames\n");
3179 nssSubjectNames = CERT_GetConstrainedCertificateNames
3180 (cert->nssCert, arena, treatCommonNameAsDNSName);
3181
3182 PKIX_CHECK(pkix_pl_CertNameConstraints_CheckNameSpaceNssNames
3183 (nssSubjectNames,
3184 nameConstraints,
3185 &checkPass,
3186 plContext),
3187 PKIX_CERTNAMECONSTRAINTSCHECKNAMESPACENSSNAMESFAILED);
3188
3189 if (checkPass != PKIX_TRUE) {
3190 PKIX_ERROR(PKIX_CERTFAILEDNAMECONSTRAINTSCHECKING);
3191 }
3192 }
3193
3194 cleanup:
3195 if (arena){
3196 PORT_FreeArena(arena, PR_FALSE);
3197 }
3198
3199 PKIX_RETURN(CERT);
3200 }
3201
3202 /*
3203 * FUNCTION: PKIX_PL_Cert_MergeNameConstraints
3204 * (see comments in pkix_pl_pki.h)
3205 */
3206 PKIX_Error *
PKIX_PL_Cert_MergeNameConstraints(PKIX_PL_CertNameConstraints * firstNC,PKIX_PL_CertNameConstraints * secondNC,PKIX_PL_CertNameConstraints ** pResultNC,void * plContext)3207 PKIX_PL_Cert_MergeNameConstraints(
3208 PKIX_PL_CertNameConstraints *firstNC,
3209 PKIX_PL_CertNameConstraints *secondNC,
3210 PKIX_PL_CertNameConstraints **pResultNC,
3211 void *plContext)
3212 {
3213 PKIX_PL_CertNameConstraints *mergedNC = NULL;
3214
3215 PKIX_ENTER(CERT, "PKIX_PL_Cert_MergeNameConstraints");
3216 PKIX_NULLCHECK_TWO(firstNC, pResultNC);
3217
3218 if (secondNC == NULL) {
3219
3220 PKIX_INCREF(firstNC);
3221 *pResultNC = firstNC;
3222
3223 goto cleanup;
3224 }
3225
3226 PKIX_CHECK(pkix_pl_CertNameConstraints_Merge
3227 (firstNC, secondNC, &mergedNC, plContext),
3228 PKIX_CERTNAMECONSTRAINTSMERGEFAILED);
3229
3230 *pResultNC = mergedNC;
3231
3232 cleanup:
3233 PKIX_RETURN(CERT);
3234 }
3235
3236 /*
3237 * Find out the state of the NSS trust bits for the requested usage.
3238 * Returns SECFailure if the cert is explicitly distrusted.
3239 * Returns SECSuccess if the cert can be used to form a chain (normal case),
3240 * or it is explicitly trusted. The trusted bool is set to true if it is
3241 * explicitly trusted.
3242 */
3243 static SECStatus
pkix_pl_Cert_GetTrusted(void * plContext,PKIX_PL_Cert * cert,PKIX_Boolean * trusted,PKIX_Boolean isCA)3244 pkix_pl_Cert_GetTrusted(void *plContext,
3245 PKIX_PL_Cert *cert,
3246 PKIX_Boolean *trusted,
3247 PKIX_Boolean isCA)
3248 {
3249 SECStatus rv;
3250 CERTCertificate *nssCert = NULL;
3251 SECCertUsage certUsage = 0;
3252 SECCertificateUsage certificateUsage;
3253 SECTrustType trustType;
3254 unsigned int trustFlags;
3255 unsigned int requiredFlags;
3256 CERTCertTrust trust;
3257
3258 *trusted = PKIX_FALSE;
3259
3260 /* no key usage information */
3261 if (plContext == NULL) {
3262 return SECSuccess;
3263 }
3264
3265 certificateUsage = ((PKIX_PL_NssContext*)plContext)->certificateUsage;
3266
3267 /* ensure we obtained a single usage bit only */
3268 PORT_Assert(!(certificateUsage & (certificateUsage - 1)));
3269
3270 /* convert SECertificateUsage (bit mask) to SECCertUsage (enum) */
3271 while (0 != (certificateUsage = certificateUsage >> 1)) { certUsage++; }
3272
3273 nssCert = cert->nssCert;
3274
3275 if (!isCA) {
3276 PRBool prTrusted;
3277 unsigned int failedFlags;
3278 rv = cert_CheckLeafTrust(nssCert, certUsage,
3279 &failedFlags, &prTrusted);
3280 *trusted = (PKIX_Boolean) prTrusted;
3281 return rv;
3282 }
3283 rv = CERT_TrustFlagsForCACertUsage(certUsage, &requiredFlags,
3284 &trustType);
3285 if (rv != SECSuccess) {
3286 return SECSuccess;
3287 }
3288
3289 rv = CERT_GetCertTrust(nssCert, &trust);
3290 if (rv != SECSuccess) {
3291 return SECSuccess;
3292 }
3293 trustFlags = SEC_GET_TRUST_FLAGS(&trust, trustType);
3294 /* normally trustTypeNone usages accept any of the given trust bits
3295 * being on as acceptable. If any are distrusted (and none are trusted),
3296 * then we will also distrust the cert */
3297 if ((trustFlags == 0) && (trustType == trustTypeNone)) {
3298 trustFlags = trust.sslFlags | trust.emailFlags |
3299 trust.objectSigningFlags;
3300 }
3301 if ((trustFlags & requiredFlags) == requiredFlags) {
3302 *trusted = PKIX_TRUE;
3303 return SECSuccess;
3304 }
3305 if ((trustFlags & CERTDB_TERMINAL_RECORD) &&
3306 ((trustFlags & (CERTDB_VALID_CA|CERTDB_TRUSTED)) == 0)) {
3307 return SECFailure;
3308 }
3309 return SECSuccess;
3310 }
3311
3312 /*
3313 * FUNCTION: PKIX_PL_Cert_IsCertTrusted
3314 * (see comments in pkix_pl_pki.h)
3315 */
3316 PKIX_Error *
PKIX_PL_Cert_IsCertTrusted(PKIX_PL_Cert * cert,PKIX_PL_TrustAnchorMode trustAnchorMode,PKIX_Boolean * pTrusted,void * plContext)3317 PKIX_PL_Cert_IsCertTrusted(
3318 PKIX_PL_Cert *cert,
3319 PKIX_PL_TrustAnchorMode trustAnchorMode,
3320 PKIX_Boolean *pTrusted,
3321 void *plContext)
3322 {
3323 PKIX_CertStore_CheckTrustCallback trustCallback = NULL;
3324 PKIX_Boolean trusted = PKIX_FALSE;
3325 SECStatus rv = SECFailure;
3326
3327 PKIX_ENTER(CERT, "PKIX_PL_Cert_IsCertTrusted");
3328 PKIX_NULLCHECK_TWO(cert, pTrusted);
3329
3330 /* Call GetTrusted first to see if we are going to distrust the
3331 * certificate */
3332 rv = pkix_pl_Cert_GetTrusted(plContext, cert, &trusted, PKIX_TRUE);
3333 if (rv != SECSuccess) {
3334 /* Failure means the cert is explicitly distrusted,
3335 * let the next level know not to use it. */
3336 *pTrusted = PKIX_FALSE;
3337 PKIX_ERROR(PKIX_CERTISCERTTRUSTEDFAILED);
3338 }
3339
3340 if (trustAnchorMode == PKIX_PL_TrustAnchorMode_Exclusive ||
3341 (trustAnchorMode == PKIX_PL_TrustAnchorMode_Additive &&
3342 cert->isUserTrustAnchor)) {
3343 /* Use the trust anchor's |trusted| value */
3344 *pTrusted = cert->isUserTrustAnchor;
3345 goto cleanup;
3346 }
3347
3348 /* no key usage information or store is not trusted */
3349 if (plContext == NULL || cert->store == NULL) {
3350 *pTrusted = PKIX_FALSE;
3351 goto cleanup;
3352 }
3353
3354 PKIX_CHECK(PKIX_CertStore_GetTrustCallback
3355 (cert->store, &trustCallback, plContext),
3356 PKIX_CERTSTOREGETTRUSTCALLBACKFAILED);
3357
3358 PKIX_CHECK_ONLY_FATAL(trustCallback
3359 (cert->store, cert, &trusted, plContext),
3360 PKIX_CHECKTRUSTCALLBACKFAILED);
3361
3362 /* allow trust store to override if we can trust the trust
3363 * bits */
3364 if (PKIX_ERROR_RECEIVED || (trusted == PKIX_FALSE)) {
3365 *pTrusted = PKIX_FALSE;
3366 goto cleanup;
3367 }
3368
3369 *pTrusted = trusted;
3370
3371 cleanup:
3372 PKIX_RETURN(CERT);
3373 }
3374
3375 /*
3376 * FUNCTION: PKIX_PL_Cert_IsLeafCertTrusted
3377 * (see comments in pkix_pl_pki.h)
3378 */
3379 PKIX_Error *
PKIX_PL_Cert_IsLeafCertTrusted(PKIX_PL_Cert * cert,PKIX_Boolean * pTrusted,void * plContext)3380 PKIX_PL_Cert_IsLeafCertTrusted(
3381 PKIX_PL_Cert *cert,
3382 PKIX_Boolean *pTrusted,
3383 void *plContext)
3384 {
3385 SECStatus rv;
3386
3387 PKIX_ENTER(CERT, "PKIX_PL_Cert_IsLeafCertTrusted");
3388 PKIX_NULLCHECK_TWO(cert, pTrusted);
3389
3390 *pTrusted = PKIX_FALSE;
3391
3392 rv = pkix_pl_Cert_GetTrusted(plContext, cert, pTrusted, PKIX_FALSE);
3393 if (rv != SECSuccess) {
3394 /* Failure means the cert is explicitly distrusted,
3395 * let the next level know not to use it. */
3396 *pTrusted = PKIX_FALSE;
3397 PKIX_ERROR(PKIX_CERTISCERTTRUSTEDFAILED);
3398 }
3399
3400 cleanup:
3401 PKIX_RETURN(CERT);
3402 }
3403
3404 /* FUNCTION: PKIX_PL_Cert_SetAsTrustAnchor */
3405 PKIX_Error*
PKIX_PL_Cert_SetAsTrustAnchor(PKIX_PL_Cert * cert,void * plContext)3406 PKIX_PL_Cert_SetAsTrustAnchor(PKIX_PL_Cert *cert,
3407 void *plContext)
3408 {
3409 PKIX_ENTER(CERT, "PKIX_PL_Cert_SetAsTrustAnchor");
3410 PKIX_NULLCHECK_ONE(cert);
3411
3412 cert->isUserTrustAnchor = PKIX_TRUE;
3413
3414 PKIX_RETURN(CERT);
3415 }
3416
3417 /*
3418 * FUNCTION: PKIX_PL_Cert_GetCacheFlag (see comments in pkix_pl_pki.h)
3419 */
3420 PKIX_Error *
PKIX_PL_Cert_GetCacheFlag(PKIX_PL_Cert * cert,PKIX_Boolean * pCacheFlag,void * plContext)3421 PKIX_PL_Cert_GetCacheFlag(
3422 PKIX_PL_Cert *cert,
3423 PKIX_Boolean *pCacheFlag,
3424 void *plContext)
3425 {
3426 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetCacheFlag");
3427 PKIX_NULLCHECK_TWO(cert, pCacheFlag);
3428
3429 *pCacheFlag = cert->cacheFlag;
3430
3431 PKIX_RETURN(CERT);
3432 }
3433
3434 /*
3435 * FUNCTION: PKIX_PL_Cert_SetCacheFlag (see comments in pkix_pl_pki.h)
3436 */
3437 PKIX_Error *
PKIX_PL_Cert_SetCacheFlag(PKIX_PL_Cert * cert,PKIX_Boolean cacheFlag,void * plContext)3438 PKIX_PL_Cert_SetCacheFlag(
3439 PKIX_PL_Cert *cert,
3440 PKIX_Boolean cacheFlag,
3441 void *plContext)
3442 {
3443 PKIX_ENTER(CERT, "PKIX_PL_Cert_SetCacheFlag");
3444 PKIX_NULLCHECK_ONE(cert);
3445
3446 cert->cacheFlag = cacheFlag;
3447
3448 PKIX_RETURN(CERT);
3449 }
3450
3451 /*
3452 * FUNCTION: PKIX_PL_Cert_GetTrustCertStore (see comments in pkix_pl_pki.h)
3453 */
3454 PKIX_Error *
PKIX_PL_Cert_GetTrustCertStore(PKIX_PL_Cert * cert,PKIX_CertStore ** pTrustCertStore,void * plContext)3455 PKIX_PL_Cert_GetTrustCertStore(
3456 PKIX_PL_Cert *cert,
3457 PKIX_CertStore **pTrustCertStore,
3458 void *plContext)
3459 {
3460 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetTrustCertStore");
3461 PKIX_NULLCHECK_TWO(cert, pTrustCertStore);
3462
3463 PKIX_INCREF(cert->store);
3464 *pTrustCertStore = cert->store;
3465
3466 cleanup:
3467 PKIX_RETURN(CERT);
3468 }
3469
3470 /*
3471 * FUNCTION: PKIX_PL_Cert_SetTrustCertStore (see comments in pkix_pl_pki.h)
3472 */
3473 PKIX_Error *
PKIX_PL_Cert_SetTrustCertStore(PKIX_PL_Cert * cert,PKIX_CertStore * trustCertStore,void * plContext)3474 PKIX_PL_Cert_SetTrustCertStore(
3475 PKIX_PL_Cert *cert,
3476 PKIX_CertStore *trustCertStore,
3477 void *plContext)
3478 {
3479 PKIX_ENTER(CERT, "PKIX_PL_Cert_SetTrustCertStore");
3480 PKIX_NULLCHECK_TWO(cert, trustCertStore);
3481
3482 PKIX_INCREF(trustCertStore);
3483 cert->store = trustCertStore;
3484
3485 cleanup:
3486 PKIX_RETURN(CERT);
3487 }
3488
3489 /*
3490 * FUNCTION: PKIX_PL_Cert_GetAuthorityInfoAccess
3491 * (see comments in pkix_pl_pki.h)
3492 */
3493 PKIX_Error *
PKIX_PL_Cert_GetAuthorityInfoAccess(PKIX_PL_Cert * cert,PKIX_List ** pAiaList,void * plContext)3494 PKIX_PL_Cert_GetAuthorityInfoAccess(
3495 PKIX_PL_Cert *cert,
3496 PKIX_List **pAiaList, /* of PKIX_PL_InfoAccess */
3497 void *plContext)
3498 {
3499 PKIX_List *aiaList = NULL; /* of PKIX_PL_InfoAccess */
3500 SECItem *encodedAIA = NULL;
3501 CERTAuthInfoAccess **aia = NULL;
3502 PLArenaPool *arena = NULL;
3503 SECStatus rv;
3504
3505 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetAuthorityInfoAccess");
3506 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pAiaList);
3507
3508 /* if we don't have a cached copy from before, we create one */
3509 if (cert->authorityInfoAccess == NULL) {
3510
3511 PKIX_OBJECT_LOCK(cert);
3512
3513 if (cert->authorityInfoAccess == NULL) {
3514
3515 PKIX_PL_NSSCALLRV(CERT, encodedAIA, SECITEM_AllocItem,
3516 (NULL, NULL, 0));
3517
3518 if (encodedAIA == NULL) {
3519 PKIX_ERROR(PKIX_OUTOFMEMORY);
3520 }
3521
3522 PKIX_PL_NSSCALLRV(CERT, rv, CERT_FindCertExtension,
3523 (cert->nssCert,
3524 SEC_OID_X509_AUTH_INFO_ACCESS,
3525 encodedAIA));
3526
3527 if (rv == SECFailure) {
3528 goto cleanup;
3529 }
3530
3531 PKIX_PL_NSSCALLRV(CERT, arena, PORT_NewArena,
3532 (DER_DEFAULT_CHUNKSIZE));
3533
3534 if (arena == NULL) {
3535 PKIX_ERROR(PKIX_OUTOFMEMORY);
3536 }
3537
3538 PKIX_PL_NSSCALLRV
3539 (CERT, aia, CERT_DecodeAuthInfoAccessExtension,
3540 (arena, encodedAIA));
3541
3542 PKIX_CHECK(pkix_pl_InfoAccess_CreateList
3543 (aia, &aiaList, plContext),
3544 PKIX_INFOACCESSCREATELISTFAILED);
3545
3546 cert->authorityInfoAccess = aiaList;
3547 }
3548
3549 PKIX_OBJECT_UNLOCK(cert);
3550 }
3551
3552 PKIX_INCREF(cert->authorityInfoAccess);
3553
3554 *pAiaList = cert->authorityInfoAccess;
3555
3556 cleanup:
3557 PKIX_OBJECT_UNLOCK(lockedObject);
3558 if (arena != NULL) {
3559 PORT_FreeArena(arena, PR_FALSE);
3560 }
3561
3562 if (encodedAIA != NULL) {
3563 SECITEM_FreeItem(encodedAIA, PR_TRUE);
3564 }
3565
3566 PKIX_RETURN(CERT);
3567 }
3568
3569 /* XXX Following defines belongs to NSS */
3570 static const unsigned char siaOIDString[] = {0x2b, 0x06, 0x01, 0x05, 0x05,
3571 0x07, 0x01, 0x0b};
3572 #define OI(x) { siDEROID, (unsigned char *)x, sizeof x }
3573
3574 /*
3575 * FUNCTION: PKIX_PL_Cert_GetSubjectInfoAccess
3576 * (see comments in pkix_pl_pki.h)
3577 */
3578 PKIX_Error *
PKIX_PL_Cert_GetSubjectInfoAccess(PKIX_PL_Cert * cert,PKIX_List ** pSiaList,void * plContext)3579 PKIX_PL_Cert_GetSubjectInfoAccess(
3580 PKIX_PL_Cert *cert,
3581 PKIX_List **pSiaList, /* of PKIX_PL_InfoAccess */
3582 void *plContext)
3583 {
3584 PKIX_List *siaList; /* of PKIX_PL_InfoAccess */
3585 SECItem siaOID = OI(siaOIDString);
3586 SECItem *encodedSubjInfoAccess = NULL;
3587 CERTAuthInfoAccess **subjInfoAccess = NULL;
3588 PLArenaPool *arena = NULL;
3589 SECStatus rv;
3590
3591 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectInfoAccess");
3592 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSiaList);
3593
3594 /* XXX
3595 * Codes to deal with SubjectInfoAccess OID should be moved to
3596 * NSS soon. I implemented them here so we don't touch NSS
3597 * source tree, from JP's suggestion.
3598 */
3599
3600 /* if we don't have a cached copy from before, we create one */
3601 if (cert->subjectInfoAccess == NULL) {
3602
3603 PKIX_OBJECT_LOCK(cert);
3604
3605 if (cert->subjectInfoAccess == NULL) {
3606
3607 encodedSubjInfoAccess = SECITEM_AllocItem(NULL, NULL, 0);
3608 if (encodedSubjInfoAccess == NULL) {
3609 PKIX_ERROR(PKIX_OUTOFMEMORY);
3610 }
3611
3612 PKIX_CERT_DEBUG
3613 ("\t\tCalling CERT_FindCertExtensionByOID).\n");
3614 rv = CERT_FindCertExtensionByOID
3615 (cert->nssCert, &siaOID, encodedSubjInfoAccess);
3616
3617 if (rv == SECFailure) {
3618 goto cleanup;
3619 }
3620
3621 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
3622 if (arena == NULL) {
3623 PKIX_ERROR(PKIX_OUTOFMEMORY);
3624 }
3625
3626 /* XXX
3627 * Decode Subject Information Access -
3628 * since its type is the same as Authority Information
3629 * Access, reuse the call. NSS- change name to avoid
3630 * confusion.
3631 */
3632 PKIX_CERT_DEBUG
3633 ("\t\tCalling CERT_DecodeAuthInfoAccessExtension).\n");
3634 subjInfoAccess = CERT_DecodeAuthInfoAccessExtension
3635 (arena, encodedSubjInfoAccess);
3636
3637 PKIX_CHECK(pkix_pl_InfoAccess_CreateList
3638 (subjInfoAccess, &siaList, plContext),
3639 PKIX_INFOACCESSCREATELISTFAILED);
3640
3641 cert->subjectInfoAccess = siaList;
3642
3643 }
3644
3645 PKIX_OBJECT_UNLOCK(cert);
3646 }
3647
3648 PKIX_INCREF(cert->subjectInfoAccess);
3649 *pSiaList = cert->subjectInfoAccess;
3650
3651 cleanup:
3652 PKIX_OBJECT_UNLOCK(lockedObject);
3653 if (arena != NULL) {
3654 PORT_FreeArena(arena, PR_FALSE);
3655 }
3656
3657 if (encodedSubjInfoAccess != NULL) {
3658 SECITEM_FreeItem(encodedSubjInfoAccess, PR_TRUE);
3659 }
3660 PKIX_RETURN(CERT);
3661 }
3662
3663 /*
3664 * FUNCTION: PKIX_PL_Cert_GetCrlDp
3665 * (see comments in pkix_pl_pki.h)
3666 */
3667 PKIX_Error *
PKIX_PL_Cert_GetCrlDp(PKIX_PL_Cert * cert,PKIX_List ** pDpList,void * plContext)3668 PKIX_PL_Cert_GetCrlDp(
3669 PKIX_PL_Cert *cert,
3670 PKIX_List **pDpList,
3671 void *plContext)
3672 {
3673 PKIX_UInt32 dpIndex = 0;
3674 pkix_pl_CrlDp *dp = NULL;
3675 CERTCrlDistributionPoints *dpoints = NULL;
3676
3677 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetCrlDp");
3678 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pDpList);
3679
3680 /* if we don't have a cached copy from before, we create one */
3681 if (cert->crldpList == NULL) {
3682 PKIX_OBJECT_LOCK(cert);
3683 if (cert->crldpList != NULL) {
3684 goto cleanup;
3685 }
3686 PKIX_CHECK(PKIX_List_Create(&cert->crldpList, plContext),
3687 PKIX_LISTCREATEFAILED);
3688 dpoints = CERT_FindCRLDistributionPoints(cert->nssCert);
3689 if (!dpoints || !dpoints->distPoints) {
3690 goto cleanup;
3691 }
3692 for (;dpoints->distPoints[dpIndex];dpIndex++) {
3693 PKIX_CHECK(
3694 pkix_pl_CrlDp_Create(dpoints->distPoints[dpIndex],
3695 &cert->nssCert->issuer,
3696 &dp, plContext),
3697 PKIX_CRLDPCREATEFAILED);
3698 /* Create crldp list in reverse order in attempt to get
3699 * to the whole crl first. */
3700 PKIX_CHECK(
3701 PKIX_List_InsertItem(cert->crldpList, 0,
3702 (PKIX_PL_Object*)dp,
3703 plContext),
3704 PKIX_LISTAPPENDITEMFAILED);
3705 PKIX_DECREF(dp);
3706 }
3707 }
3708 cleanup:
3709 PKIX_INCREF(cert->crldpList);
3710 *pDpList = cert->crldpList;
3711
3712 PKIX_OBJECT_UNLOCK(lockedObject);
3713 PKIX_DECREF(dp);
3714
3715 PKIX_RETURN(CERT);
3716 }
3717
3718 /*
3719 * FUNCTION: PKIX_PL_Cert_GetCERTCertificate
3720 * (see comments in pkix_pl_pki.h)
3721 */
3722 PKIX_Error *
PKIX_PL_Cert_GetCERTCertificate(PKIX_PL_Cert * cert,CERTCertificate ** pnssCert,void * plContext)3723 PKIX_PL_Cert_GetCERTCertificate(
3724 PKIX_PL_Cert *cert,
3725 CERTCertificate **pnssCert,
3726 void *plContext)
3727 {
3728 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetNssCert");
3729 PKIX_NULLCHECK_TWO(cert, pnssCert);
3730
3731 *pnssCert = CERT_DupCertificate(cert->nssCert);
3732
3733 PKIX_RETURN(CERT);
3734 }
3735