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                 &notBeforeString,
933                 plContext),
934                 PKIX_DATETOSTRINGHELPERFAILED);
935 
936         /* Validity: NotAfter */
937         PKIX_CHECK(pkix_pl_Date_ToString_Helper
938                 (&(cert->nssCert->validity.notAfter),
939                 &notAfterString,
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