andre@0: /* This Source Code Form is subject to the terms of the Mozilla Public andre@0: * License, v. 2.0. If a copy of the MPL was not distributed with this andre@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ andre@0: /* andre@0: * pkix_pl_cert.c andre@0: * andre@0: * Certificate Object Functions andre@0: * andre@0: */ andre@0: andre@0: #include "pkix_pl_cert.h" andre@0: andre@0: extern PKIX_PL_HashTable *cachedCertSigTable; andre@0: andre@0: /* --Private-Cert-Functions------------------------------------- */ andre@0: andre@0: /* andre@0: * FUNCTION: pkix_pl_Cert_IsExtensionCritical andre@0: * DESCRIPTION: andre@0: * andre@0: * Checks the Cert specified by "cert" to determine whether the extension andre@0: * whose tag is the UInt32 value given by "tag" is marked as a critical andre@0: * extension, and stores the result in "pCritical". andre@0: * andre@0: * Tags are the index into the table "oids" of SECOidData defined in the andre@0: * file secoid.c. Constants, such as SEC_OID_X509_CERTIFICATE_POLICIES, are andre@0: * are defined in secoidt.h for most of the table entries. andre@0: * andre@0: * If the specified tag is invalid (not in the list of tags) or if the andre@0: * extension is not found in the certificate, PKIX_FALSE is stored. andre@0: * andre@0: * PARAMETERS andre@0: * "cert" andre@0: * Address of Cert whose extensions are to be examined. Must be non-NULL. andre@0: * "tag" andre@0: * The UInt32 value of the tag for the extension whose criticality is andre@0: * to be determined andre@0: * "pCritical" andre@0: * Address where the Boolean value will be stored. Must be non-NULL. andre@0: * "plContext" andre@0: * Platform-specific context pointer. andre@0: * THREAD SAFETY: andre@0: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) andre@0: * RETURNS: andre@0: * Returns NULL if the function succeeds. andre@0: * Returns a Fatal Error if the function fails in an unrecoverable way. andre@0: */ andre@0: static PKIX_Error * andre@0: pkix_pl_Cert_IsExtensionCritical( andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_UInt32 tag, andre@0: PKIX_Boolean *pCritical, andre@0: void *plContext) andre@0: { andre@0: PKIX_Boolean criticality = PKIX_FALSE; andre@0: CERTCertExtension **extensions = NULL; andre@0: SECStatus rv; andre@0: andre@0: PKIX_ENTER(CERT, "pkix_pl_Cert_IsExtensionCritical"); andre@0: PKIX_NULLCHECK_THREE(cert, cert->nssCert, pCritical); andre@0: andre@0: extensions = cert->nssCert->extensions; andre@0: PKIX_NULLCHECK_ONE(extensions); andre@0: andre@0: PKIX_CERT_DEBUG("\t\tCalling CERT_GetExtenCriticality).\n"); andre@0: rv = CERT_GetExtenCriticality(extensions, tag, &criticality); andre@0: if (SECSuccess == rv) { andre@0: *pCritical = criticality; andre@0: } else { andre@0: *pCritical = PKIX_FALSE; andre@0: } andre@0: andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_pl_Cert_DecodePolicyInfo andre@0: * DESCRIPTION: andre@0: * andre@0: * Decodes the contents of the CertificatePolicy extension in the andre@0: * CERTCertificate pointed to by "nssCert", to create a List of andre@0: * CertPolicyInfos, which is stored at the address "pCertPolicyInfos". andre@0: * A CERTCertificate contains the DER representation of the Cert. andre@0: * If this certificate does not have a CertificatePolicy extension, andre@0: * NULL will be stored. If a List is returned, it will be immutable. andre@0: * andre@0: * PARAMETERS andre@0: * "nssCert" andre@0: * Address of the Cert data whose extension is to be examined. Must be andre@0: * non-NULL. andre@0: * "pCertPolicyInfos" andre@0: * Address where the List of CertPolicyInfos will be stored. Must be andre@0: * non-NULL. andre@0: * "plContext" andre@0: * Platform-specific context pointer. andre@0: * THREAD SAFETY: andre@0: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) andre@0: * RETURNS: andre@0: * Returns NULL if the function succeeds. andre@0: * Returns a Cert Error if the function fails in a non-fatal way. andre@0: * Returns a Fatal Error if the function fails in an unrecoverable way. andre@0: */ andre@0: static PKIX_Error * andre@0: pkix_pl_Cert_DecodePolicyInfo( andre@0: CERTCertificate *nssCert, andre@0: PKIX_List **pCertPolicyInfos, andre@0: void *plContext) andre@0: { andre@0: andre@0: SECStatus rv; andre@0: SECItem encodedCertPolicyInfo; andre@0: andre@0: /* Allocated in the arena; freed in CERT_Destroy... */ andre@0: CERTCertificatePolicies *certPol = NULL; andre@0: CERTPolicyInfo **policyInfos = NULL; andre@0: andre@0: /* Holder for the return value */ andre@0: PKIX_List *infos = NULL; andre@0: andre@0: PKIX_PL_OID *pkixOID = NULL; andre@0: PKIX_List *qualifiers = NULL; andre@0: PKIX_PL_CertPolicyInfo *certPolicyInfo = NULL; andre@0: PKIX_PL_CertPolicyQualifier *certPolicyQualifier = NULL; andre@0: PKIX_PL_ByteArray *qualifierArray = NULL; andre@0: andre@0: PKIX_ENTER(CERT, "pkix_pl_Cert_DecodePolicyInfo"); andre@0: PKIX_NULLCHECK_TWO(nssCert, pCertPolicyInfos); andre@0: andre@0: /* get PolicyInfo as a SECItem */ andre@0: PKIX_CERT_DEBUG("\t\tCERT_FindCertExtension).\n"); andre@0: rv = CERT_FindCertExtension andre@0: (nssCert, andre@0: SEC_OID_X509_CERTIFICATE_POLICIES, andre@0: &encodedCertPolicyInfo); andre@0: if (SECSuccess != rv) { andre@0: *pCertPolicyInfos = NULL; andre@0: goto cleanup; andre@0: } andre@0: andre@0: /* translate PolicyInfo to CERTCertificatePolicies */ andre@0: PKIX_CERT_DEBUG("\t\tCERT_DecodeCertificatePoliciesExtension).\n"); andre@0: certPol = CERT_DecodeCertificatePoliciesExtension andre@0: (&encodedCertPolicyInfo); andre@0: andre@0: PORT_Free(encodedCertPolicyInfo.data); andre@0: andre@0: if (NULL == certPol) { andre@0: PKIX_ERROR(PKIX_CERTDECODECERTIFICATEPOLICIESEXTENSIONFAILED); andre@0: } andre@0: andre@0: /* andre@0: * Check whether there are any policyInfos, so we can andre@0: * avoid creating an unnecessary List andre@0: */ andre@0: policyInfos = certPol->policyInfos; andre@0: if (!policyInfos) { andre@0: *pCertPolicyInfos = NULL; andre@0: goto cleanup; andre@0: } andre@0: andre@0: /* create a List of CertPolicyInfo Objects */ andre@0: PKIX_CHECK(PKIX_List_Create(&infos, plContext), andre@0: PKIX_LISTCREATEFAILED); andre@0: andre@0: /* andre@0: * Traverse the CERTCertificatePolicies structure, andre@0: * building each PKIX_PL_CertPolicyInfo object in turn andre@0: */ andre@0: while (*policyInfos != NULL) { andre@0: CERTPolicyInfo *policyInfo = *policyInfos; andre@0: CERTPolicyQualifier **policyQualifiers = andre@0: policyInfo->policyQualifiers; andre@0: if (policyQualifiers) { andre@0: /* create a PKIX_List of PKIX_PL_CertPolicyQualifiers */ andre@0: PKIX_CHECK(PKIX_List_Create(&qualifiers, plContext), andre@0: PKIX_LISTCREATEFAILED); andre@0: andre@0: while (*policyQualifiers != NULL) { andre@0: CERTPolicyQualifier *policyQualifier = andre@0: *policyQualifiers; andre@0: andre@0: /* create the qualifier's OID object */ andre@0: PKIX_CHECK(PKIX_PL_OID_CreateBySECItem andre@0: (&policyQualifier->qualifierID, andre@0: &pkixOID, plContext), andre@0: PKIX_OIDCREATEFAILED); andre@0: andre@0: /* create qualifier's ByteArray object */ andre@0: andre@0: PKIX_CHECK(PKIX_PL_ByteArray_Create andre@0: (policyQualifier->qualifierValue.data, andre@0: policyQualifier->qualifierValue.len, andre@0: &qualifierArray, andre@0: plContext), andre@0: PKIX_BYTEARRAYCREATEFAILED); andre@0: andre@0: /* create a CertPolicyQualifier object */ andre@0: andre@0: PKIX_CHECK(pkix_pl_CertPolicyQualifier_Create andre@0: (pkixOID, andre@0: qualifierArray, andre@0: &certPolicyQualifier, andre@0: plContext), andre@0: PKIX_CERTPOLICYQUALIFIERCREATEFAILED); andre@0: andre@0: PKIX_CHECK(PKIX_List_AppendItem andre@0: (qualifiers, andre@0: (PKIX_PL_Object *)certPolicyQualifier, andre@0: plContext), andre@0: PKIX_LISTAPPENDITEMFAILED); andre@0: andre@0: PKIX_DECREF(pkixOID); andre@0: PKIX_DECREF(qualifierArray); andre@0: PKIX_DECREF(certPolicyQualifier); andre@0: andre@0: policyQualifiers++; andre@0: } andre@0: andre@0: PKIX_CHECK(PKIX_List_SetImmutable andre@0: (qualifiers, plContext), andre@0: PKIX_LISTSETIMMUTABLEFAILED); andre@0: } andre@0: andre@0: andre@0: /* andre@0: * Create an OID object pkixOID from policyInfo->policyID. andre@0: * (The CERTPolicyInfo structure has an oid field, but it andre@0: * is of type SECOidTag. This function wants a SECItem.) andre@0: */ andre@0: PKIX_CHECK(PKIX_PL_OID_CreateBySECItem andre@0: (&policyInfo->policyID, &pkixOID, plContext), andre@0: PKIX_OIDCREATEFAILED); andre@0: andre@0: /* Create a CertPolicyInfo object */ andre@0: PKIX_CHECK(pkix_pl_CertPolicyInfo_Create andre@0: (pkixOID, qualifiers, &certPolicyInfo, plContext), andre@0: PKIX_CERTPOLICYINFOCREATEFAILED); andre@0: andre@0: /* Append the new CertPolicyInfo object to the list */ andre@0: PKIX_CHECK(PKIX_List_AppendItem andre@0: (infos, (PKIX_PL_Object *)certPolicyInfo, plContext), andre@0: PKIX_LISTAPPENDITEMFAILED); andre@0: andre@0: PKIX_DECREF(pkixOID); andre@0: PKIX_DECREF(qualifiers); andre@0: PKIX_DECREF(certPolicyInfo); andre@0: andre@0: policyInfos++; andre@0: } andre@0: andre@0: /* andre@0: * If there were no policies, we went straight to andre@0: * cleanup, so we don't have to NULLCHECK infos. andre@0: */ andre@0: PKIX_CHECK(PKIX_List_SetImmutable(infos, plContext), andre@0: PKIX_LISTSETIMMUTABLEFAILED); andre@0: andre@0: *pCertPolicyInfos = infos; andre@0: infos = NULL; andre@0: andre@0: cleanup: andre@0: if (certPol) { andre@0: PKIX_CERT_DEBUG andre@0: ("\t\tCalling CERT_DestroyCertificatePoliciesExtension).\n"); andre@0: CERT_DestroyCertificatePoliciesExtension(certPol); andre@0: } andre@0: andre@0: PKIX_DECREF(infos); andre@0: PKIX_DECREF(pkixOID); andre@0: PKIX_DECREF(qualifiers); andre@0: PKIX_DECREF(certPolicyInfo); andre@0: PKIX_DECREF(certPolicyQualifier); andre@0: PKIX_DECREF(qualifierArray); andre@0: andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_pl_Cert_DecodePolicyMapping andre@0: * DESCRIPTION: andre@0: * andre@0: * Decodes the contents of the PolicyMapping extension of the CERTCertificate andre@0: * pointed to by "nssCert", storing the resulting List of CertPolicyMaps at andre@0: * the address pointed to by "pCertPolicyMaps". If this certificate does not andre@0: * have a PolicyMapping extension, NULL will be stored. If a List is returned, andre@0: * it will be immutable. andre@0: * andre@0: * PARAMETERS andre@0: * "nssCert" andre@0: * Address of the Cert data whose extension is to be examined. Must be andre@0: * non-NULL. andre@0: * "pCertPolicyMaps" andre@0: * Address where the List of CertPolicyMaps will be stored. Must be andre@0: * non-NULL. andre@0: * "plContext" andre@0: * Platform-specific context pointer. andre@0: * THREAD SAFETY: andre@0: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) andre@0: * RETURNS: andre@0: * Returns NULL if the function succeeds. andre@0: * Returns a Cert Error if the function fails in a non-fatal way. andre@0: * Returns a Fatal Error if the function fails in an unrecoverable way. andre@0: */ andre@0: static PKIX_Error * andre@0: pkix_pl_Cert_DecodePolicyMapping( andre@0: CERTCertificate *nssCert, andre@0: PKIX_List **pCertPolicyMaps, andre@0: void *plContext) andre@0: { andre@0: SECStatus rv; andre@0: SECItem encodedCertPolicyMaps; andre@0: andre@0: /* Allocated in the arena; freed in CERT_Destroy... */ andre@0: CERTCertificatePolicyMappings *certPolMaps = NULL; andre@0: CERTPolicyMap **policyMaps = NULL; andre@0: andre@0: /* Holder for the return value */ andre@0: PKIX_List *maps = NULL; andre@0: andre@0: PKIX_PL_OID *issuerDomainOID = NULL; andre@0: PKIX_PL_OID *subjectDomainOID = NULL; andre@0: PKIX_PL_CertPolicyMap *certPolicyMap = NULL; andre@0: andre@0: PKIX_ENTER(CERT, "pkix_pl_Cert_DecodePolicyMapping"); andre@0: PKIX_NULLCHECK_TWO(nssCert, pCertPolicyMaps); andre@0: andre@0: /* get PolicyMappings as a SECItem */ andre@0: PKIX_CERT_DEBUG("\t\tCERT_FindCertExtension).\n"); andre@0: rv = CERT_FindCertExtension andre@0: (nssCert, SEC_OID_X509_POLICY_MAPPINGS, &encodedCertPolicyMaps); andre@0: if (SECSuccess != rv) { andre@0: *pCertPolicyMaps = NULL; andre@0: goto cleanup; andre@0: } andre@0: andre@0: /* translate PolicyMaps to CERTCertificatePolicyMappings */ andre@0: certPolMaps = CERT_DecodePolicyMappingsExtension andre@0: (&encodedCertPolicyMaps); andre@0: andre@0: PORT_Free(encodedCertPolicyMaps.data); andre@0: andre@0: if (!certPolMaps) { andre@0: PKIX_ERROR(PKIX_CERTDECODEPOLICYMAPPINGSEXTENSIONFAILED); andre@0: } andre@0: andre@0: PKIX_NULLCHECK_ONE(certPolMaps->policyMaps); andre@0: andre@0: policyMaps = certPolMaps->policyMaps; andre@0: andre@0: /* create a List of CertPolicyMap Objects */ andre@0: PKIX_CHECK(PKIX_List_Create(&maps, plContext), andre@0: PKIX_LISTCREATEFAILED); andre@0: andre@0: /* andre@0: * Traverse the CERTCertificatePolicyMappings structure, andre@0: * building each CertPolicyMap object in turn andre@0: */ andre@0: do { andre@0: CERTPolicyMap *policyMap = *policyMaps; andre@0: andre@0: /* create the OID for the issuer Domain Policy */ andre@0: PKIX_CHECK(PKIX_PL_OID_CreateBySECItem andre@0: (&policyMap->issuerDomainPolicy, andre@0: &issuerDomainOID, plContext), andre@0: PKIX_OIDCREATEFAILED); andre@0: andre@0: /* create the OID for the subject Domain Policy */ andre@0: PKIX_CHECK(PKIX_PL_OID_CreateBySECItem andre@0: (&policyMap->subjectDomainPolicy, andre@0: &subjectDomainOID, plContext), andre@0: PKIX_OIDCREATEFAILED); andre@0: andre@0: /* create the CertPolicyMap */ andre@0: andre@0: PKIX_CHECK(pkix_pl_CertPolicyMap_Create andre@0: (issuerDomainOID, andre@0: subjectDomainOID, andre@0: &certPolicyMap, andre@0: plContext), andre@0: PKIX_CERTPOLICYMAPCREATEFAILED); andre@0: andre@0: PKIX_CHECK(PKIX_List_AppendItem andre@0: (maps, (PKIX_PL_Object *)certPolicyMap, plContext), andre@0: PKIX_LISTAPPENDITEMFAILED); andre@0: andre@0: PKIX_DECREF(issuerDomainOID); andre@0: PKIX_DECREF(subjectDomainOID); andre@0: PKIX_DECREF(certPolicyMap); andre@0: andre@0: policyMaps++; andre@0: } while (*policyMaps != NULL); andre@0: andre@0: PKIX_CHECK(PKIX_List_SetImmutable(maps, plContext), andre@0: PKIX_LISTSETIMMUTABLEFAILED); andre@0: andre@0: *pCertPolicyMaps = maps; andre@0: maps = NULL; andre@0: andre@0: cleanup: andre@0: if (certPolMaps) { andre@0: PKIX_CERT_DEBUG andre@0: ("\t\tCalling CERT_DestroyPolicyMappingsExtension).\n"); andre@0: CERT_DestroyPolicyMappingsExtension(certPolMaps); andre@0: } andre@0: andre@0: PKIX_DECREF(maps); andre@0: PKIX_DECREF(issuerDomainOID); andre@0: PKIX_DECREF(subjectDomainOID); andre@0: PKIX_DECREF(certPolicyMap); andre@0: andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_pl_Cert_DecodePolicyConstraints andre@0: * DESCRIPTION: andre@0: * andre@0: * Decodes the contents of the PolicyConstraints extension in the andre@0: * CERTCertificate pointed to by "nssCert", to obtain SkipCerts values andre@0: * which are stored at the addresses "pExplicitPolicySkipCerts" and andre@0: * "pInhibitMappingSkipCerts", respectively. If this certificate does andre@0: * not have an PolicyConstraints extension, or if either of the optional andre@0: * components is not supplied, this function stores a value of -1 for any andre@0: * missing component. andre@0: * andre@0: * PARAMETERS andre@0: * "nssCert" andre@0: * Address of the Cert data whose extension is to be examined. Must be andre@0: * non-NULL. andre@0: * "pExplicitPolicySkipCerts" andre@0: * Address where the SkipCert value for the requireExplicitPolicy andre@0: * component will be stored. Must be non-NULL. andre@0: * "pInhibitMappingSkipCerts" andre@0: * Address where the SkipCert value for the inhibitPolicyMapping andre@0: * component will be stored. Must be non-NULL. andre@0: * "plContext" andre@0: * Platform-specific context pointer. andre@0: * THREAD SAFETY: andre@0: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) andre@0: * RETURNS: andre@0: * Returns NULL if the function succeeds. andre@0: * Returns a Cert Error if the function fails in a non-fatal way. andre@0: * Returns a Fatal Error if the function fails in an unrecoverable way. andre@0: */ andre@0: static PKIX_Error * andre@0: pkix_pl_Cert_DecodePolicyConstraints( andre@0: CERTCertificate *nssCert, andre@0: PKIX_Int32 *pExplicitPolicySkipCerts, andre@0: PKIX_Int32 *pInhibitMappingSkipCerts, andre@0: void *plContext) andre@0: { andre@0: CERTCertificatePolicyConstraints policyConstraints; andre@0: SECStatus rv; andre@0: SECItem encodedCertPolicyConstraints; andre@0: PKIX_Int32 explicitPolicySkipCerts = -1; andre@0: PKIX_Int32 inhibitMappingSkipCerts = -1; andre@0: andre@0: PKIX_ENTER(CERT, "pkix_pl_Cert_DecodePolicyConstraints"); andre@0: PKIX_NULLCHECK_THREE andre@0: (nssCert, pExplicitPolicySkipCerts, pInhibitMappingSkipCerts); andre@0: andre@0: /* get the two skipCert values as SECItems */ andre@0: PKIX_CERT_DEBUG("\t\tCalling CERT_FindCertExtension).\n"); andre@0: rv = CERT_FindCertExtension andre@0: (nssCert, andre@0: SEC_OID_X509_POLICY_CONSTRAINTS, andre@0: &encodedCertPolicyConstraints); andre@0: andre@0: if (rv == SECSuccess) { andre@0: andre@0: policyConstraints.explicitPolicySkipCerts.data = andre@0: (unsigned char *)&explicitPolicySkipCerts; andre@0: policyConstraints.inhibitMappingSkipCerts.data = andre@0: (unsigned char *)&inhibitMappingSkipCerts; andre@0: andre@0: /* translate DER to CERTCertificatePolicyConstraints */ andre@0: rv = CERT_DecodePolicyConstraintsExtension andre@0: (&policyConstraints, &encodedCertPolicyConstraints); andre@0: andre@0: PORT_Free(encodedCertPolicyConstraints.data); andre@0: andre@0: if (rv != SECSuccess) { andre@0: PKIX_ERROR andre@0: (PKIX_CERTDECODEPOLICYCONSTRAINTSEXTENSIONFAILED); andre@0: } andre@0: } andre@0: andre@0: *pExplicitPolicySkipCerts = explicitPolicySkipCerts; andre@0: *pInhibitMappingSkipCerts = inhibitMappingSkipCerts; andre@0: andre@0: cleanup: andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_pl_Cert_DecodeInhibitAnyPolicy andre@0: * DESCRIPTION: andre@0: * andre@0: * Decodes the contents of the InhibitAnyPolicy extension in the andre@0: * CERTCertificate pointed to by "nssCert", to obtain a SkipCerts value, andre@0: * which is stored at the address "pSkipCerts". If this certificate does andre@0: * not have an InhibitAnyPolicy extension, -1 will be stored. andre@0: * andre@0: * PARAMETERS andre@0: * "nssCert" andre@0: * Address of the Cert data whose InhibitAnyPolicy extension is to be andre@0: * processed. Must be non-NULL. andre@0: * "pSkipCerts" andre@0: * Address where the SkipCert value from the InhibitAnyPolicy extension andre@0: * will be stored. Must be non-NULL. andre@0: * "plContext" andre@0: * Platform-specific context pointer. andre@0: * THREAD SAFETY: andre@0: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) andre@0: * RETURNS: andre@0: * Returns NULL if the function succeeds. andre@0: * Returns a Cert Error if the function fails in a non-fatal way. andre@0: * Returns a Fatal Error if the function fails in an unrecoverable way. andre@0: */ andre@0: PKIX_Error * andre@0: pkix_pl_Cert_DecodeInhibitAnyPolicy( andre@0: CERTCertificate *nssCert, andre@0: PKIX_Int32 *pSkipCerts, andre@0: void *plContext) andre@0: { andre@0: CERTCertificateInhibitAny inhibitAny; andre@0: SECStatus rv; andre@0: SECItem encodedCertInhibitAny; andre@0: PKIX_Int32 skipCerts = -1; andre@0: andre@0: PKIX_ENTER(CERT, "pkix_pl_Cert_DecodeInhibitAnyPolicy"); andre@0: PKIX_NULLCHECK_TWO(nssCert, pSkipCerts); andre@0: andre@0: /* get InhibitAny as a SECItem */ andre@0: PKIX_CERT_DEBUG("\t\tCalling CERT_FindCertExtension).\n"); andre@0: rv = CERT_FindCertExtension andre@0: (nssCert, SEC_OID_X509_INHIBIT_ANY_POLICY, &encodedCertInhibitAny); andre@0: andre@0: if (rv == SECSuccess) { andre@0: inhibitAny.inhibitAnySkipCerts.data = andre@0: (unsigned char *)&skipCerts; andre@0: andre@0: /* translate DER to CERTCertificateInhibitAny */ andre@0: rv = CERT_DecodeInhibitAnyExtension andre@0: (&inhibitAny, &encodedCertInhibitAny); andre@0: andre@0: PORT_Free(encodedCertInhibitAny.data); andre@0: andre@0: if (rv != SECSuccess) { andre@0: PKIX_ERROR(PKIX_CERTDECODEINHIBITANYEXTENSIONFAILED); andre@0: } andre@0: } andre@0: andre@0: *pSkipCerts = skipCerts; andre@0: andre@0: cleanup: andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_pl_Cert_GetNssSubjectAltNames andre@0: * DESCRIPTION: andre@0: * andre@0: * Retrieves the Subject Alternative Names of the certificate specified by andre@0: * "cert" and stores it at "pNssSubjAltNames". If the Subject Alternative andre@0: * Name extension is not present, NULL is returned at "pNssSubjAltNames". andre@0: * If the Subject Alternative Names has not been previously decoded, it is andre@0: * decoded here with lock on the "cert" unless the flag "hasLock" indicates andre@0: * the lock had been obtained at a higher call level. andre@0: * andre@0: * PARAMETERS andre@0: * "cert" andre@0: * Address of the certificate whose Subject Alternative Names extensions andre@0: * is retrieved. Must be non-NULL. andre@0: * "hasLock" andre@0: * Boolean indicates caller has acquired a lock. andre@0: * Must be non-NULL. andre@0: * "pNssSubjAltNames" andre@0: * Address where the returned Subject Alternative Names will be stored. andre@0: * Must be non-NULL. andre@0: * "plContext" andre@0: * Platform-specific context pointer. andre@0: * THREAD SAFETY: andre@0: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) andre@0: * RETURNS: andre@0: * Returns NULL if the function succeeds. andre@0: * Returns a Cert Error if the function fails in a non-fatal way. andre@0: * Returns a Fatal Error if the function fails in an unrecoverable way. andre@0: */ andre@0: static PKIX_Error * andre@0: pkix_pl_Cert_GetNssSubjectAltNames( andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_Boolean hasLock, andre@0: CERTGeneralName **pNssSubjAltNames, andre@0: void *plContext) andre@0: { andre@0: CERTCertificate *nssCert = NULL; andre@0: CERTGeneralName *nssOriginalAltName = NULL; andre@0: PLArenaPool *arena = NULL; andre@0: SECItem altNameExtension = {siBuffer, NULL, 0}; andre@0: SECStatus rv = SECFailure; andre@0: andre@0: PKIX_ENTER(CERT, "pkix_pl_Cert_GetNssSubjectAltNames"); andre@0: PKIX_NULLCHECK_THREE(cert, pNssSubjAltNames, cert->nssCert); andre@0: andre@0: nssCert = cert->nssCert; andre@0: andre@0: if ((cert->nssSubjAltNames == NULL) && (!cert->subjAltNamesAbsent)){ andre@0: andre@0: if (!hasLock) { andre@0: PKIX_OBJECT_LOCK(cert); andre@0: } andre@0: andre@0: if ((cert->nssSubjAltNames == NULL) && andre@0: (!cert->subjAltNamesAbsent)){ andre@0: andre@0: PKIX_PL_NSSCALLRV(CERT, rv, CERT_FindCertExtension, andre@0: (nssCert, andre@0: SEC_OID_X509_SUBJECT_ALT_NAME, andre@0: &altNameExtension)); andre@0: andre@0: if (rv != SECSuccess) { andre@0: *pNssSubjAltNames = NULL; andre@0: cert->subjAltNamesAbsent = PKIX_TRUE; andre@0: goto cleanup; andre@0: } andre@0: andre@0: if (cert->arenaNameConstraints == NULL) { andre@0: PKIX_PL_NSSCALLRV(CERT, arena, PORT_NewArena, andre@0: (DER_DEFAULT_CHUNKSIZE)); andre@0: andre@0: if (arena == NULL) { andre@0: PKIX_ERROR(PKIX_OUTOFMEMORY); andre@0: } andre@0: cert->arenaNameConstraints = arena; andre@0: } andre@0: andre@0: PKIX_PL_NSSCALLRV andre@0: (CERT, andre@0: nssOriginalAltName, andre@0: (CERTGeneralName *) CERT_DecodeAltNameExtension, andre@0: (cert->arenaNameConstraints, &altNameExtension)); andre@0: andre@0: PKIX_PL_NSSCALL(CERT, PORT_Free, (altNameExtension.data)); andre@0: andre@0: if (nssOriginalAltName == NULL) { andre@0: PKIX_ERROR(PKIX_CERTDECODEALTNAMEEXTENSIONFAILED); andre@0: } andre@0: cert->nssSubjAltNames = nssOriginalAltName; andre@0: andre@0: } andre@0: andre@0: if (!hasLock) { andre@0: PKIX_OBJECT_UNLOCK(cert); andre@0: } andre@0: } andre@0: andre@0: *pNssSubjAltNames = cert->nssSubjAltNames; andre@0: andre@0: cleanup: andre@0: PKIX_OBJECT_UNLOCK(lockedObject); andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_pl_Cert_CheckExtendKeyUsage andre@0: * DESCRIPTION: andre@0: * andre@0: * For each of the ON bit in "requiredExtendedKeyUsages" that represents its andre@0: * SECCertUsageEnum type, this function checks "cert"'s certType (extended andre@0: * key usage) and key usage with what is required for SECCertUsageEnum type. andre@0: * andre@0: * PARAMETERS andre@0: * "cert" andre@0: * Address of the certificate whose Extended Key Usage extensions andre@0: * is retrieved. Must be non-NULL. andre@0: * "requiredExtendedKeyUsages" andre@0: * An unsigned integer, its bit location is ON based on the required key andre@0: * usage value representing in SECCertUsageEnum. andre@0: * "pPass" andre@0: * Address where the return value, indicating key usage check passed, is andre@0: * stored. Must be non-NULL. andre@0: * "plContext" andre@0: * Platform-specific context pointer. andre@0: * THREAD SAFETY: andre@0: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) andre@0: * RETURNS: andre@0: * Returns NULL if the function succeeds. andre@0: * Returns a Cert Error if the function fails in a non-fatal way. andre@0: * Returns a Fatal Error if the function fails in an unrecoverable way. andre@0: */ andre@0: PKIX_Error * andre@0: pkix_pl_Cert_CheckExtendedKeyUsage( andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_UInt32 requiredExtendedKeyUsages, andre@0: PKIX_Boolean *pPass, andre@0: void *plContext) andre@0: { andre@0: PKIX_PL_CertBasicConstraints *basicConstraints = NULL; andre@0: PKIX_UInt32 certType = 0; andre@0: PKIX_UInt32 requiredKeyUsage = 0; andre@0: PKIX_UInt32 requiredCertType = 0; andre@0: PKIX_UInt32 requiredExtendedKeyUsage = 0; andre@0: PKIX_UInt32 i; andre@0: PKIX_Boolean isCA = PKIX_FALSE; andre@0: SECStatus rv = SECFailure; andre@0: andre@0: PKIX_ENTER(CERT, "pkix_pl_Cert_CheckExtendKeyUsage"); andre@0: PKIX_NULLCHECK_THREE(cert, pPass, cert->nssCert); andre@0: andre@0: *pPass = PKIX_FALSE; andre@0: andre@0: PKIX_CERT_DEBUG("\t\tCalling cert_GetCertType).\n"); andre@0: cert_GetCertType(cert->nssCert); andre@0: certType = cert->nssCert->nsCertType; andre@0: andre@0: PKIX_CHECK(PKIX_PL_Cert_GetBasicConstraints andre@0: (cert, andre@0: &basicConstraints, andre@0: plContext), andre@0: PKIX_CERTGETBASICCONSTRAINTFAILED); andre@0: andre@0: if (basicConstraints != NULL) { andre@0: PKIX_CHECK(PKIX_PL_BasicConstraints_GetCAFlag andre@0: (basicConstraints, &isCA, plContext), andre@0: PKIX_BASICCONSTRAINTSGETCAFLAGFAILED); andre@0: } andre@0: andre@0: i = 0; andre@0: while (requiredExtendedKeyUsages != 0) { andre@0: andre@0: /* Find the bit location of the right-most non-zero bit */ andre@0: while (requiredExtendedKeyUsages != 0) { andre@0: if (((1 << i) & requiredExtendedKeyUsages) != 0) { andre@0: requiredExtendedKeyUsage = 1 << i; andre@0: break; andre@0: } andre@0: i++; andre@0: } andre@0: requiredExtendedKeyUsages ^= requiredExtendedKeyUsage; andre@0: andre@0: requiredExtendedKeyUsage = i; andre@0: andre@0: PKIX_PL_NSSCALLRV(CERT, rv, CERT_KeyUsageAndTypeForCertUsage, andre@0: (requiredExtendedKeyUsage, andre@0: isCA, andre@0: &requiredKeyUsage, andre@0: &requiredCertType)); andre@0: andre@0: if (!(certType & requiredCertType)) { andre@0: goto cleanup; andre@0: } andre@0: andre@0: PKIX_PL_NSSCALLRV(CERT, rv, CERT_CheckKeyUsage, andre@0: (cert->nssCert, requiredKeyUsage)); andre@0: if (rv != SECSuccess) { andre@0: goto cleanup; andre@0: } andre@0: i++; andre@0: andre@0: } andre@0: andre@0: *pPass = PKIX_TRUE; andre@0: andre@0: cleanup: andre@0: PKIX_DECREF(basicConstraints); andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_pl_Cert_ToString_Helper andre@0: * DESCRIPTION: andre@0: * andre@0: * Helper function that creates a string representation of the Cert pointed andre@0: * to by "cert" and stores it at "pString", where the value of andre@0: * "partialString" determines whether a full or partial representation of andre@0: * the Cert is stored. andre@0: * andre@0: * PARAMETERS andre@0: * "cert" andre@0: * Address of Cert whose string representation is desired. andre@0: * Must be non-NULL. andre@0: * "partialString" andre@0: * Boolean indicating whether a partial Cert representation is desired. andre@0: * "pString" andre@0: * Address where object pointer will be stored. Must be non-NULL. andre@0: * "plContext" andre@0: * Platform-specific context pointer. andre@0: * THREAD SAFETY: andre@0: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) andre@0: * RETURNS: andre@0: * Returns NULL if the function succeeds. andre@0: * Returns a Cert Error if the function fails in a non-fatal way. andre@0: * Returns a Fatal Error if the function fails in an unrecoverable way. andre@0: */ andre@0: PKIX_Error * andre@0: pkix_pl_Cert_ToString_Helper( andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_Boolean partialString, andre@0: PKIX_PL_String **pString, andre@0: void *plContext) andre@0: { andre@0: PKIX_PL_String *certString = NULL; andre@0: char *asciiFormat = NULL; andre@0: PKIX_PL_String *formatString = NULL; andre@0: PKIX_UInt32 certVersion; andre@0: PKIX_PL_BigInt *certSN = NULL; andre@0: PKIX_PL_String *certSNString = NULL; andre@0: PKIX_PL_X500Name *certIssuer = NULL; andre@0: PKIX_PL_String *certIssuerString = NULL; andre@0: PKIX_PL_X500Name *certSubject = NULL; andre@0: PKIX_PL_String *certSubjectString = NULL; andre@0: PKIX_PL_String *notBeforeString = NULL; andre@0: PKIX_PL_String *notAfterString = NULL; andre@0: PKIX_List *subjAltNames = NULL; andre@0: PKIX_PL_String *subjAltNamesString = NULL; andre@0: PKIX_PL_ByteArray *authKeyId = NULL; andre@0: PKIX_PL_String *authKeyIdString = NULL; andre@0: PKIX_PL_ByteArray *subjKeyId = NULL; andre@0: PKIX_PL_String *subjKeyIdString = NULL; andre@0: PKIX_PL_PublicKey *nssPubKey = NULL; andre@0: PKIX_PL_String *nssPubKeyString = NULL; andre@0: PKIX_List *critExtOIDs = NULL; andre@0: PKIX_PL_String *critExtOIDsString = NULL; andre@0: PKIX_List *extKeyUsages = NULL; andre@0: PKIX_PL_String *extKeyUsagesString = NULL; andre@0: PKIX_PL_CertBasicConstraints *basicConstraint = NULL; andre@0: PKIX_PL_String *certBasicConstraintsString = NULL; andre@0: PKIX_List *policyInfo = NULL; andre@0: PKIX_PL_String *certPolicyInfoString = NULL; andre@0: PKIX_List *certPolicyMappings = NULL; andre@0: PKIX_PL_String *certPolicyMappingsString = NULL; andre@0: PKIX_Int32 certExplicitPolicy = 0; andre@0: PKIX_Int32 certInhibitMapping = 0; andre@0: PKIX_Int32 certInhibitAnyPolicy = 0; andre@0: PKIX_PL_CertNameConstraints *nameConstraints = NULL; andre@0: PKIX_PL_String *nameConstraintsString = NULL; andre@0: PKIX_List *authorityInfoAccess = NULL; andre@0: PKIX_PL_String *authorityInfoAccessString = NULL; andre@0: PKIX_List *subjectInfoAccess = NULL; andre@0: PKIX_PL_String *subjectInfoAccessString = NULL; andre@0: andre@0: PKIX_ENTER(CERT, "pkix_pl_Cert_ToString_Helper"); andre@0: PKIX_NULLCHECK_THREE(cert, cert->nssCert, pString); andre@0: andre@0: /* andre@0: * XXX Add to this format as certificate components are developed. andre@0: */ andre@0: andre@0: if (partialString){ andre@0: asciiFormat = andre@0: "\t[Issuer: %s\n" andre@0: "\t Subject: %s]"; andre@0: } else { andre@0: asciiFormat = andre@0: "[\n" andre@0: "\tVersion: v%d\n" andre@0: "\tSerialNumber: %s\n" andre@0: "\tIssuer: %s\n" andre@0: "\tSubject: %s\n" andre@0: "\tValidity: [From: %s\n" andre@0: "\t To: %s]\n" andre@0: "\tSubjectAltNames: %s\n" andre@0: "\tAuthorityKeyId: %s\n" andre@0: "\tSubjectKeyId: %s\n" andre@0: "\tSubjPubKeyAlgId: %s\n" andre@0: "\tCritExtOIDs: %s\n" andre@0: "\tExtKeyUsages: %s\n" andre@0: "\tBasicConstraint: %s\n" andre@0: "\tCertPolicyInfo: %s\n" andre@0: "\tPolicyMappings: %s\n" andre@0: "\tExplicitPolicy: %d\n" andre@0: "\tInhibitMapping: %d\n" andre@0: "\tInhibitAnyPolicy:%d\n" andre@0: "\tNameConstraints: %s\n" andre@0: "\tAuthorityInfoAccess: %s\n" andre@0: "\tSubjectInfoAccess: %s\n" andre@0: "\tCacheFlag: %d\n" andre@0: "]\n"; andre@0: } andre@0: andre@0: andre@0: andre@0: PKIX_CHECK(PKIX_PL_String_Create andre@0: (PKIX_ESCASCII, asciiFormat, 0, &formatString, plContext), andre@0: PKIX_STRINGCREATEFAILED); andre@0: andre@0: /* Issuer */ andre@0: PKIX_CHECK(PKIX_PL_Cert_GetIssuer andre@0: (cert, &certIssuer, plContext), andre@0: PKIX_CERTGETISSUERFAILED); andre@0: andre@0: PKIX_CHECK(PKIX_PL_Object_ToString andre@0: ((PKIX_PL_Object *)certIssuer, &certIssuerString, plContext), andre@0: PKIX_X500NAMETOSTRINGFAILED); andre@0: andre@0: /* Subject */ andre@0: PKIX_CHECK(PKIX_PL_Cert_GetSubject(cert, &certSubject, plContext), andre@0: PKIX_CERTGETSUBJECTFAILED); andre@0: andre@0: PKIX_TOSTRING(certSubject, &certSubjectString, plContext, andre@0: PKIX_X500NAMETOSTRINGFAILED); andre@0: andre@0: if (partialString){ andre@0: PKIX_CHECK(PKIX_PL_Sprintf andre@0: (&certString, andre@0: plContext, andre@0: formatString, andre@0: certIssuerString, andre@0: certSubjectString), andre@0: PKIX_SPRINTFFAILED); andre@0: andre@0: *pString = certString; andre@0: goto cleanup; andre@0: } andre@0: andre@0: /* Version */ andre@0: PKIX_CHECK(PKIX_PL_Cert_GetVersion(cert, &certVersion, plContext), andre@0: PKIX_CERTGETVERSIONFAILED); andre@0: andre@0: /* SerialNumber */ andre@0: PKIX_CHECK(PKIX_PL_Cert_GetSerialNumber(cert, &certSN, plContext), andre@0: PKIX_CERTGETSERIALNUMBERFAILED); andre@0: andre@0: PKIX_CHECK(PKIX_PL_Object_ToString andre@0: ((PKIX_PL_Object *)certSN, &certSNString, plContext), andre@0: PKIX_BIGINTTOSTRINGFAILED); andre@0: andre@0: /* Validity: NotBefore */ andre@0: PKIX_CHECK(pkix_pl_Date_ToString_Helper andre@0: (&(cert->nssCert->validity.notBefore), andre@0: ¬BeforeString, andre@0: plContext), andre@0: PKIX_DATETOSTRINGHELPERFAILED); andre@0: andre@0: /* Validity: NotAfter */ andre@0: PKIX_CHECK(pkix_pl_Date_ToString_Helper andre@0: (&(cert->nssCert->validity.notAfter), andre@0: ¬AfterString, andre@0: plContext), andre@0: PKIX_DATETOSTRINGHELPERFAILED); andre@0: andre@0: /* SubjectAltNames */ andre@0: PKIX_CHECK(PKIX_PL_Cert_GetSubjectAltNames andre@0: (cert, &subjAltNames, plContext), andre@0: PKIX_CERTGETSUBJECTALTNAMESFAILED); andre@0: andre@0: PKIX_TOSTRING(subjAltNames, &subjAltNamesString, plContext, andre@0: PKIX_LISTTOSTRINGFAILED); andre@0: andre@0: /* AuthorityKeyIdentifier */ andre@0: PKIX_CHECK(PKIX_PL_Cert_GetAuthorityKeyIdentifier andre@0: (cert, &authKeyId, plContext), andre@0: PKIX_CERTGETAUTHORITYKEYIDENTIFIERFAILED); andre@0: andre@0: PKIX_TOSTRING(authKeyId, &authKeyIdString, plContext, andre@0: PKIX_BYTEARRAYTOSTRINGFAILED); andre@0: andre@0: /* SubjectKeyIdentifier */ andre@0: PKIX_CHECK(PKIX_PL_Cert_GetSubjectKeyIdentifier andre@0: (cert, &subjKeyId, plContext), andre@0: PKIX_CERTGETSUBJECTKEYIDENTIFIERFAILED); andre@0: andre@0: PKIX_TOSTRING(subjKeyId, &subjKeyIdString, plContext, andre@0: PKIX_BYTEARRAYTOSTRINGFAILED); andre@0: andre@0: /* SubjectPublicKey */ andre@0: PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey andre@0: (cert, &nssPubKey, plContext), andre@0: PKIX_CERTGETSUBJECTPUBLICKEYFAILED); andre@0: andre@0: PKIX_CHECK(PKIX_PL_Object_ToString andre@0: ((PKIX_PL_Object *)nssPubKey, &nssPubKeyString, plContext), andre@0: PKIX_PUBLICKEYTOSTRINGFAILED); andre@0: andre@0: /* CriticalExtensionOIDs */ andre@0: PKIX_CHECK(PKIX_PL_Cert_GetCriticalExtensionOIDs andre@0: (cert, &critExtOIDs, plContext), andre@0: PKIX_CERTGETCRITICALEXTENSIONOIDSFAILED); andre@0: andre@0: PKIX_TOSTRING(critExtOIDs, &critExtOIDsString, plContext, andre@0: PKIX_LISTTOSTRINGFAILED); andre@0: andre@0: /* ExtendedKeyUsages */ andre@0: PKIX_CHECK(PKIX_PL_Cert_GetExtendedKeyUsage andre@0: (cert, &extKeyUsages, plContext), andre@0: PKIX_CERTGETEXTENDEDKEYUSAGEFAILED); andre@0: andre@0: PKIX_TOSTRING(extKeyUsages, &extKeyUsagesString, plContext, andre@0: PKIX_LISTTOSTRINGFAILED); andre@0: andre@0: /* CertBasicConstraints */ andre@0: PKIX_CHECK(PKIX_PL_Cert_GetBasicConstraints andre@0: (cert, &basicConstraint, plContext), andre@0: PKIX_CERTGETBASICCONSTRAINTSFAILED); andre@0: andre@0: PKIX_TOSTRING(basicConstraint, &certBasicConstraintsString, plContext, andre@0: PKIX_CERTBASICCONSTRAINTSTOSTRINGFAILED); andre@0: andre@0: /* CertPolicyInfo */ andre@0: PKIX_CHECK(PKIX_PL_Cert_GetPolicyInformation andre@0: (cert, &policyInfo, plContext), andre@0: PKIX_CERTGETPOLICYINFORMATIONFAILED); andre@0: andre@0: PKIX_TOSTRING(policyInfo, &certPolicyInfoString, plContext, andre@0: PKIX_LISTTOSTRINGFAILED); andre@0: andre@0: /* Advanced Policies */ andre@0: PKIX_CHECK(PKIX_PL_Cert_GetPolicyMappings andre@0: (cert, &certPolicyMappings, plContext), andre@0: PKIX_CERTGETPOLICYMAPPINGSFAILED); andre@0: andre@0: PKIX_TOSTRING(certPolicyMappings, &certPolicyMappingsString, plContext, andre@0: PKIX_LISTTOSTRINGFAILED); andre@0: andre@0: PKIX_CHECK(PKIX_PL_Cert_GetRequireExplicitPolicy andre@0: (cert, &certExplicitPolicy, plContext), andre@0: PKIX_CERTGETREQUIREEXPLICITPOLICYFAILED); andre@0: andre@0: PKIX_CHECK(PKIX_PL_Cert_GetPolicyMappingInhibited andre@0: (cert, &certInhibitMapping, plContext), andre@0: PKIX_CERTGETPOLICYMAPPINGINHIBITEDFAILED); andre@0: andre@0: PKIX_CHECK(PKIX_PL_Cert_GetInhibitAnyPolicy andre@0: (cert, &certInhibitAnyPolicy, plContext), andre@0: PKIX_CERTGETINHIBITANYPOLICYFAILED); andre@0: andre@0: /* Name Constraints */ andre@0: PKIX_CHECK(PKIX_PL_Cert_GetNameConstraints andre@0: (cert, &nameConstraints, plContext), andre@0: PKIX_CERTGETNAMECONSTRAINTSFAILED); andre@0: andre@0: PKIX_TOSTRING(nameConstraints, &nameConstraintsString, plContext, andre@0: PKIX_LISTTOSTRINGFAILED); andre@0: andre@0: /* Authority Information Access */ andre@0: PKIX_CHECK(PKIX_PL_Cert_GetAuthorityInfoAccess andre@0: (cert, &authorityInfoAccess, plContext), andre@0: PKIX_CERTGETAUTHORITYINFOACCESSFAILED); andre@0: andre@0: PKIX_TOSTRING(authorityInfoAccess, &authorityInfoAccessString, plContext, andre@0: PKIX_LISTTOSTRINGFAILED); andre@0: andre@0: /* Subject Information Access */ andre@0: PKIX_CHECK(PKIX_PL_Cert_GetSubjectInfoAccess andre@0: (cert, &subjectInfoAccess, plContext), andre@0: PKIX_CERTGETSUBJECTINFOACCESSFAILED); andre@0: andre@0: PKIX_TOSTRING(subjectInfoAccess, &subjectInfoAccessString, plContext, andre@0: PKIX_LISTTOSTRINGFAILED); andre@0: andre@0: PKIX_CHECK(PKIX_PL_Sprintf andre@0: (&certString, andre@0: plContext, andre@0: formatString, andre@0: certVersion + 1, andre@0: certSNString, andre@0: certIssuerString, andre@0: certSubjectString, andre@0: notBeforeString, andre@0: notAfterString, andre@0: subjAltNamesString, andre@0: authKeyIdString, andre@0: subjKeyIdString, andre@0: nssPubKeyString, andre@0: critExtOIDsString, andre@0: extKeyUsagesString, andre@0: certBasicConstraintsString, andre@0: certPolicyInfoString, andre@0: certPolicyMappingsString, andre@0: certExplicitPolicy, /* an Int32, not a String */ andre@0: certInhibitMapping, /* an Int32, not a String */ andre@0: certInhibitAnyPolicy, /* an Int32, not a String */ andre@0: nameConstraintsString, andre@0: authorityInfoAccessString, andre@0: subjectInfoAccessString, andre@0: cert->cacheFlag), /* a boolean */ andre@0: PKIX_SPRINTFFAILED); andre@0: andre@0: *pString = certString; andre@0: andre@0: cleanup: andre@0: PKIX_DECREF(certSN); andre@0: PKIX_DECREF(certSNString); andre@0: PKIX_DECREF(certIssuer); andre@0: PKIX_DECREF(certIssuerString); andre@0: PKIX_DECREF(certSubject); andre@0: PKIX_DECREF(certSubjectString); andre@0: PKIX_DECREF(notBeforeString); andre@0: PKIX_DECREF(notAfterString); andre@0: PKIX_DECREF(subjAltNames); andre@0: PKIX_DECREF(subjAltNamesString); andre@0: PKIX_DECREF(authKeyId); andre@0: PKIX_DECREF(authKeyIdString); andre@0: PKIX_DECREF(subjKeyId); andre@0: PKIX_DECREF(subjKeyIdString); andre@0: PKIX_DECREF(nssPubKey); andre@0: PKIX_DECREF(nssPubKeyString); andre@0: PKIX_DECREF(critExtOIDs); andre@0: PKIX_DECREF(critExtOIDsString); andre@0: PKIX_DECREF(extKeyUsages); andre@0: PKIX_DECREF(extKeyUsagesString); andre@0: PKIX_DECREF(basicConstraint); andre@0: PKIX_DECREF(certBasicConstraintsString); andre@0: PKIX_DECREF(policyInfo); andre@0: PKIX_DECREF(certPolicyInfoString); andre@0: PKIX_DECREF(certPolicyMappings); andre@0: PKIX_DECREF(certPolicyMappingsString); andre@0: PKIX_DECREF(nameConstraints); andre@0: PKIX_DECREF(nameConstraintsString); andre@0: PKIX_DECREF(authorityInfoAccess); andre@0: PKIX_DECREF(authorityInfoAccessString); andre@0: PKIX_DECREF(subjectInfoAccess); andre@0: PKIX_DECREF(subjectInfoAccessString); andre@0: PKIX_DECREF(formatString); andre@0: andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_pl_Cert_Destroy andre@0: * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) andre@0: */ andre@0: static PKIX_Error * andre@0: pkix_pl_Cert_Destroy( andre@0: PKIX_PL_Object *object, andre@0: void *plContext) andre@0: { andre@0: PKIX_PL_Cert *cert = NULL; andre@0: andre@0: PKIX_ENTER(CERT, "pkix_pl_Cert_Destroy"); andre@0: PKIX_NULLCHECK_ONE(object); andre@0: andre@0: PKIX_CHECK(pkix_CheckType(object, PKIX_CERT_TYPE, plContext), andre@0: PKIX_OBJECTNOTCERT); andre@0: andre@0: cert = (PKIX_PL_Cert*)object; andre@0: andre@0: PKIX_DECREF(cert->subject); andre@0: PKIX_DECREF(cert->issuer); andre@0: PKIX_DECREF(cert->subjAltNames); andre@0: PKIX_DECREF(cert->publicKeyAlgId); andre@0: PKIX_DECREF(cert->publicKey); andre@0: PKIX_DECREF(cert->serialNumber); andre@0: PKIX_DECREF(cert->critExtOids); andre@0: PKIX_DECREF(cert->authKeyId); andre@0: PKIX_DECREF(cert->subjKeyId); andre@0: PKIX_DECREF(cert->extKeyUsages); andre@0: PKIX_DECREF(cert->certBasicConstraints); andre@0: PKIX_DECREF(cert->certPolicyInfos); andre@0: PKIX_DECREF(cert->certPolicyMappings); andre@0: PKIX_DECREF(cert->nameConstraints); andre@0: PKIX_DECREF(cert->store); andre@0: PKIX_DECREF(cert->authorityInfoAccess); andre@0: PKIX_DECREF(cert->subjectInfoAccess); andre@0: PKIX_DECREF(cert->crldpList); andre@0: andre@0: if (cert->arenaNameConstraints){ andre@0: /* This arena was allocated for SubjectAltNames */ andre@0: PKIX_PL_NSSCALL(CERT, PORT_FreeArena, andre@0: (cert->arenaNameConstraints, PR_FALSE)); andre@0: andre@0: cert->arenaNameConstraints = NULL; andre@0: cert->nssSubjAltNames = NULL; andre@0: } andre@0: andre@0: CERT_DestroyCertificate(cert->nssCert); andre@0: cert->nssCert = NULL; andre@0: andre@0: cleanup: andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_pl_Cert_ToString andre@0: * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) andre@0: */ andre@0: static PKIX_Error * andre@0: pkix_pl_Cert_ToString( andre@0: PKIX_PL_Object *object, andre@0: PKIX_PL_String **pString, andre@0: void *plContext) andre@0: { andre@0: PKIX_PL_String *certString = NULL; andre@0: PKIX_PL_Cert *pkixCert = NULL; andre@0: andre@0: PKIX_ENTER(CERT, "pkix_pl_Cert_toString"); andre@0: PKIX_NULLCHECK_TWO(object, pString); andre@0: andre@0: PKIX_CHECK(pkix_CheckType(object, PKIX_CERT_TYPE, plContext), andre@0: PKIX_OBJECTNOTCERT); andre@0: andre@0: pkixCert = (PKIX_PL_Cert *)object; andre@0: andre@0: PKIX_CHECK(pkix_pl_Cert_ToString_Helper andre@0: (pkixCert, PKIX_FALSE, &certString, plContext), andre@0: PKIX_CERTTOSTRINGHELPERFAILED); andre@0: andre@0: *pString = certString; andre@0: andre@0: cleanup: andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_pl_Cert_Hashcode andre@0: * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) andre@0: */ andre@0: static PKIX_Error * andre@0: pkix_pl_Cert_Hashcode( andre@0: PKIX_PL_Object *object, andre@0: PKIX_UInt32 *pHashcode, andre@0: void *plContext) andre@0: { andre@0: PKIX_PL_Cert *pkixCert = NULL; andre@0: CERTCertificate *nssCert = NULL; andre@0: unsigned char *derBytes = NULL; andre@0: PKIX_UInt32 derLength; andre@0: PKIX_UInt32 certHash; andre@0: andre@0: PKIX_ENTER(CERT, "pkix_pl_Cert_Hashcode"); andre@0: PKIX_NULLCHECK_TWO(object, pHashcode); andre@0: andre@0: PKIX_CHECK(pkix_CheckType(object, PKIX_CERT_TYPE, plContext), andre@0: PKIX_OBJECTNOTCERT); andre@0: andre@0: pkixCert = (PKIX_PL_Cert *)object; andre@0: andre@0: nssCert = pkixCert->nssCert; andre@0: derBytes = (nssCert->derCert).data; andre@0: derLength = (nssCert->derCert).len; andre@0: andre@0: PKIX_CHECK(pkix_hash(derBytes, derLength, &certHash, plContext), andre@0: PKIX_HASHFAILED); andre@0: andre@0: *pHashcode = certHash; andre@0: andre@0: cleanup: andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: andre@0: /* andre@0: * FUNCTION: pkix_pl_Cert_Equals andre@0: * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h) andre@0: */ andre@0: static PKIX_Error * andre@0: pkix_pl_Cert_Equals( andre@0: PKIX_PL_Object *firstObject, andre@0: PKIX_PL_Object *secondObject, andre@0: PKIX_Boolean *pResult, andre@0: void *plContext) andre@0: { andre@0: CERTCertificate *firstCert = NULL; andre@0: CERTCertificate *secondCert = NULL; andre@0: PKIX_UInt32 secondType; andre@0: PKIX_Boolean cmpResult; andre@0: andre@0: PKIX_ENTER(CERT, "pkix_pl_Cert_Equals"); andre@0: PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); andre@0: andre@0: /* test that firstObject is a Cert */ andre@0: PKIX_CHECK(pkix_CheckType(firstObject, PKIX_CERT_TYPE, plContext), andre@0: PKIX_FIRSTOBJECTNOTCERT); andre@0: andre@0: /* andre@0: * Since we know firstObject is a Cert, if both references are andre@0: * identical, they must be equal andre@0: */ andre@0: if (firstObject == secondObject){ andre@0: *pResult = PKIX_TRUE; andre@0: goto cleanup; andre@0: } andre@0: andre@0: /* andre@0: * If secondObject isn't a Cert, we don't throw an error. andre@0: * We simply return a Boolean result of FALSE andre@0: */ andre@0: *pResult = PKIX_FALSE; andre@0: PKIX_CHECK(PKIX_PL_Object_GetType andre@0: (secondObject, &secondType, plContext), andre@0: PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); andre@0: if (secondType != PKIX_CERT_TYPE) goto cleanup; andre@0: andre@0: firstCert = ((PKIX_PL_Cert *)firstObject)->nssCert; andre@0: secondCert = ((PKIX_PL_Cert *)secondObject)->nssCert; andre@0: andre@0: PKIX_NULLCHECK_TWO(firstCert, secondCert); andre@0: andre@0: /* CERT_CompareCerts does byte comparison on DER encodings of certs */ andre@0: PKIX_CERT_DEBUG("\t\tCalling CERT_CompareCerts).\n"); andre@0: cmpResult = CERT_CompareCerts(firstCert, secondCert); andre@0: andre@0: *pResult = cmpResult; andre@0: andre@0: cleanup: andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_pl_Cert_RegisterSelf andre@0: * DESCRIPTION: andre@0: * Registers PKIX_CERT_TYPE and its related functions with systemClasses[] andre@0: * THREAD SAFETY: andre@0: * Not Thread Safe - for performance and complexity reasons andre@0: * andre@0: * Since this function is only called by PKIX_PL_Initialize, which should andre@0: * only be called once, it is acceptable that this function is not andre@0: * thread-safe. andre@0: */ andre@0: PKIX_Error * andre@0: pkix_pl_Cert_RegisterSelf(void *plContext) andre@0: { andre@0: andre@0: extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; andre@0: pkix_ClassTable_Entry entry; andre@0: andre@0: PKIX_ENTER(CERT, "pkix_pl_Cert_RegisterSelf"); andre@0: andre@0: entry.description = "Cert"; andre@0: entry.objCounter = 0; andre@0: entry.typeObjectSize = sizeof(PKIX_PL_Cert); andre@0: entry.destructor = pkix_pl_Cert_Destroy; andre@0: entry.equalsFunction = pkix_pl_Cert_Equals; andre@0: entry.hashcodeFunction = pkix_pl_Cert_Hashcode; andre@0: entry.toStringFunction = pkix_pl_Cert_ToString; andre@0: entry.comparator = NULL; andre@0: entry.duplicateFunction = pkix_duplicateImmutable; andre@0: andre@0: systemClasses[PKIX_CERT_TYPE] = entry; andre@0: andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_pl_Cert_CreateWithNSSCert andre@0: * DESCRIPTION: andre@0: * andre@0: * Creates a new certificate using the CERTCertificate pointed to by "nssCert" andre@0: * and stores it at "pCert". Once created, a Cert is immutable. andre@0: * andre@0: * This function is primarily used as a convenience function for the andre@0: * performance tests that have easy access to a CERTCertificate. andre@0: * andre@0: * PARAMETERS: andre@0: * "nssCert" andre@0: * Address of CERTCertificate representing the NSS certificate. andre@0: * Must be non-NULL. andre@0: * "pCert" andre@0: * Address where object pointer will be stored. Must be non-NULL. andre@0: * "plContext" andre@0: * Platform-specific context pointer. andre@0: * THREAD SAFETY: andre@0: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) andre@0: * RETURNS: andre@0: * Returns NULL if the function succeeds. andre@0: * Returns a Cert Error if the function fails in a non-fatal way. andre@0: * Returns a Fatal Error if the function fails in an unrecoverable way. andre@0: */ andre@0: PKIX_Error * andre@0: pkix_pl_Cert_CreateWithNSSCert( andre@0: CERTCertificate *nssCert, andre@0: PKIX_PL_Cert **pCert, andre@0: void *plContext) andre@0: { andre@0: PKIX_PL_Cert *cert = NULL; andre@0: andre@0: PKIX_ENTER(CERT, "pkix_pl_Cert_CreateWithNSSCert"); andre@0: PKIX_NULLCHECK_TWO(pCert, nssCert); andre@0: andre@0: /* create a PKIX_PL_Cert object */ andre@0: PKIX_CHECK(PKIX_PL_Object_Alloc andre@0: (PKIX_CERT_TYPE, andre@0: sizeof (PKIX_PL_Cert), andre@0: (PKIX_PL_Object **)&cert, andre@0: plContext), andre@0: PKIX_COULDNOTCREATEOBJECT); andre@0: andre@0: /* populate the nssCert field */ andre@0: cert->nssCert = nssCert; andre@0: andre@0: /* initialize remaining fields */ andre@0: /* andre@0: * Fields ending with Absent are initialized to PKIX_FALSE so that the andre@0: * first time we need the value we will look for it. If we find it is andre@0: * actually absent, the flag will at that time be set to PKIX_TRUE to andre@0: * prevent searching for it later. andre@0: * Fields ending with Processed are those where a value is defined andre@0: * for the Absent case, and a value of zero is possible. When the andre@0: * flag is still true we have to look for the field, set the default andre@0: * value if necessary, and set the Processed flag to PKIX_TRUE. andre@0: */ andre@0: cert->subject = NULL; andre@0: cert->issuer = NULL; andre@0: cert->subjAltNames = NULL; andre@0: cert->subjAltNamesAbsent = PKIX_FALSE; andre@0: cert->publicKeyAlgId = NULL; andre@0: cert->publicKey = NULL; andre@0: cert->serialNumber = NULL; andre@0: cert->critExtOids = NULL; andre@0: cert->subjKeyId = NULL; andre@0: cert->subjKeyIdAbsent = PKIX_FALSE; andre@0: cert->authKeyId = NULL; andre@0: cert->authKeyIdAbsent = PKIX_FALSE; andre@0: cert->extKeyUsages = NULL; andre@0: cert->extKeyUsagesAbsent = PKIX_FALSE; andre@0: cert->certBasicConstraints = NULL; andre@0: cert->basicConstraintsAbsent = PKIX_FALSE; andre@0: cert->certPolicyInfos = NULL; andre@0: cert->policyInfoAbsent = PKIX_FALSE; andre@0: cert->policyMappingsAbsent = PKIX_FALSE; andre@0: cert->certPolicyMappings = NULL; andre@0: cert->policyConstraintsProcessed = PKIX_FALSE; andre@0: cert->policyConstraintsExplicitPolicySkipCerts = 0; andre@0: cert->policyConstraintsInhibitMappingSkipCerts = 0; andre@0: cert->inhibitAnyPolicyProcessed = PKIX_FALSE; andre@0: cert->inhibitAnySkipCerts = 0; andre@0: cert->nameConstraints = NULL; andre@0: cert->nameConstraintsAbsent = PKIX_FALSE; andre@0: cert->arenaNameConstraints = NULL; andre@0: cert->nssSubjAltNames = NULL; andre@0: cert->cacheFlag = PKIX_FALSE; andre@0: cert->store = NULL; andre@0: cert->authorityInfoAccess = NULL; andre@0: cert->subjectInfoAccess = NULL; andre@0: cert->isUserTrustAnchor = PKIX_FALSE; andre@0: cert->crldpList = NULL; andre@0: andre@0: *pCert = cert; andre@0: andre@0: cleanup: andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_pl_Cert_CreateToList andre@0: * DESCRIPTION: andre@0: * andre@0: * Creates a new certificate using the DER-encoding pointed to by "derCertItem" andre@0: * and appends it to the list pointed to by "certList". If Cert creation fails, andre@0: * the function returns with certList unchanged, but any decoding Error is andre@0: * discarded. andre@0: * andre@0: * PARAMETERS: andre@0: * "derCertItem" andre@0: * Address of SECItem containing the DER representation of a certificate. andre@0: * Must be non-NULL. andre@0: * "certList" andre@0: * Address of List to which the Cert will be appended, if successfully andre@0: * created. May be empty, but must be non-NULL. andre@0: * "plContext" andre@0: * Platform-specific context pointer. andre@0: * THREAD SAFETY: andre@0: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) andre@0: * RETURNS: andre@0: * Returns NULL if the function succeeds. andre@0: * Returns a Cert Error if the function fails in a non-fatal way. andre@0: * Returns a Fatal Error if the function fails in an unrecoverable way. andre@0: */ andre@0: PKIX_Error * andre@0: pkix_pl_Cert_CreateToList( andre@0: SECItem *derCertItem, andre@0: PKIX_List *certList, andre@0: void *plContext) andre@0: { andre@0: CERTCertificate *nssCert = NULL; andre@0: PKIX_PL_Cert *cert = NULL; andre@0: CERTCertDBHandle *handle; andre@0: andre@0: PKIX_ENTER(CERT, "pkix_pl_Cert_CreateToList"); andre@0: PKIX_NULLCHECK_TWO(derCertItem, certList); andre@0: andre@0: handle = CERT_GetDefaultCertDB(); andre@0: nssCert = CERT_NewTempCertificate(handle, derCertItem, andre@0: /* nickname */ NULL, andre@0: /* isPerm */ PR_FALSE, andre@0: /* copyDer */ PR_TRUE); andre@0: if (!nssCert) { andre@0: goto cleanup; andre@0: } andre@0: andre@0: PKIX_CHECK(pkix_pl_Cert_CreateWithNSSCert andre@0: (nssCert, &cert, plContext), andre@0: PKIX_CERTCREATEWITHNSSCERTFAILED); andre@0: andre@0: nssCert = NULL; andre@0: andre@0: PKIX_CHECK(PKIX_List_AppendItem andre@0: (certList, (PKIX_PL_Object *) cert, plContext), andre@0: PKIX_LISTAPPENDITEMFAILED); andre@0: andre@0: cleanup: andre@0: if (nssCert) { andre@0: CERT_DestroyCertificate(nssCert); andre@0: } andre@0: andre@0: PKIX_DECREF(cert); andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* --Public-Functions------------------------------------------------------- */ andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_Cert_Create (see comments in pkix_pl_pki.h) andre@0: * XXX We may want to cache the cert after parsing it, so it can be reused andre@0: * XXX Are the NSS/NSPR functions thread safe andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_Cert_Create( andre@0: PKIX_PL_ByteArray *byteArray, andre@0: PKIX_PL_Cert **pCert, andre@0: void *plContext) andre@0: { andre@0: CERTCertificate *nssCert = NULL; andre@0: SECItem *derCertItem = NULL; andre@0: void *derBytes = NULL; andre@0: PKIX_UInt32 derLength; andre@0: PKIX_Boolean copyDER; andre@0: PKIX_PL_Cert *cert = NULL; andre@0: CERTCertDBHandle *handle; andre@0: andre@0: PKIX_ENTER(CERT, "PKIX_PL_Cert_Create"); andre@0: PKIX_NULLCHECK_TWO(pCert, byteArray); andre@0: andre@0: PKIX_CHECK(PKIX_PL_ByteArray_GetPointer andre@0: (byteArray, &derBytes, plContext), andre@0: PKIX_BYTEARRAYGETPOINTERFAILED); andre@0: andre@0: PKIX_CHECK(PKIX_PL_ByteArray_GetLength andre@0: (byteArray, &derLength, plContext), andre@0: PKIX_BYTEARRAYGETLENGTHFAILED); andre@0: andre@0: derCertItem = SECITEM_AllocItem(NULL, NULL, derLength); andre@0: if (derCertItem == NULL){ andre@0: PKIX_ERROR(PKIX_OUTOFMEMORY); andre@0: } andre@0: andre@0: (void) PORT_Memcpy(derCertItem->data, derBytes, derLength); andre@0: andre@0: /* andre@0: * setting copyDER to true forces NSS to make its own copy of the DER, andre@0: * allowing us to free our copy without worrying about whether NSS andre@0: * is still using it andre@0: */ andre@0: copyDER = PKIX_TRUE; andre@0: handle = CERT_GetDefaultCertDB(); andre@0: nssCert = CERT_NewTempCertificate(handle, derCertItem, andre@0: /* nickname */ NULL, andre@0: /* isPerm */ PR_FALSE, andre@0: /* copyDer */ PR_TRUE); andre@0: if (!nssCert){ andre@0: PKIX_ERROR(PKIX_CERTDECODEDERCERTIFICATEFAILED); andre@0: } andre@0: andre@0: PKIX_CHECK(pkix_pl_Cert_CreateWithNSSCert andre@0: (nssCert, &cert, plContext), andre@0: PKIX_CERTCREATEWITHNSSCERTFAILED); andre@0: andre@0: *pCert = cert; andre@0: andre@0: cleanup: andre@0: if (derCertItem){ andre@0: SECITEM_FreeItem(derCertItem, PKIX_TRUE); andre@0: } andre@0: andre@0: if (nssCert && PKIX_ERROR_RECEIVED){ andre@0: PKIX_CERT_DEBUG("\t\tCalling CERT_DestroyCertificate).\n"); andre@0: CERT_DestroyCertificate(nssCert); andre@0: nssCert = NULL; andre@0: } andre@0: andre@0: PKIX_FREE(derBytes); andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_Cert_CreateFromCERTCertificate andre@0: * (see comments in pkix_pl_pki.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_Cert_CreateFromCERTCertificate( andre@0: const CERTCertificate *nssCert, andre@0: PKIX_PL_Cert **pCert, andre@0: void *plContext) andre@0: { andre@0: void *buf = NULL; andre@0: PKIX_UInt32 len; andre@0: PKIX_PL_ByteArray *byteArray = NULL; andre@0: andre@0: PKIX_ENTER(CERT, "PKIX_PL_Cert_CreateWithNssCert"); andre@0: PKIX_NULLCHECK_TWO(pCert, nssCert); andre@0: andre@0: buf = (void*)nssCert->derCert.data; andre@0: len = nssCert->derCert.len; andre@0: andre@0: PKIX_CHECK( andre@0: PKIX_PL_ByteArray_Create(buf, len, &byteArray, plContext), andre@0: PKIX_BYTEARRAYCREATEFAILED); andre@0: andre@0: PKIX_CHECK( andre@0: PKIX_PL_Cert_Create(byteArray, pCert, plContext), andre@0: PKIX_CERTCREATEWITHNSSCERTFAILED); andre@0: andre@0: #ifdef PKIX_UNDEF andre@0: /* will be tested and used as a patch for bug 391612 */ andre@0: nssCert = CERT_DupCertificate(nssInCert); andre@0: andre@0: PKIX_CHECK(pkix_pl_Cert_CreateWithNSSCert andre@0: (nssCert, &cert, plContext), andre@0: PKIX_CERTCREATEWITHNSSCERTFAILED); andre@0: #endif /* PKIX_UNDEF */ andre@0: andre@0: cleanup: andre@0: andre@0: #ifdef PKIX_UNDEF andre@0: if (nssCert && PKIX_ERROR_RECEIVED){ andre@0: PKIX_CERT_DEBUG("\t\tCalling CERT_DestroyCertificate).\n"); andre@0: CERT_DestroyCertificate(nssCert); andre@0: nssCert = NULL; andre@0: } andre@0: #endif /* PKIX_UNDEF */ andre@0: andre@0: PKIX_DECREF(byteArray); andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_Cert_GetVersion (see comments in pkix_pl_pki.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_Cert_GetVersion( andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_UInt32 *pVersion, andre@0: void *plContext) andre@0: { andre@0: CERTCertificate *nssCert = NULL; andre@0: PKIX_UInt32 myVersion = 0; /* v1 */ andre@0: andre@0: PKIX_ENTER(CERT, "PKIX_PL_Cert_GetVersion"); andre@0: PKIX_NULLCHECK_THREE(cert, cert->nssCert, pVersion); andre@0: andre@0: nssCert = cert->nssCert; andre@0: if (nssCert->version.len != 0) { andre@0: myVersion = *(nssCert->version.data); andre@0: } andre@0: andre@0: if (myVersion > 2){ andre@0: PKIX_ERROR(PKIX_VERSIONVALUEMUSTBEV1V2ORV3); andre@0: } andre@0: andre@0: *pVersion = myVersion; andre@0: andre@0: cleanup: andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_Cert_GetSerialNumber (see comments in pkix_pl_pki.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_Cert_GetSerialNumber( andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_PL_BigInt **pSerialNumber, andre@0: void *plContext) andre@0: { andre@0: CERTCertificate *nssCert = NULL; andre@0: SECItem serialNumItem; andre@0: PKIX_PL_BigInt *serialNumber = NULL; andre@0: char *bytes = NULL; andre@0: PKIX_UInt32 length; andre@0: andre@0: PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSerialNumber"); andre@0: PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSerialNumber); andre@0: andre@0: if (cert->serialNumber == NULL){ andre@0: andre@0: PKIX_OBJECT_LOCK(cert); andre@0: andre@0: if (cert->serialNumber == NULL){ andre@0: andre@0: nssCert = cert->nssCert; andre@0: serialNumItem = nssCert->serialNumber; andre@0: andre@0: length = serialNumItem.len; andre@0: bytes = (char *)serialNumItem.data; andre@0: andre@0: PKIX_CHECK(pkix_pl_BigInt_CreateWithBytes andre@0: (bytes, length, &serialNumber, plContext), andre@0: PKIX_BIGINTCREATEWITHBYTESFAILED); andre@0: andre@0: /* save a cached copy in case it is asked for again */ andre@0: cert->serialNumber = serialNumber; andre@0: } andre@0: andre@0: PKIX_OBJECT_UNLOCK(cert); andre@0: } andre@0: andre@0: PKIX_INCREF(cert->serialNumber); andre@0: *pSerialNumber = cert->serialNumber; andre@0: andre@0: cleanup: andre@0: PKIX_OBJECT_UNLOCK(lockedObject); andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_Cert_GetSubject (see comments in pkix_pl_pki.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_Cert_GetSubject( andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_PL_X500Name **pCertSubject, andre@0: void *plContext) andre@0: { andre@0: PKIX_PL_X500Name *pkixSubject = NULL; andre@0: CERTName *subjName = NULL; andre@0: SECItem *derSubjName = NULL; andre@0: andre@0: PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubject"); andre@0: PKIX_NULLCHECK_THREE(cert, cert->nssCert, pCertSubject); andre@0: andre@0: /* if we don't have a cached copy from before, we create one */ andre@0: if (cert->subject == NULL){ andre@0: andre@0: PKIX_OBJECT_LOCK(cert); andre@0: andre@0: if (cert->subject == NULL){ andre@0: andre@0: subjName = &cert->nssCert->subject; andre@0: derSubjName = &cert->nssCert->derSubject; andre@0: andre@0: /* if there is no subject name */ andre@0: if (derSubjName->data == NULL) { andre@0: andre@0: pkixSubject = NULL; andre@0: andre@0: } else { andre@0: PKIX_CHECK(PKIX_PL_X500Name_CreateFromCERTName andre@0: (derSubjName, subjName, &pkixSubject, andre@0: plContext), andre@0: PKIX_X500NAMECREATEFROMCERTNAMEFAILED); andre@0: andre@0: } andre@0: /* save a cached copy in case it is asked for again */ andre@0: cert->subject = pkixSubject; andre@0: } andre@0: andre@0: PKIX_OBJECT_UNLOCK(cert); andre@0: } andre@0: andre@0: PKIX_INCREF(cert->subject); andre@0: *pCertSubject = cert->subject; andre@0: andre@0: cleanup: andre@0: PKIX_OBJECT_UNLOCK(lockedObject); andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_Cert_GetIssuer (see comments in pkix_pl_pki.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_Cert_GetIssuer( andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_PL_X500Name **pCertIssuer, andre@0: void *plContext) andre@0: { andre@0: PKIX_PL_X500Name *pkixIssuer = NULL; andre@0: SECItem *derIssuerName = NULL; andre@0: CERTName *issuerName = NULL; andre@0: andre@0: PKIX_ENTER(CERT, "PKIX_PL_Cert_GetIssuer"); andre@0: PKIX_NULLCHECK_THREE(cert, cert->nssCert, pCertIssuer); andre@0: andre@0: /* if we don't have a cached copy from before, we create one */ andre@0: if (cert->issuer == NULL){ andre@0: andre@0: PKIX_OBJECT_LOCK(cert); andre@0: andre@0: if (cert->issuer == NULL){ andre@0: andre@0: issuerName = &cert->nssCert->issuer; andre@0: derIssuerName = &cert->nssCert->derIssuer; andre@0: andre@0: /* if there is no subject name */ andre@0: PKIX_CHECK(PKIX_PL_X500Name_CreateFromCERTName andre@0: (derIssuerName, issuerName, andre@0: &pkixIssuer, plContext), andre@0: PKIX_X500NAMECREATEFROMCERTNAMEFAILED); andre@0: andre@0: /* save a cached copy in case it is asked for again */ andre@0: cert->issuer = pkixIssuer; andre@0: } andre@0: andre@0: PKIX_OBJECT_UNLOCK(cert); andre@0: } andre@0: andre@0: PKIX_INCREF(cert->issuer); andre@0: *pCertIssuer = cert->issuer; andre@0: andre@0: cleanup: andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_Cert_GetSubjectAltNames (see comments in pkix_pl_pki.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_Cert_GetSubjectAltNames( andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_List **pSubjectAltNames, /* list of PKIX_PL_GeneralName */ andre@0: void *plContext) andre@0: { andre@0: PKIX_PL_GeneralName *pkixAltName = NULL; andre@0: PKIX_List *altNamesList = NULL; andre@0: andre@0: CERTGeneralName *nssOriginalAltName = NULL; andre@0: CERTGeneralName *nssTempAltName = NULL; andre@0: andre@0: PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectAltNames"); andre@0: PKIX_NULLCHECK_TWO(cert, pSubjectAltNames); andre@0: andre@0: /* if we don't have a cached copy from before, we create one */ andre@0: if ((cert->subjAltNames == NULL) && (!cert->subjAltNamesAbsent)){ andre@0: andre@0: PKIX_OBJECT_LOCK(cert); andre@0: andre@0: if ((cert->subjAltNames == NULL) && andre@0: (!cert->subjAltNamesAbsent)){ andre@0: andre@0: PKIX_CHECK(pkix_pl_Cert_GetNssSubjectAltNames andre@0: (cert, andre@0: PKIX_TRUE, andre@0: &nssOriginalAltName, andre@0: plContext), andre@0: PKIX_CERTGETNSSSUBJECTALTNAMESFAILED); andre@0: andre@0: if (nssOriginalAltName == NULL) { andre@0: cert->subjAltNamesAbsent = PKIX_TRUE; andre@0: pSubjectAltNames = NULL; andre@0: goto cleanup; andre@0: } andre@0: andre@0: nssTempAltName = nssOriginalAltName; andre@0: andre@0: PKIX_CHECK(PKIX_List_Create(&altNamesList, plContext), andre@0: PKIX_LISTCREATEFAILED); andre@0: andre@0: do { andre@0: PKIX_CHECK(pkix_pl_GeneralName_Create andre@0: (nssTempAltName, &pkixAltName, plContext), andre@0: PKIX_GENERALNAMECREATEFAILED); andre@0: andre@0: PKIX_CHECK(PKIX_List_AppendItem andre@0: (altNamesList, andre@0: (PKIX_PL_Object *)pkixAltName, andre@0: plContext), andre@0: PKIX_LISTAPPENDITEMFAILED); andre@0: andre@0: PKIX_DECREF(pkixAltName); andre@0: andre@0: PKIX_CERT_DEBUG andre@0: ("\t\tCalling CERT_GetNextGeneralName).\n"); andre@0: nssTempAltName = CERT_GetNextGeneralName andre@0: (nssTempAltName); andre@0: andre@0: } while (nssTempAltName != nssOriginalAltName); andre@0: andre@0: /* save a cached copy in case it is asked for again */ andre@0: cert->subjAltNames = altNamesList; andre@0: PKIX_CHECK(PKIX_List_SetImmutable andre@0: (cert->subjAltNames, plContext), andre@0: PKIX_LISTSETIMMUTABLEFAILED); andre@0: andre@0: } andre@0: andre@0: PKIX_OBJECT_UNLOCK(cert); andre@0: } andre@0: andre@0: PKIX_INCREF(cert->subjAltNames); andre@0: andre@0: *pSubjectAltNames = cert->subjAltNames; andre@0: andre@0: cleanup: andre@0: PKIX_DECREF(pkixAltName); andre@0: if (PKIX_ERROR_RECEIVED){ andre@0: PKIX_DECREF(altNamesList); andre@0: } andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_Cert_GetAllSubjectNames (see comments in pkix_pl_pki.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_Cert_GetAllSubjectNames( andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_List **pAllSubjectNames, /* list of PKIX_PL_GeneralName */ andre@0: void *plContext) andre@0: { andre@0: CERTGeneralName *nssOriginalSubjectName = NULL; andre@0: CERTGeneralName *nssTempSubjectName = NULL; andre@0: PKIX_List *allSubjectNames = NULL; andre@0: PKIX_PL_GeneralName *pkixSubjectName = NULL; andre@0: PLArenaPool *arena = NULL; andre@0: andre@0: PKIX_ENTER(CERT, "PKIX_PL_Cert_GetAllSubjectNames"); andre@0: PKIX_NULLCHECK_THREE(cert, cert->nssCert, pAllSubjectNames); andre@0: andre@0: andre@0: if (cert->nssCert->subjectName == NULL){ andre@0: /* if there is no subject DN, just get altnames */ andre@0: andre@0: PKIX_CHECK(pkix_pl_Cert_GetNssSubjectAltNames andre@0: (cert, andre@0: PKIX_FALSE, /* hasLock */ andre@0: &nssOriginalSubjectName, andre@0: plContext), andre@0: PKIX_CERTGETNSSSUBJECTALTNAMESFAILED); andre@0: andre@0: } else { /* get subject DN and altnames */ andre@0: andre@0: arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); andre@0: if (arena == NULL) { andre@0: PKIX_ERROR(PKIX_OUTOFMEMORY); andre@0: } andre@0: andre@0: /* This NSS call returns both Subject and Subject Alt Names */ andre@0: PKIX_CERT_DEBUG("\t\tCalling CERT_GetCertificateNames\n"); andre@0: nssOriginalSubjectName = andre@0: CERT_GetCertificateNames(cert->nssCert, arena); andre@0: } andre@0: andre@0: if (nssOriginalSubjectName == NULL) { andre@0: pAllSubjectNames = NULL; andre@0: goto cleanup; andre@0: } andre@0: andre@0: nssTempSubjectName = nssOriginalSubjectName; andre@0: andre@0: PKIX_CHECK(PKIX_List_Create(&allSubjectNames, plContext), andre@0: PKIX_LISTCREATEFAILED); andre@0: andre@0: do { andre@0: PKIX_CHECK(pkix_pl_GeneralName_Create andre@0: (nssTempSubjectName, &pkixSubjectName, plContext), andre@0: PKIX_GENERALNAMECREATEFAILED); andre@0: andre@0: PKIX_CHECK(PKIX_List_AppendItem andre@0: (allSubjectNames, andre@0: (PKIX_PL_Object *)pkixSubjectName, andre@0: plContext), andre@0: PKIX_LISTAPPENDITEMFAILED); andre@0: andre@0: PKIX_DECREF(pkixSubjectName); andre@0: andre@0: PKIX_CERT_DEBUG andre@0: ("\t\tCalling CERT_GetNextGeneralName).\n"); andre@0: nssTempSubjectName = CERT_GetNextGeneralName andre@0: (nssTempSubjectName); andre@0: } while (nssTempSubjectName != nssOriginalSubjectName); andre@0: andre@0: *pAllSubjectNames = allSubjectNames; andre@0: andre@0: cleanup: andre@0: if (PKIX_ERROR_RECEIVED){ andre@0: PKIX_DECREF(allSubjectNames); andre@0: } andre@0: andre@0: if (arena){ andre@0: PORT_FreeArena(arena, PR_FALSE); andre@0: } andre@0: PKIX_DECREF(pkixSubjectName); andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_Cert_GetSubjectPublicKeyAlgId andre@0: * (see comments in pkix_pl_pki.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_Cert_GetSubjectPublicKeyAlgId( andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_PL_OID **pSubjKeyAlgId, andre@0: void *plContext) andre@0: { andre@0: PKIX_PL_OID *pubKeyAlgId = NULL; andre@0: andre@0: PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectPublicKeyAlgId"); andre@0: PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSubjKeyAlgId); andre@0: andre@0: /* if we don't have a cached copy from before, we create one */ andre@0: if (cert->publicKeyAlgId == NULL){ andre@0: PKIX_OBJECT_LOCK(cert); andre@0: if (cert->publicKeyAlgId == NULL){ andre@0: CERTCertificate *nssCert = cert->nssCert; andre@0: SECAlgorithmID *algorithm; andre@0: SECItem *algBytes; andre@0: andre@0: algorithm = &nssCert->subjectPublicKeyInfo.algorithm; andre@0: algBytes = &algorithm->algorithm; andre@0: if (!algBytes->data || !algBytes->len) { andre@0: PKIX_ERROR_FATAL(PKIX_ALGORITHMBYTESLENGTH0); andre@0: } andre@0: PKIX_CHECK(PKIX_PL_OID_CreateBySECItem andre@0: (algBytes, &pubKeyAlgId, plContext), andre@0: PKIX_OIDCREATEFAILED); andre@0: andre@0: /* save a cached copy in case it is asked for again */ andre@0: cert->publicKeyAlgId = pubKeyAlgId; andre@0: pubKeyAlgId = NULL; andre@0: } andre@0: PKIX_OBJECT_UNLOCK(cert); andre@0: } andre@0: andre@0: PKIX_INCREF(cert->publicKeyAlgId); andre@0: *pSubjKeyAlgId = cert->publicKeyAlgId; andre@0: andre@0: cleanup: andre@0: PKIX_DECREF(pubKeyAlgId); andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_Cert_GetSubjectPublicKey (see comments in pkix_pl_pki.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_Cert_GetSubjectPublicKey( andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_PL_PublicKey **pPublicKey, andre@0: void *plContext) andre@0: { andre@0: PKIX_PL_PublicKey *pkixPubKey = NULL; andre@0: SECStatus rv; andre@0: andre@0: CERTSubjectPublicKeyInfo *from = NULL; andre@0: CERTSubjectPublicKeyInfo *to = NULL; andre@0: SECItem *fromItem = NULL; andre@0: SECItem *toItem = NULL; andre@0: andre@0: PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectPublicKey"); andre@0: PKIX_NULLCHECK_THREE(cert, cert->nssCert, pPublicKey); andre@0: andre@0: /* if we don't have a cached copy from before, we create one */ andre@0: if (cert->publicKey == NULL){ andre@0: andre@0: PKIX_OBJECT_LOCK(cert); andre@0: andre@0: if (cert->publicKey == NULL){ andre@0: andre@0: /* create a PKIX_PL_PublicKey object */ andre@0: PKIX_CHECK(PKIX_PL_Object_Alloc andre@0: (PKIX_PUBLICKEY_TYPE, andre@0: sizeof (PKIX_PL_PublicKey), andre@0: (PKIX_PL_Object **)&pkixPubKey, andre@0: plContext), andre@0: PKIX_COULDNOTCREATEOBJECT); andre@0: andre@0: /* initialize fields */ andre@0: pkixPubKey->nssSPKI = NULL; andre@0: andre@0: /* populate the SPKI field */ andre@0: PKIX_CHECK(PKIX_PL_Malloc andre@0: (sizeof (CERTSubjectPublicKeyInfo), andre@0: (void **)&pkixPubKey->nssSPKI, andre@0: plContext), andre@0: PKIX_MALLOCFAILED); andre@0: andre@0: to = pkixPubKey->nssSPKI; andre@0: from = &cert->nssCert->subjectPublicKeyInfo; andre@0: andre@0: PKIX_NULLCHECK_TWO(to, from); andre@0: andre@0: PKIX_CERT_DEBUG andre@0: ("\t\tCalling SECOID_CopyAlgorithmID).\n"); andre@0: rv = SECOID_CopyAlgorithmID andre@0: (NULL, &to->algorithm, &from->algorithm); andre@0: if (rv != SECSuccess) { andre@0: PKIX_ERROR(PKIX_SECOIDCOPYALGORITHMIDFAILED); andre@0: } andre@0: andre@0: /* andre@0: * NSS stores the length of subjectPublicKey in bits. andre@0: * Therefore, we use that length converted to bytes andre@0: * using ((length+7)>>3) before calling PORT_Memcpy andre@0: * in order to avoid "read from uninitialized memory" andre@0: * errors. andre@0: */ andre@0: andre@0: toItem = &to->subjectPublicKey; andre@0: fromItem = &from->subjectPublicKey; andre@0: andre@0: PKIX_NULLCHECK_TWO(toItem, fromItem); andre@0: andre@0: toItem->type = fromItem->type; andre@0: andre@0: toItem->data = andre@0: (unsigned char*) PORT_ZAlloc(fromItem->len); andre@0: if (!toItem->data){ andre@0: PKIX_ERROR(PKIX_OUTOFMEMORY); andre@0: } andre@0: andre@0: (void) PORT_Memcpy(toItem->data, andre@0: fromItem->data, andre@0: (fromItem->len + 7)>>3); andre@0: toItem->len = fromItem->len; andre@0: andre@0: /* save a cached copy in case it is asked for again */ andre@0: cert->publicKey = pkixPubKey; andre@0: } andre@0: andre@0: PKIX_OBJECT_UNLOCK(cert); andre@0: } andre@0: andre@0: PKIX_INCREF(cert->publicKey); andre@0: *pPublicKey = cert->publicKey; andre@0: andre@0: cleanup: andre@0: andre@0: if (PKIX_ERROR_RECEIVED && pkixPubKey){ andre@0: PKIX_DECREF(pkixPubKey); andre@0: cert->publicKey = NULL; andre@0: } andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_Cert_GetCriticalExtensionOIDs andre@0: * (see comments in pkix_pl_pki.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_Cert_GetCriticalExtensionOIDs( andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_List **pList, /* list of PKIX_PL_OID */ andre@0: void *plContext) andre@0: { andre@0: PKIX_List *oidsList = NULL; andre@0: CERTCertExtension **extensions = NULL; andre@0: CERTCertificate *nssCert = NULL; andre@0: andre@0: PKIX_ENTER(CERT, "PKIX_PL_Cert_GetCriticalExtensionOIDs"); andre@0: PKIX_NULLCHECK_THREE(cert, cert->nssCert, pList); andre@0: andre@0: /* if we don't have a cached copy from before, we create one */ andre@0: if (cert->critExtOids == NULL) { andre@0: andre@0: PKIX_OBJECT_LOCK(cert); andre@0: andre@0: if (cert->critExtOids == NULL) { andre@0: andre@0: nssCert = cert->nssCert; andre@0: andre@0: /* andre@0: * ASN.1 for Extension andre@0: * andre@0: * Extension ::= SEQUENCE { andre@0: * extnID OBJECT IDENTIFIER, andre@0: * critical BOOLEAN DEFAULT FALSE, andre@0: * extnValue OCTET STRING } andre@0: * andre@0: */ andre@0: andre@0: extensions = nssCert->extensions; andre@0: andre@0: PKIX_CHECK(pkix_pl_OID_GetCriticalExtensionOIDs andre@0: (extensions, &oidsList, plContext), andre@0: PKIX_GETCRITICALEXTENSIONOIDSFAILED); andre@0: andre@0: /* save a cached copy in case it is asked for again */ andre@0: cert->critExtOids = oidsList; andre@0: } andre@0: andre@0: PKIX_OBJECT_UNLOCK(cert); andre@0: } andre@0: andre@0: /* We should return a copy of the List since this list changes */ andre@0: PKIX_DUPLICATE(cert->critExtOids, pList, plContext, andre@0: PKIX_OBJECTDUPLICATELISTFAILED); andre@0: andre@0: cleanup: andre@0: PKIX_OBJECT_UNLOCK(lockedObject); andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_Cert_GetAuthorityKeyIdentifier andre@0: * (see comments in pkix_pl_pki.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_Cert_GetAuthorityKeyIdentifier( andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_PL_ByteArray **pAuthKeyId, andre@0: void *plContext) andre@0: { andre@0: PKIX_PL_ByteArray *authKeyId = NULL; andre@0: CERTCertificate *nssCert = NULL; andre@0: CERTAuthKeyID *authKeyIdExtension = NULL; andre@0: PLArenaPool *arena = NULL; andre@0: SECItem retItem; andre@0: andre@0: PKIX_ENTER(CERT, "PKIX_PL_Cert_GetAuthorityKeyIdentifier"); andre@0: PKIX_NULLCHECK_THREE(cert, cert->nssCert, pAuthKeyId); andre@0: andre@0: /* if we don't have a cached copy from before, we create one */ andre@0: if ((cert->authKeyId == NULL) && (!cert->authKeyIdAbsent)){ andre@0: andre@0: PKIX_OBJECT_LOCK(cert); andre@0: andre@0: if ((cert->authKeyId == NULL) && (!cert->authKeyIdAbsent)){ andre@0: andre@0: arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); andre@0: if (arena == NULL) { andre@0: PKIX_ERROR(PKIX_OUTOFMEMORY); andre@0: } andre@0: andre@0: nssCert = cert->nssCert; andre@0: andre@0: authKeyIdExtension = andre@0: CERT_FindAuthKeyIDExten(arena, nssCert); andre@0: if (authKeyIdExtension == NULL){ andre@0: cert->authKeyIdAbsent = PKIX_TRUE; andre@0: *pAuthKeyId = NULL; andre@0: goto cleanup; andre@0: } andre@0: andre@0: retItem = authKeyIdExtension->keyID; andre@0: andre@0: if (retItem.len == 0){ andre@0: cert->authKeyIdAbsent = PKIX_TRUE; andre@0: *pAuthKeyId = NULL; andre@0: goto cleanup; andre@0: } andre@0: andre@0: PKIX_CHECK(PKIX_PL_ByteArray_Create andre@0: (retItem.data, andre@0: retItem.len, andre@0: &authKeyId, andre@0: plContext), andre@0: PKIX_BYTEARRAYCREATEFAILED); andre@0: andre@0: /* save a cached copy in case it is asked for again */ andre@0: cert->authKeyId = authKeyId; andre@0: } andre@0: andre@0: PKIX_OBJECT_UNLOCK(cert); andre@0: } andre@0: andre@0: PKIX_INCREF(cert->authKeyId); andre@0: *pAuthKeyId = cert->authKeyId; andre@0: andre@0: cleanup: andre@0: PKIX_OBJECT_UNLOCK(lockedObject); andre@0: if (arena){ andre@0: PORT_FreeArena(arena, PR_FALSE); andre@0: } andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_Cert_GetSubjectKeyIdentifier andre@0: * (see comments in pkix_pl_pki.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_Cert_GetSubjectKeyIdentifier( andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_PL_ByteArray **pSubjKeyId, andre@0: void *plContext) andre@0: { andre@0: PKIX_PL_ByteArray *subjKeyId = NULL; andre@0: CERTCertificate *nssCert = NULL; andre@0: SECItem *retItem = NULL; andre@0: SECStatus status; andre@0: andre@0: PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectKeyIdentifier"); andre@0: PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSubjKeyId); andre@0: andre@0: /* if we don't have a cached copy from before, we create one */ andre@0: if ((cert->subjKeyId == NULL) && (!cert->subjKeyIdAbsent)){ andre@0: andre@0: PKIX_OBJECT_LOCK(cert); andre@0: andre@0: if ((cert->subjKeyId == NULL) && (!cert->subjKeyIdAbsent)){ andre@0: andre@0: retItem = SECITEM_AllocItem(NULL, NULL, 0); andre@0: if (retItem == NULL){ andre@0: PKIX_ERROR(PKIX_OUTOFMEMORY); andre@0: } andre@0: andre@0: nssCert = cert->nssCert; andre@0: andre@0: status = CERT_FindSubjectKeyIDExtension andre@0: (nssCert, retItem); andre@0: if (status != SECSuccess) { andre@0: cert->subjKeyIdAbsent = PKIX_TRUE; andre@0: *pSubjKeyId = NULL; andre@0: goto cleanup; andre@0: } andre@0: andre@0: PKIX_CHECK(PKIX_PL_ByteArray_Create andre@0: (retItem->data, andre@0: retItem->len, andre@0: &subjKeyId, andre@0: plContext), andre@0: PKIX_BYTEARRAYCREATEFAILED); andre@0: andre@0: /* save a cached copy in case it is asked for again */ andre@0: cert->subjKeyId = subjKeyId; andre@0: } andre@0: andre@0: PKIX_OBJECT_UNLOCK(cert); andre@0: } andre@0: andre@0: PKIX_INCREF(cert->subjKeyId); andre@0: *pSubjKeyId = cert->subjKeyId; andre@0: andre@0: cleanup: andre@0: PKIX_OBJECT_UNLOCK(lockedObject); andre@0: if (retItem){ andre@0: SECITEM_FreeItem(retItem, PKIX_TRUE); andre@0: } andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_Cert_GetExtendedKeyUsage (see comments in pkix_pl_pki.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_Cert_GetExtendedKeyUsage( andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_List **pKeyUsage, /* list of PKIX_PL_OID */ andre@0: void *plContext) andre@0: { andre@0: CERTOidSequence *extKeyUsage = NULL; andre@0: CERTCertificate *nssCert = NULL; andre@0: PKIX_PL_OID *pkixOID = NULL; andre@0: PKIX_List *oidsList = NULL; andre@0: SECItem **oids = NULL; andre@0: SECItem encodedExtKeyUsage; andre@0: SECStatus rv; andre@0: andre@0: PKIX_ENTER(CERT, "PKIX_PL_Cert_GetExtendedKeyUsage"); andre@0: PKIX_NULLCHECK_THREE(cert, cert->nssCert, pKeyUsage); andre@0: andre@0: /* if we don't have a cached copy from before, we create one */ andre@0: if ((cert->extKeyUsages == NULL) && (!cert->extKeyUsagesAbsent)){ andre@0: andre@0: PKIX_OBJECT_LOCK(cert); andre@0: andre@0: if ((cert->extKeyUsages == NULL) && andre@0: (!cert->extKeyUsagesAbsent)){ andre@0: andre@0: nssCert = cert->nssCert; andre@0: andre@0: rv = CERT_FindCertExtension andre@0: (nssCert, SEC_OID_X509_EXT_KEY_USAGE, andre@0: &encodedExtKeyUsage); andre@0: if (rv != SECSuccess){ andre@0: cert->extKeyUsagesAbsent = PKIX_TRUE; andre@0: *pKeyUsage = NULL; andre@0: goto cleanup; andre@0: } andre@0: andre@0: extKeyUsage = andre@0: CERT_DecodeOidSequence(&encodedExtKeyUsage); andre@0: if (extKeyUsage == NULL){ andre@0: PKIX_ERROR(PKIX_CERTDECODEOIDSEQUENCEFAILED); andre@0: } andre@0: andre@0: PORT_Free(encodedExtKeyUsage.data); andre@0: andre@0: oids = extKeyUsage->oids; andre@0: andre@0: if (!oids){ andre@0: /* no extended key usage extensions found */ andre@0: cert->extKeyUsagesAbsent = PKIX_TRUE; andre@0: *pKeyUsage = NULL; andre@0: goto cleanup; andre@0: } andre@0: andre@0: PKIX_CHECK(PKIX_List_Create(&oidsList, plContext), andre@0: PKIX_LISTCREATEFAILED); andre@0: andre@0: while (*oids){ andre@0: SECItem *oid = *oids++; andre@0: andre@0: PKIX_CHECK(PKIX_PL_OID_CreateBySECItem andre@0: (oid, &pkixOID, plContext), andre@0: PKIX_OIDCREATEFAILED); andre@0: andre@0: PKIX_CHECK(PKIX_List_AppendItem andre@0: (oidsList, andre@0: (PKIX_PL_Object *)pkixOID, andre@0: plContext), andre@0: PKIX_LISTAPPENDITEMFAILED); andre@0: PKIX_DECREF(pkixOID); andre@0: } andre@0: andre@0: PKIX_CHECK(PKIX_List_SetImmutable andre@0: (oidsList, plContext), andre@0: PKIX_LISTSETIMMUTABLEFAILED); andre@0: andre@0: /* save a cached copy in case it is asked for again */ andre@0: cert->extKeyUsages = oidsList; andre@0: oidsList = NULL; andre@0: } andre@0: andre@0: PKIX_OBJECT_UNLOCK(cert); andre@0: } andre@0: andre@0: PKIX_INCREF(cert->extKeyUsages); andre@0: *pKeyUsage = cert->extKeyUsages; andre@0: andre@0: cleanup: andre@0: PKIX_OBJECT_UNLOCK(lockedObject); andre@0: andre@0: PKIX_DECREF(pkixOID); andre@0: PKIX_DECREF(oidsList); andre@0: CERT_DestroyOidSequence(extKeyUsage); andre@0: andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_Cert_GetBasicConstraints andre@0: * (see comments in pkix_pl_pki.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_Cert_GetBasicConstraints( andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_PL_CertBasicConstraints **pBasicConstraints, andre@0: void *plContext) andre@0: { andre@0: CERTCertificate *nssCert = NULL; andre@0: CERTBasicConstraints nssBasicConstraint; andre@0: SECStatus rv; andre@0: PKIX_PL_CertBasicConstraints *basic; andre@0: PKIX_Int32 pathLen = 0; andre@0: PKIX_Boolean isCA = PKIX_FALSE; andre@0: enum { andre@0: realBC, synthBC, absentBC andre@0: } constraintSource = absentBC; andre@0: andre@0: PKIX_ENTER(CERT, "PKIX_PL_Cert_GetBasicConstraints"); andre@0: PKIX_NULLCHECK_THREE(cert, cert->nssCert, pBasicConstraints); andre@0: andre@0: /* if we don't have a cached copy from before, we create one */ andre@0: if ((cert->certBasicConstraints == NULL) && andre@0: (!cert->basicConstraintsAbsent)) { andre@0: andre@0: PKIX_OBJECT_LOCK(cert); andre@0: andre@0: if ((cert->certBasicConstraints == NULL) && andre@0: (!cert->basicConstraintsAbsent)) { andre@0: andre@0: nssCert = cert->nssCert; andre@0: andre@0: PKIX_CERT_DEBUG( andre@0: "\t\tCalling Cert_FindBasicConstraintExten\n"); andre@0: rv = CERT_FindBasicConstraintExten andre@0: (nssCert, &nssBasicConstraint); andre@0: if (rv == SECSuccess) { andre@0: constraintSource = realBC; andre@0: } andre@0: andre@0: if (constraintSource == absentBC) { andre@0: /* can we deduce it's a CA and create a andre@0: synthetic constraint? andre@0: */ andre@0: CERTCertTrust trust; andre@0: rv = CERT_GetCertTrust(nssCert, &trust); andre@0: if (rv == SECSuccess) { andre@0: int anyWantedFlag = CERTDB_TRUSTED_CA | CERTDB_VALID_CA; andre@0: if ((trust.sslFlags & anyWantedFlag) andre@0: || (trust.emailFlags & anyWantedFlag) andre@0: || (trust.objectSigningFlags & anyWantedFlag)) { andre@0: andre@0: constraintSource = synthBC; andre@0: } andre@0: } andre@0: } andre@0: andre@0: if (constraintSource == absentBC) { andre@0: cert->basicConstraintsAbsent = PKIX_TRUE; andre@0: *pBasicConstraints = NULL; andre@0: goto cleanup; andre@0: } andre@0: } andre@0: andre@0: if (constraintSource == synthBC) { andre@0: isCA = PKIX_TRUE; andre@0: pathLen = PKIX_UNLIMITED_PATH_CONSTRAINT; andre@0: } else { andre@0: isCA = (nssBasicConstraint.isCA)?PKIX_TRUE:PKIX_FALSE; andre@0: andre@0: /* The pathLen has meaning only for CAs */ andre@0: if (isCA) { andre@0: if (CERT_UNLIMITED_PATH_CONSTRAINT == andre@0: nssBasicConstraint.pathLenConstraint) { andre@0: pathLen = PKIX_UNLIMITED_PATH_CONSTRAINT; andre@0: } else { andre@0: pathLen = nssBasicConstraint.pathLenConstraint; andre@0: } andre@0: } andre@0: } andre@0: andre@0: PKIX_CHECK(pkix_pl_CertBasicConstraints_Create andre@0: (isCA, pathLen, &basic, plContext), andre@0: PKIX_CERTBASICCONSTRAINTSCREATEFAILED); andre@0: andre@0: /* save a cached copy in case it is asked for again */ andre@0: cert->certBasicConstraints = basic; andre@0: } andre@0: andre@0: PKIX_INCREF(cert->certBasicConstraints); andre@0: *pBasicConstraints = cert->certBasicConstraints; andre@0: andre@0: cleanup: andre@0: PKIX_OBJECT_UNLOCK(lockedObject); andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_Cert_GetPolicyInformation andre@0: * (see comments in pkix_pl_pki.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_Cert_GetPolicyInformation( andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_List **pPolicyInfo, andre@0: void *plContext) andre@0: { andre@0: PKIX_List *policyList = NULL; andre@0: andre@0: PKIX_ENTER(CERT, "PKIX_PL_Cert_GetPolicyInformation"); andre@0: PKIX_NULLCHECK_THREE(cert, cert->nssCert, pPolicyInfo); andre@0: andre@0: /* if we don't have a cached copy from before, we create one */ andre@0: if ((cert->certPolicyInfos == NULL) && andre@0: (!cert->policyInfoAbsent)) { andre@0: andre@0: PKIX_OBJECT_LOCK(cert); andre@0: andre@0: if ((cert->certPolicyInfos == NULL) && andre@0: (!cert->policyInfoAbsent)) { andre@0: andre@0: PKIX_CHECK(pkix_pl_Cert_DecodePolicyInfo andre@0: (cert->nssCert, &policyList, plContext), andre@0: PKIX_CERTDECODEPOLICYINFOFAILED); andre@0: andre@0: if (!policyList) { andre@0: cert->policyInfoAbsent = PKIX_TRUE; andre@0: *pPolicyInfo = NULL; andre@0: goto cleanup; andre@0: } andre@0: } andre@0: andre@0: PKIX_OBJECT_UNLOCK(cert); andre@0: andre@0: /* save a cached copy in case it is asked for again */ andre@0: cert->certPolicyInfos = policyList; andre@0: policyList = NULL; andre@0: } andre@0: andre@0: PKIX_INCREF(cert->certPolicyInfos); andre@0: *pPolicyInfo = cert->certPolicyInfos; andre@0: andre@0: cleanup: andre@0: PKIX_OBJECT_UNLOCK(lockedObject); andre@0: andre@0: PKIX_DECREF(policyList); andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_Cert_GetPolicyMappings (see comments in pkix_pl_pki.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_Cert_GetPolicyMappings( andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_List **pPolicyMappings, /* list of PKIX_PL_CertPolicyMap */ andre@0: void *plContext) andre@0: { andre@0: PKIX_List *policyMappings = NULL; /* list of PKIX_PL_CertPolicyMap */ andre@0: andre@0: PKIX_ENTER(CERT, "PKIX_PL_Cert_GetPolicyMappings"); andre@0: PKIX_NULLCHECK_THREE(cert, cert->nssCert, pPolicyMappings); andre@0: andre@0: /* if we don't have a cached copy from before, we create one */ andre@0: if (!(cert->certPolicyMappings) && !(cert->policyMappingsAbsent)) { andre@0: andre@0: PKIX_OBJECT_LOCK(cert); andre@0: andre@0: if (!(cert->certPolicyMappings) && andre@0: !(cert->policyMappingsAbsent)) { andre@0: andre@0: PKIX_CHECK(pkix_pl_Cert_DecodePolicyMapping andre@0: (cert->nssCert, &policyMappings, plContext), andre@0: PKIX_CERTDECODEPOLICYMAPPINGFAILED); andre@0: andre@0: if (!policyMappings) { andre@0: cert->policyMappingsAbsent = PKIX_TRUE; andre@0: *pPolicyMappings = NULL; andre@0: goto cleanup; andre@0: } andre@0: } andre@0: andre@0: PKIX_OBJECT_UNLOCK(cert); andre@0: andre@0: /* save a cached copy in case it is asked for again */ andre@0: cert->certPolicyMappings = policyMappings; andre@0: policyMappings = NULL; andre@0: } andre@0: andre@0: PKIX_INCREF(cert->certPolicyMappings); andre@0: *pPolicyMappings = cert->certPolicyMappings; andre@0: andre@0: cleanup: andre@0: PKIX_OBJECT_UNLOCK(lockedObject); andre@0: andre@0: PKIX_DECREF(policyMappings); andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_Cert_GetRequireExplicitPolicy andre@0: * (see comments in pkix_pl_pki.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_Cert_GetRequireExplicitPolicy( andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_Int32 *pSkipCerts, andre@0: void *plContext) andre@0: { andre@0: PKIX_Int32 explicitPolicySkipCerts = 0; andre@0: PKIX_Int32 inhibitMappingSkipCerts = 0; andre@0: andre@0: PKIX_ENTER(CERT, "PKIX_PL_Cert_GetRequireExplicitPolicy"); andre@0: PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSkipCerts); andre@0: andre@0: if (!(cert->policyConstraintsProcessed)) { andre@0: PKIX_OBJECT_LOCK(cert); andre@0: andre@0: if (!(cert->policyConstraintsProcessed)) { andre@0: andre@0: /* andre@0: * If we can't process it now, we probably will be andre@0: * unable to process it later. Set the default value. andre@0: */ andre@0: cert->policyConstraintsProcessed = PKIX_TRUE; andre@0: cert->policyConstraintsExplicitPolicySkipCerts = -1; andre@0: cert->policyConstraintsInhibitMappingSkipCerts = -1; andre@0: andre@0: PKIX_CHECK(pkix_pl_Cert_DecodePolicyConstraints andre@0: (cert->nssCert, andre@0: &explicitPolicySkipCerts, andre@0: &inhibitMappingSkipCerts, andre@0: plContext), andre@0: PKIX_CERTDECODEPOLICYCONSTRAINTSFAILED); andre@0: andre@0: cert->policyConstraintsExplicitPolicySkipCerts = andre@0: explicitPolicySkipCerts; andre@0: cert->policyConstraintsInhibitMappingSkipCerts = andre@0: inhibitMappingSkipCerts; andre@0: } andre@0: andre@0: PKIX_OBJECT_UNLOCK(cert); andre@0: } andre@0: andre@0: *pSkipCerts = cert->policyConstraintsExplicitPolicySkipCerts; andre@0: andre@0: cleanup: andre@0: PKIX_OBJECT_UNLOCK(lockedObject); andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_Cert_GetPolicyMappingInhibited andre@0: * (see comments in pkix_pl_pki.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_Cert_GetPolicyMappingInhibited( andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_Int32 *pSkipCerts, andre@0: void *plContext) andre@0: { andre@0: PKIX_Int32 explicitPolicySkipCerts = 0; andre@0: PKIX_Int32 inhibitMappingSkipCerts = 0; andre@0: andre@0: PKIX_ENTER(CERT, "PKIX_PL_Cert_GetPolicyMappingInhibited"); andre@0: PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSkipCerts); andre@0: andre@0: if (!(cert->policyConstraintsProcessed)) { andre@0: PKIX_OBJECT_LOCK(cert); andre@0: andre@0: if (!(cert->policyConstraintsProcessed)) { andre@0: andre@0: /* andre@0: * If we can't process it now, we probably will be andre@0: * unable to process it later. Set the default value. andre@0: */ andre@0: cert->policyConstraintsProcessed = PKIX_TRUE; andre@0: cert->policyConstraintsExplicitPolicySkipCerts = -1; andre@0: cert->policyConstraintsInhibitMappingSkipCerts = -1; andre@0: andre@0: PKIX_CHECK(pkix_pl_Cert_DecodePolicyConstraints andre@0: (cert->nssCert, andre@0: &explicitPolicySkipCerts, andre@0: &inhibitMappingSkipCerts, andre@0: plContext), andre@0: PKIX_CERTDECODEPOLICYCONSTRAINTSFAILED); andre@0: andre@0: cert->policyConstraintsExplicitPolicySkipCerts = andre@0: explicitPolicySkipCerts; andre@0: cert->policyConstraintsInhibitMappingSkipCerts = andre@0: inhibitMappingSkipCerts; andre@0: } andre@0: andre@0: PKIX_OBJECT_UNLOCK(cert); andre@0: } andre@0: andre@0: *pSkipCerts = cert->policyConstraintsInhibitMappingSkipCerts; andre@0: andre@0: cleanup: andre@0: PKIX_OBJECT_UNLOCK(lockedObject); andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_Cert_GetInhibitAnyPolicy (see comments in pkix_pl_pki.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_Cert_GetInhibitAnyPolicy( andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_Int32 *pSkipCerts, andre@0: void *plContext) andre@0: { andre@0: PKIX_Int32 skipCerts = 0; andre@0: andre@0: PKIX_ENTER(CERT, "PKIX_PL_Cert_GetInhibitAnyPolicy"); andre@0: PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSkipCerts); andre@0: andre@0: if (!(cert->inhibitAnyPolicyProcessed)) { andre@0: andre@0: PKIX_OBJECT_LOCK(cert); andre@0: andre@0: if (!(cert->inhibitAnyPolicyProcessed)) { andre@0: andre@0: /* andre@0: * If we can't process it now, we probably will be andre@0: * unable to process it later. Set the default value. andre@0: */ andre@0: cert->inhibitAnyPolicyProcessed = PKIX_TRUE; andre@0: cert->inhibitAnySkipCerts = -1; andre@0: andre@0: PKIX_CHECK(pkix_pl_Cert_DecodeInhibitAnyPolicy andre@0: (cert->nssCert, &skipCerts, plContext), andre@0: PKIX_CERTDECODEINHIBITANYPOLICYFAILED); andre@0: andre@0: cert->inhibitAnySkipCerts = skipCerts; andre@0: } andre@0: andre@0: PKIX_OBJECT_UNLOCK(cert); andre@0: } andre@0: andre@0: cleanup: andre@0: PKIX_OBJECT_UNLOCK(lockedObject); andre@0: *pSkipCerts = cert->inhibitAnySkipCerts; andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_Cert_AreCertPoliciesCritical andre@0: * (see comments in pkix_pl_pki.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_Cert_AreCertPoliciesCritical( andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_Boolean *pCritical, andre@0: void *plContext) andre@0: { andre@0: PKIX_Boolean criticality = PKIX_FALSE; andre@0: andre@0: PKIX_ENTER(CERT, "PKIX_PL_Cert_AreCertPoliciesCritical"); andre@0: PKIX_NULLCHECK_TWO(cert, pCritical); andre@0: andre@0: PKIX_CHECK(pkix_pl_Cert_IsExtensionCritical( andre@0: cert, andre@0: SEC_OID_X509_CERTIFICATE_POLICIES, andre@0: &criticality, andre@0: plContext), andre@0: PKIX_CERTISEXTENSIONCRITICALFAILED); andre@0: andre@0: *pCritical = criticality; andre@0: andre@0: cleanup: andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_Cert_VerifySignature (see comments in pkix_pl_pki.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_Cert_VerifySignature( andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_PL_PublicKey *pubKey, andre@0: void *plContext) andre@0: { andre@0: CERTCertificate *nssCert = NULL; andre@0: SECKEYPublicKey *nssPubKey = NULL; andre@0: CERTSignedData *tbsCert = NULL; andre@0: PKIX_PL_Cert *cachedCert = NULL; andre@0: PKIX_Error *verifySig = NULL; andre@0: PKIX_Error *cachedSig = NULL; andre@0: SECStatus status; andre@0: PKIX_Boolean certEqual = PKIX_FALSE; andre@0: PKIX_Boolean certInHash = PKIX_FALSE; andre@0: void* wincx = NULL; andre@0: andre@0: PKIX_ENTER(CERT, "PKIX_PL_Cert_VerifySignature"); andre@0: PKIX_NULLCHECK_THREE(cert, cert->nssCert, pubKey); andre@0: andre@0: verifySig = PKIX_PL_HashTable_Lookup andre@0: (cachedCertSigTable, andre@0: (PKIX_PL_Object *) pubKey, andre@0: (PKIX_PL_Object **) &cachedCert, andre@0: plContext); andre@0: andre@0: if (cachedCert != NULL && verifySig == NULL) { andre@0: /* Cached Signature Table lookup succeed */ andre@0: PKIX_EQUALS(cert, cachedCert, &certEqual, plContext, andre@0: PKIX_OBJECTEQUALSFAILED); andre@0: if (certEqual == PKIX_TRUE) { andre@0: goto cleanup; andre@0: } andre@0: /* Different PubKey may hash to same value, skip add */ andre@0: certInHash = PKIX_TRUE; andre@0: } andre@0: andre@0: nssCert = cert->nssCert; andre@0: tbsCert = &nssCert->signatureWrap; andre@0: andre@0: PKIX_CERT_DEBUG("\t\tCalling SECKEY_ExtractPublicKey).\n"); andre@0: nssPubKey = SECKEY_ExtractPublicKey(pubKey->nssSPKI); andre@0: if (!nssPubKey){ andre@0: PKIX_ERROR(PKIX_SECKEYEXTRACTPUBLICKEYFAILED); andre@0: } andre@0: andre@0: PKIX_CERT_DEBUG("\t\tCalling CERT_VerifySignedDataWithPublicKey).\n"); andre@0: andre@0: PKIX_CHECK(pkix_pl_NssContext_GetWincx andre@0: ((PKIX_PL_NssContext *)plContext, &wincx), andre@0: PKIX_NSSCONTEXTGETWINCXFAILED); andre@0: andre@0: status = CERT_VerifySignedDataWithPublicKey(tbsCert, nssPubKey, wincx); andre@0: andre@0: if (status != SECSuccess) { andre@0: if (PORT_GetError() != SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED) { andre@0: PORT_SetError(SEC_ERROR_BAD_SIGNATURE); andre@0: } andre@0: PKIX_ERROR(PKIX_SIGNATUREDIDNOTVERIFYWITHTHEPUBLICKEY); andre@0: } andre@0: andre@0: if (certInHash == PKIX_FALSE) { andre@0: cachedSig = PKIX_PL_HashTable_Add andre@0: (cachedCertSigTable, andre@0: (PKIX_PL_Object *) pubKey, andre@0: (PKIX_PL_Object *) cert, andre@0: plContext); andre@0: andre@0: if (cachedSig != NULL) { andre@0: PKIX_DEBUG("PKIX_PL_HashTable_Add skipped: entry existed\n"); andre@0: } andre@0: } andre@0: andre@0: cleanup: andre@0: if (nssPubKey){ andre@0: PKIX_CERT_DEBUG("\t\tCalling SECKEY_DestroyPublicKey).\n"); andre@0: SECKEY_DestroyPublicKey(nssPubKey); andre@0: } andre@0: andre@0: PKIX_DECREF(cachedCert); andre@0: PKIX_DECREF(verifySig); andre@0: PKIX_DECREF(cachedSig); andre@0: andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_Cert_CheckValidity (see comments in pkix_pl_pki.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_Cert_CheckValidity( andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_PL_Date *date, andre@0: void *plContext) andre@0: { andre@0: SECCertTimeValidity val; andre@0: PRTime timeToCheck; andre@0: PKIX_Boolean allowOverride; andre@0: SECCertificateUsage requiredUsages; andre@0: andre@0: PKIX_ENTER(CERT, "PKIX_PL_Cert_CheckValidity"); andre@0: PKIX_NULLCHECK_ONE(cert); andre@0: andre@0: /* if the caller supplies a date, we use it; else, use current time */ andre@0: if (date != NULL){ andre@0: PKIX_CHECK(pkix_pl_Date_GetPRTime andre@0: (date, &timeToCheck, plContext), andre@0: PKIX_DATEGETPRTIMEFAILED); andre@0: } else { andre@0: timeToCheck = PR_Now(); andre@0: } andre@0: andre@0: requiredUsages = ((PKIX_PL_NssContext*)plContext)->certificateUsage; andre@0: allowOverride = andre@0: (PRBool)((requiredUsages & certificateUsageSSLServer) || andre@0: (requiredUsages & certificateUsageSSLServerWithStepUp)); andre@0: val = CERT_CheckCertValidTimes(cert->nssCert, timeToCheck, allowOverride); andre@0: if (val != secCertTimeValid){ andre@0: PKIX_ERROR(PKIX_CERTCHECKCERTVALIDTIMESFAILED); andre@0: } andre@0: andre@0: cleanup: andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_Cert_GetValidityNotAfter (see comments in pkix_pl_pki.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_Cert_GetValidityNotAfter( andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_PL_Date **pDate, andre@0: void *plContext) andre@0: { andre@0: PRTime prtime; andre@0: SECStatus rv = SECFailure; andre@0: andre@0: PKIX_ENTER(CERT, "PKIX_PL_Cert_GetValidityNotAfter"); andre@0: PKIX_NULLCHECK_TWO(cert, pDate); andre@0: andre@0: PKIX_DATE_DEBUG("\t\tCalling DER_DecodeTimeChoice).\n"); andre@0: rv = DER_DecodeTimeChoice(&prtime, &(cert->nssCert->validity.notAfter)); andre@0: if (rv != SECSuccess){ andre@0: PKIX_ERROR(PKIX_DERDECODETIMECHOICEFAILED); andre@0: } andre@0: andre@0: PKIX_CHECK(pkix_pl_Date_CreateFromPRTime andre@0: (prtime, pDate, plContext), andre@0: PKIX_DATECREATEFROMPRTIMEFAILED); andre@0: andre@0: cleanup: andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_Cert_VerifyCertAndKeyType (see comments in pkix_pl_pki.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_Cert_VerifyCertAndKeyType( andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_Boolean isChainCert, andre@0: void *plContext) andre@0: { andre@0: PKIX_PL_CertBasicConstraints *basicConstraints = NULL; andre@0: SECCertificateUsage certificateUsage; andre@0: SECCertUsage certUsage = 0; andre@0: unsigned int requiredKeyUsage; andre@0: unsigned int requiredCertType; andre@0: unsigned int certType; andre@0: SECStatus rv = SECSuccess; andre@0: andre@0: PKIX_ENTER(CERT, "PKIX_PL_Cert_VerifyCertType"); andre@0: PKIX_NULLCHECK_TWO(cert, plContext); andre@0: andre@0: certificateUsage = ((PKIX_PL_NssContext*)plContext)->certificateUsage; andre@0: andre@0: /* ensure we obtained a single usage bit only */ andre@0: PORT_Assert(!(certificateUsage & (certificateUsage - 1))); andre@0: andre@0: /* convert SECertificateUsage (bit mask) to SECCertUsage (enum) */ andre@0: while (0 != (certificateUsage = certificateUsage >> 1)) { certUsage++; } andre@0: andre@0: /* check key usage and netscape cert type */ andre@0: cert_GetCertType(cert->nssCert); andre@0: certType = cert->nssCert->nsCertType; andre@0: if (isChainCert || andre@0: (certUsage != certUsageVerifyCA && certUsage != certUsageAnyCA)) { andre@0: rv = CERT_KeyUsageAndTypeForCertUsage(certUsage, isChainCert, andre@0: &requiredKeyUsage, andre@0: &requiredCertType); andre@0: if (rv == SECFailure) { andre@0: PKIX_ERROR(PKIX_UNSUPPORTEDCERTUSAGE); andre@0: } andre@0: } else { andre@0: /* use this key usage and cert type for certUsageAnyCA and andre@0: * certUsageVerifyCA. */ andre@0: requiredKeyUsage = KU_KEY_CERT_SIGN; andre@0: requiredCertType = NS_CERT_TYPE_CA; andre@0: } andre@0: if (CERT_CheckKeyUsage(cert->nssCert, requiredKeyUsage) != SECSuccess) { andre@0: PKIX_ERROR(PKIX_CERTCHECKKEYUSAGEFAILED); andre@0: } andre@0: if (!(certType & requiredCertType)) { andre@0: PKIX_ERROR(PKIX_CERTCHECKCERTTYPEFAILED); andre@0: } andre@0: cleanup: andre@0: PKIX_DECREF(basicConstraints); andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_Cert_VerifyKeyUsage (see comments in pkix_pl_pki.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_Cert_VerifyKeyUsage( andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_UInt32 keyUsage, andre@0: void *plContext) andre@0: { andre@0: CERTCertificate *nssCert = NULL; andre@0: PKIX_UInt32 nssKeyUsage = 0; andre@0: SECStatus status; andre@0: andre@0: PKIX_ENTER(CERT, "PKIX_PL_Cert_VerifyKeyUsage"); andre@0: PKIX_NULLCHECK_TWO(cert, cert->nssCert); andre@0: andre@0: nssCert = cert->nssCert; andre@0: andre@0: /* if cert doesn't have keyUsage extension, all keyUsages are valid */ andre@0: if (!nssCert->keyUsagePresent){ andre@0: goto cleanup; andre@0: } andre@0: andre@0: if (keyUsage & PKIX_DIGITAL_SIGNATURE){ andre@0: nssKeyUsage = nssKeyUsage | KU_DIGITAL_SIGNATURE; andre@0: } andre@0: andre@0: if (keyUsage & PKIX_NON_REPUDIATION){ andre@0: nssKeyUsage = nssKeyUsage | KU_NON_REPUDIATION; andre@0: } andre@0: andre@0: if (keyUsage & PKIX_KEY_ENCIPHERMENT){ andre@0: nssKeyUsage = nssKeyUsage | KU_KEY_ENCIPHERMENT; andre@0: } andre@0: andre@0: if (keyUsage & PKIX_DATA_ENCIPHERMENT){ andre@0: nssKeyUsage = nssKeyUsage | KU_DATA_ENCIPHERMENT; andre@0: } andre@0: andre@0: if (keyUsage & PKIX_KEY_AGREEMENT){ andre@0: nssKeyUsage = nssKeyUsage | KU_KEY_AGREEMENT; andre@0: } andre@0: andre@0: if (keyUsage & PKIX_KEY_CERT_SIGN){ andre@0: nssKeyUsage = nssKeyUsage | KU_KEY_CERT_SIGN; andre@0: } andre@0: andre@0: if (keyUsage & PKIX_CRL_SIGN){ andre@0: nssKeyUsage = nssKeyUsage | KU_CRL_SIGN; andre@0: } andre@0: andre@0: if (keyUsage & PKIX_ENCIPHER_ONLY){ andre@0: nssKeyUsage = nssKeyUsage | 0x01; andre@0: } andre@0: andre@0: if (keyUsage & PKIX_DECIPHER_ONLY){ andre@0: /* XXX we should support this once it is fixed in NSS */ andre@0: PKIX_ERROR(PKIX_DECIPHERONLYKEYUSAGENOTSUPPORTED); andre@0: } andre@0: andre@0: status = CERT_CheckKeyUsage(nssCert, nssKeyUsage); andre@0: if (status != SECSuccess) { andre@0: PKIX_ERROR(PKIX_CERTCHECKKEYUSAGEFAILED); andre@0: } andre@0: andre@0: cleanup: andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_Cert_GetNameConstraints andre@0: * (see comments in pkix_pl_pki.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_Cert_GetNameConstraints( andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_PL_CertNameConstraints **pNameConstraints, andre@0: void *plContext) andre@0: { andre@0: PKIX_PL_CertNameConstraints *nameConstraints = NULL; andre@0: andre@0: PKIX_ENTER(CERT, "PKIX_PL_Cert_GetNameConstraints"); andre@0: PKIX_NULLCHECK_THREE(cert, cert->nssCert, pNameConstraints); andre@0: andre@0: /* if we don't have a cached copy from before, we create one */ andre@0: if (cert->nameConstraints == NULL && !cert->nameConstraintsAbsent) { andre@0: andre@0: PKIX_OBJECT_LOCK(cert); andre@0: andre@0: if (cert->nameConstraints == NULL && andre@0: !cert->nameConstraintsAbsent) { andre@0: andre@0: PKIX_CHECK(pkix_pl_CertNameConstraints_Create andre@0: (cert->nssCert, &nameConstraints, plContext), andre@0: PKIX_CERTNAMECONSTRAINTSCREATEFAILED); andre@0: andre@0: if (nameConstraints == NULL) { andre@0: cert->nameConstraintsAbsent = PKIX_TRUE; andre@0: } andre@0: andre@0: cert->nameConstraints = nameConstraints; andre@0: } andre@0: andre@0: PKIX_OBJECT_UNLOCK(cert); andre@0: andre@0: } andre@0: andre@0: PKIX_INCREF(cert->nameConstraints); andre@0: andre@0: *pNameConstraints = cert->nameConstraints; andre@0: andre@0: cleanup: andre@0: PKIX_OBJECT_UNLOCK(lockedObject); andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_Cert_CheckNameConstraints andre@0: * (see comments in pkix_pl_pki.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_Cert_CheckNameConstraints( andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_PL_CertNameConstraints *nameConstraints, andre@0: PKIX_Boolean treatCommonNameAsDNSName, andre@0: void *plContext) andre@0: { andre@0: PKIX_Boolean checkPass = PKIX_TRUE; andre@0: CERTGeneralName *nssSubjectNames = NULL; andre@0: PLArenaPool *arena = NULL; andre@0: andre@0: PKIX_ENTER(CERT, "PKIX_PL_Cert_CheckNameConstraints"); andre@0: PKIX_NULLCHECK_ONE(cert); andre@0: andre@0: if (nameConstraints != NULL) { andre@0: andre@0: arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); andre@0: if (arena == NULL) { andre@0: PKIX_ERROR(PKIX_OUTOFMEMORY); andre@0: } andre@0: andre@0: /* This NSS call returns Subject Alt Names. If andre@0: * treatCommonNameAsDNSName is true, it also returns the andre@0: * Subject Common Name andre@0: */ andre@0: PKIX_CERT_DEBUG andre@0: ("\t\tCalling CERT_GetConstrainedCertificateNames\n"); andre@0: nssSubjectNames = CERT_GetConstrainedCertificateNames andre@0: (cert->nssCert, arena, treatCommonNameAsDNSName); andre@0: andre@0: PKIX_CHECK(pkix_pl_CertNameConstraints_CheckNameSpaceNssNames andre@0: (nssSubjectNames, andre@0: nameConstraints, andre@0: &checkPass, andre@0: plContext), andre@0: PKIX_CERTNAMECONSTRAINTSCHECKNAMESPACENSSNAMESFAILED); andre@0: andre@0: if (checkPass != PKIX_TRUE) { andre@0: PKIX_ERROR(PKIX_CERTFAILEDNAMECONSTRAINTSCHECKING); andre@0: } andre@0: } andre@0: andre@0: cleanup: andre@0: if (arena){ andre@0: PORT_FreeArena(arena, PR_FALSE); andre@0: } andre@0: andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_Cert_MergeNameConstraints andre@0: * (see comments in pkix_pl_pki.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_Cert_MergeNameConstraints( andre@0: PKIX_PL_CertNameConstraints *firstNC, andre@0: PKIX_PL_CertNameConstraints *secondNC, andre@0: PKIX_PL_CertNameConstraints **pResultNC, andre@0: void *plContext) andre@0: { andre@0: PKIX_PL_CertNameConstraints *mergedNC = NULL; andre@0: andre@0: PKIX_ENTER(CERT, "PKIX_PL_Cert_MergeNameConstraints"); andre@0: PKIX_NULLCHECK_TWO(firstNC, pResultNC); andre@0: andre@0: if (secondNC == NULL) { andre@0: andre@0: PKIX_INCREF(firstNC); andre@0: *pResultNC = firstNC; andre@0: andre@0: goto cleanup; andre@0: } andre@0: andre@0: PKIX_CHECK(pkix_pl_CertNameConstraints_Merge andre@0: (firstNC, secondNC, &mergedNC, plContext), andre@0: PKIX_CERTNAMECONSTRAINTSMERGEFAILED); andre@0: andre@0: *pResultNC = mergedNC; andre@0: andre@0: cleanup: andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * Find out the state of the NSS trust bits for the requested usage. andre@0: * Returns SECFailure if the cert is explicitly distrusted. andre@0: * Returns SECSuccess if the cert can be used to form a chain (normal case), andre@0: * or it is explicitly trusted. The trusted bool is set to true if it is andre@0: * explicitly trusted. andre@0: */ andre@0: static SECStatus andre@0: pkix_pl_Cert_GetTrusted(void *plContext, andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_Boolean *trusted, andre@0: PKIX_Boolean isCA) andre@0: { andre@0: SECStatus rv; andre@0: CERTCertificate *nssCert = NULL; andre@0: SECCertUsage certUsage = 0; andre@0: SECCertificateUsage certificateUsage; andre@0: SECTrustType trustType; andre@0: unsigned int trustFlags; andre@0: unsigned int requiredFlags; andre@0: CERTCertTrust trust; andre@0: andre@0: *trusted = PKIX_FALSE; andre@0: andre@0: /* no key usage information */ andre@0: if (plContext == NULL) { andre@0: return SECSuccess; andre@0: } andre@0: andre@0: certificateUsage = ((PKIX_PL_NssContext*)plContext)->certificateUsage; andre@0: andre@0: /* ensure we obtained a single usage bit only */ andre@0: PORT_Assert(!(certificateUsage & (certificateUsage - 1))); andre@0: andre@0: /* convert SECertificateUsage (bit mask) to SECCertUsage (enum) */ andre@0: while (0 != (certificateUsage = certificateUsage >> 1)) { certUsage++; } andre@0: andre@0: nssCert = cert->nssCert; andre@0: andre@0: if (!isCA) { andre@0: PRBool prTrusted; andre@0: unsigned int failedFlags; andre@0: rv = cert_CheckLeafTrust(nssCert, certUsage, andre@0: &failedFlags, &prTrusted); andre@0: *trusted = (PKIX_Boolean) prTrusted; andre@0: return rv; andre@0: } andre@0: rv = CERT_TrustFlagsForCACertUsage(certUsage, &requiredFlags, andre@0: &trustType); andre@0: if (rv != SECSuccess) { andre@0: return SECSuccess; andre@0: } andre@0: andre@0: rv = CERT_GetCertTrust(nssCert, &trust); andre@0: if (rv != SECSuccess) { andre@0: return SECSuccess; andre@0: } andre@0: trustFlags = SEC_GET_TRUST_FLAGS(&trust, trustType); andre@0: /* normally trustTypeNone usages accept any of the given trust bits andre@0: * being on as acceptable. If any are distrusted (and none are trusted), andre@0: * then we will also distrust the cert */ andre@0: if ((trustFlags == 0) && (trustType == trustTypeNone)) { andre@0: trustFlags = trust.sslFlags | trust.emailFlags | andre@0: trust.objectSigningFlags; andre@0: } andre@0: if ((trustFlags & requiredFlags) == requiredFlags) { andre@0: *trusted = PKIX_TRUE; andre@0: return SECSuccess; andre@0: } andre@0: if ((trustFlags & CERTDB_TERMINAL_RECORD) && andre@0: ((trustFlags & (CERTDB_VALID_CA|CERTDB_TRUSTED)) == 0)) { andre@0: return SECFailure; andre@0: } andre@0: return SECSuccess; andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_Cert_IsCertTrusted andre@0: * (see comments in pkix_pl_pki.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_Cert_IsCertTrusted( andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_PL_TrustAnchorMode trustAnchorMode, andre@0: PKIX_Boolean *pTrusted, andre@0: void *plContext) andre@0: { andre@0: PKIX_CertStore_CheckTrustCallback trustCallback = NULL; andre@0: PKIX_Boolean trusted = PKIX_FALSE; andre@0: SECStatus rv = SECFailure; andre@0: andre@0: PKIX_ENTER(CERT, "PKIX_PL_Cert_IsCertTrusted"); andre@0: PKIX_NULLCHECK_TWO(cert, pTrusted); andre@0: andre@0: /* Call GetTrusted first to see if we are going to distrust the andre@0: * certificate */ andre@0: rv = pkix_pl_Cert_GetTrusted(plContext, cert, &trusted, PKIX_TRUE); andre@0: if (rv != SECSuccess) { andre@0: /* Failure means the cert is explicitly distrusted, andre@0: * let the next level know not to use it. */ andre@0: *pTrusted = PKIX_FALSE; andre@0: PKIX_ERROR(PKIX_CERTISCERTTRUSTEDFAILED); andre@0: } andre@0: andre@0: if (trustAnchorMode == PKIX_PL_TrustAnchorMode_Exclusive || andre@0: (trustAnchorMode == PKIX_PL_TrustAnchorMode_Additive && andre@0: cert->isUserTrustAnchor)) { andre@0: /* Use the trust anchor's |trusted| value */ andre@0: *pTrusted = cert->isUserTrustAnchor; andre@0: goto cleanup; andre@0: } andre@0: andre@0: /* no key usage information or store is not trusted */ andre@0: if (plContext == NULL || cert->store == NULL) { andre@0: *pTrusted = PKIX_FALSE; andre@0: goto cleanup; andre@0: } andre@0: andre@0: PKIX_CHECK(PKIX_CertStore_GetTrustCallback andre@0: (cert->store, &trustCallback, plContext), andre@0: PKIX_CERTSTOREGETTRUSTCALLBACKFAILED); andre@0: andre@0: PKIX_CHECK_ONLY_FATAL(trustCallback andre@0: (cert->store, cert, &trusted, plContext), andre@0: PKIX_CHECKTRUSTCALLBACKFAILED); andre@0: andre@0: /* allow trust store to override if we can trust the trust andre@0: * bits */ andre@0: if (PKIX_ERROR_RECEIVED || (trusted == PKIX_FALSE)) { andre@0: *pTrusted = PKIX_FALSE; andre@0: goto cleanup; andre@0: } andre@0: andre@0: *pTrusted = trusted; andre@0: andre@0: cleanup: andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_Cert_IsLeafCertTrusted andre@0: * (see comments in pkix_pl_pki.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_Cert_IsLeafCertTrusted( andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_Boolean *pTrusted, andre@0: void *plContext) andre@0: { andre@0: SECStatus rv; andre@0: andre@0: PKIX_ENTER(CERT, "PKIX_PL_Cert_IsLeafCertTrusted"); andre@0: PKIX_NULLCHECK_TWO(cert, pTrusted); andre@0: andre@0: *pTrusted = PKIX_FALSE; andre@0: andre@0: rv = pkix_pl_Cert_GetTrusted(plContext, cert, pTrusted, PKIX_FALSE); andre@0: if (rv != SECSuccess) { andre@0: /* Failure means the cert is explicitly distrusted, andre@0: * let the next level know not to use it. */ andre@0: *pTrusted = PKIX_FALSE; andre@0: PKIX_ERROR(PKIX_CERTISCERTTRUSTEDFAILED); andre@0: } andre@0: andre@0: cleanup: andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* FUNCTION: PKIX_PL_Cert_SetAsTrustAnchor */ andre@0: PKIX_Error* andre@0: PKIX_PL_Cert_SetAsTrustAnchor(PKIX_PL_Cert *cert, andre@0: void *plContext) andre@0: { andre@0: PKIX_ENTER(CERT, "PKIX_PL_Cert_SetAsTrustAnchor"); andre@0: PKIX_NULLCHECK_ONE(cert); andre@0: andre@0: cert->isUserTrustAnchor = PKIX_TRUE; andre@0: andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_Cert_GetCacheFlag (see comments in pkix_pl_pki.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_Cert_GetCacheFlag( andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_Boolean *pCacheFlag, andre@0: void *plContext) andre@0: { andre@0: PKIX_ENTER(CERT, "PKIX_PL_Cert_GetCacheFlag"); andre@0: PKIX_NULLCHECK_TWO(cert, pCacheFlag); andre@0: andre@0: *pCacheFlag = cert->cacheFlag; andre@0: andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_Cert_SetCacheFlag (see comments in pkix_pl_pki.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_Cert_SetCacheFlag( andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_Boolean cacheFlag, andre@0: void *plContext) andre@0: { andre@0: PKIX_ENTER(CERT, "PKIX_PL_Cert_SetCacheFlag"); andre@0: PKIX_NULLCHECK_ONE(cert); andre@0: andre@0: cert->cacheFlag = cacheFlag; andre@0: andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_Cert_GetTrustCertStore (see comments in pkix_pl_pki.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_Cert_GetTrustCertStore( andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_CertStore **pTrustCertStore, andre@0: void *plContext) andre@0: { andre@0: PKIX_ENTER(CERT, "PKIX_PL_Cert_GetTrustCertStore"); andre@0: PKIX_NULLCHECK_TWO(cert, pTrustCertStore); andre@0: andre@0: PKIX_INCREF(cert->store); andre@0: *pTrustCertStore = cert->store; andre@0: andre@0: cleanup: andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_Cert_SetTrustCertStore (see comments in pkix_pl_pki.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_Cert_SetTrustCertStore( andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_CertStore *trustCertStore, andre@0: void *plContext) andre@0: { andre@0: PKIX_ENTER(CERT, "PKIX_PL_Cert_SetTrustCertStore"); andre@0: PKIX_NULLCHECK_TWO(cert, trustCertStore); andre@0: andre@0: PKIX_INCREF(trustCertStore); andre@0: cert->store = trustCertStore; andre@0: andre@0: cleanup: andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_Cert_GetAuthorityInfoAccess andre@0: * (see comments in pkix_pl_pki.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_Cert_GetAuthorityInfoAccess( andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_List **pAiaList, /* of PKIX_PL_InfoAccess */ andre@0: void *plContext) andre@0: { andre@0: PKIX_List *aiaList = NULL; /* of PKIX_PL_InfoAccess */ andre@0: SECItem *encodedAIA = NULL; andre@0: CERTAuthInfoAccess **aia = NULL; andre@0: PLArenaPool *arena = NULL; andre@0: SECStatus rv; andre@0: andre@0: PKIX_ENTER(CERT, "PKIX_PL_Cert_GetAuthorityInfoAccess"); andre@0: PKIX_NULLCHECK_THREE(cert, cert->nssCert, pAiaList); andre@0: andre@0: /* if we don't have a cached copy from before, we create one */ andre@0: if (cert->authorityInfoAccess == NULL) { andre@0: andre@0: PKIX_OBJECT_LOCK(cert); andre@0: andre@0: if (cert->authorityInfoAccess == NULL) { andre@0: andre@0: PKIX_PL_NSSCALLRV(CERT, encodedAIA, SECITEM_AllocItem, andre@0: (NULL, NULL, 0)); andre@0: andre@0: if (encodedAIA == NULL) { andre@0: PKIX_ERROR(PKIX_OUTOFMEMORY); andre@0: } andre@0: andre@0: PKIX_PL_NSSCALLRV(CERT, rv, CERT_FindCertExtension, andre@0: (cert->nssCert, andre@0: SEC_OID_X509_AUTH_INFO_ACCESS, andre@0: encodedAIA)); andre@0: andre@0: if (rv == SECFailure) { andre@0: goto cleanup; andre@0: } andre@0: andre@0: PKIX_PL_NSSCALLRV(CERT, arena, PORT_NewArena, andre@0: (DER_DEFAULT_CHUNKSIZE)); andre@0: andre@0: if (arena == NULL) { andre@0: PKIX_ERROR(PKIX_OUTOFMEMORY); andre@0: } andre@0: andre@0: PKIX_PL_NSSCALLRV andre@0: (CERT, aia, CERT_DecodeAuthInfoAccessExtension, andre@0: (arena, encodedAIA)); andre@0: andre@0: PKIX_CHECK(pkix_pl_InfoAccess_CreateList andre@0: (aia, &aiaList, plContext), andre@0: PKIX_INFOACCESSCREATELISTFAILED); andre@0: andre@0: cert->authorityInfoAccess = aiaList; andre@0: } andre@0: andre@0: PKIX_OBJECT_UNLOCK(cert); andre@0: } andre@0: andre@0: PKIX_INCREF(cert->authorityInfoAccess); andre@0: andre@0: *pAiaList = cert->authorityInfoAccess; andre@0: andre@0: cleanup: andre@0: PKIX_OBJECT_UNLOCK(lockedObject); andre@0: if (arena != NULL) { andre@0: PORT_FreeArena(arena, PR_FALSE); andre@0: } andre@0: andre@0: if (encodedAIA != NULL) { andre@0: SECITEM_FreeItem(encodedAIA, PR_TRUE); andre@0: } andre@0: andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* XXX Following defines belongs to NSS */ andre@0: static const unsigned char siaOIDString[] = {0x2b, 0x06, 0x01, 0x05, 0x05, andre@0: 0x07, 0x01, 0x0b}; andre@0: #define OI(x) { siDEROID, (unsigned char *)x, sizeof x } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_Cert_GetSubjectInfoAccess andre@0: * (see comments in pkix_pl_pki.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_Cert_GetSubjectInfoAccess( andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_List **pSiaList, /* of PKIX_PL_InfoAccess */ andre@0: void *plContext) andre@0: { andre@0: PKIX_List *siaList; /* of PKIX_PL_InfoAccess */ andre@0: SECItem siaOID = OI(siaOIDString); andre@0: SECItem *encodedSubjInfoAccess = NULL; andre@0: CERTAuthInfoAccess **subjInfoAccess = NULL; andre@0: PLArenaPool *arena = NULL; andre@0: SECStatus rv; andre@0: andre@0: PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectInfoAccess"); andre@0: PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSiaList); andre@0: andre@0: /* XXX andre@0: * Codes to deal with SubjectInfoAccess OID should be moved to andre@0: * NSS soon. I implemented them here so we don't touch NSS andre@0: * source tree, from JP's suggestion. andre@0: */ andre@0: andre@0: /* if we don't have a cached copy from before, we create one */ andre@0: if (cert->subjectInfoAccess == NULL) { andre@0: andre@0: PKIX_OBJECT_LOCK(cert); andre@0: andre@0: if (cert->subjectInfoAccess == NULL) { andre@0: andre@0: encodedSubjInfoAccess = SECITEM_AllocItem(NULL, NULL, 0); andre@0: if (encodedSubjInfoAccess == NULL) { andre@0: PKIX_ERROR(PKIX_OUTOFMEMORY); andre@0: } andre@0: andre@0: PKIX_CERT_DEBUG andre@0: ("\t\tCalling CERT_FindCertExtensionByOID).\n"); andre@0: rv = CERT_FindCertExtensionByOID andre@0: (cert->nssCert, &siaOID, encodedSubjInfoAccess); andre@0: andre@0: if (rv == SECFailure) { andre@0: goto cleanup; andre@0: } andre@0: andre@0: arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); andre@0: if (arena == NULL) { andre@0: PKIX_ERROR(PKIX_OUTOFMEMORY); andre@0: } andre@0: andre@0: /* XXX andre@0: * Decode Subject Information Access - andre@0: * since its type is the same as Authority Information andre@0: * Access, reuse the call. NSS- change name to avoid andre@0: * confusion. andre@0: */ andre@0: PKIX_CERT_DEBUG andre@0: ("\t\tCalling CERT_DecodeAuthInfoAccessExtension).\n"); andre@0: subjInfoAccess = CERT_DecodeAuthInfoAccessExtension andre@0: (arena, encodedSubjInfoAccess); andre@0: andre@0: PKIX_CHECK(pkix_pl_InfoAccess_CreateList andre@0: (subjInfoAccess, &siaList, plContext), andre@0: PKIX_INFOACCESSCREATELISTFAILED); andre@0: andre@0: cert->subjectInfoAccess = siaList; andre@0: andre@0: } andre@0: andre@0: PKIX_OBJECT_UNLOCK(cert); andre@0: } andre@0: andre@0: PKIX_INCREF(cert->subjectInfoAccess); andre@0: *pSiaList = cert->subjectInfoAccess; andre@0: andre@0: cleanup: andre@0: PKIX_OBJECT_UNLOCK(lockedObject); andre@0: if (arena != NULL) { andre@0: PORT_FreeArena(arena, PR_FALSE); andre@0: } andre@0: andre@0: if (encodedSubjInfoAccess != NULL) { andre@0: SECITEM_FreeItem(encodedSubjInfoAccess, PR_TRUE); andre@0: } andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_Cert_GetCrlDp andre@0: * (see comments in pkix_pl_pki.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_Cert_GetCrlDp( andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_List **pDpList, andre@0: void *plContext) andre@0: { andre@0: PKIX_UInt32 dpIndex = 0; andre@0: pkix_pl_CrlDp *dp = NULL; andre@0: CERTCrlDistributionPoints *dpoints = NULL; andre@0: andre@0: PKIX_ENTER(CERT, "PKIX_PL_Cert_GetCrlDp"); andre@0: PKIX_NULLCHECK_THREE(cert, cert->nssCert, pDpList); andre@0: andre@0: /* if we don't have a cached copy from before, we create one */ andre@0: if (cert->crldpList == NULL) { andre@0: PKIX_OBJECT_LOCK(cert); andre@0: if (cert->crldpList != NULL) { andre@0: goto cleanup; andre@0: } andre@0: PKIX_CHECK(PKIX_List_Create(&cert->crldpList, plContext), andre@0: PKIX_LISTCREATEFAILED); andre@0: dpoints = CERT_FindCRLDistributionPoints(cert->nssCert); andre@0: if (!dpoints || !dpoints->distPoints) { andre@0: goto cleanup; andre@0: } andre@0: for (;dpoints->distPoints[dpIndex];dpIndex++) { andre@0: PKIX_CHECK( andre@0: pkix_pl_CrlDp_Create(dpoints->distPoints[dpIndex], andre@0: &cert->nssCert->issuer, andre@0: &dp, plContext), andre@0: PKIX_CRLDPCREATEFAILED); andre@0: /* Create crldp list in reverse order in attempt to get andre@0: * to the whole crl first. */ andre@0: PKIX_CHECK( andre@0: PKIX_List_InsertItem(cert->crldpList, 0, andre@0: (PKIX_PL_Object*)dp, andre@0: plContext), andre@0: PKIX_LISTAPPENDITEMFAILED); andre@0: PKIX_DECREF(dp); andre@0: } andre@0: } andre@0: cleanup: andre@0: PKIX_INCREF(cert->crldpList); andre@0: *pDpList = cert->crldpList; andre@0: andre@0: PKIX_OBJECT_UNLOCK(lockedObject); andre@0: PKIX_DECREF(dp); andre@0: andre@0: PKIX_RETURN(CERT); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_Cert_GetCERTCertificate andre@0: * (see comments in pkix_pl_pki.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_Cert_GetCERTCertificate( andre@0: PKIX_PL_Cert *cert, andre@0: CERTCertificate **pnssCert, andre@0: void *plContext) andre@0: { andre@0: PKIX_ENTER(CERT, "PKIX_PL_Cert_GetNssCert"); andre@0: PKIX_NULLCHECK_TWO(cert, pnssCert); andre@0: andre@0: *pnssCert = CERT_DupCertificate(cert->nssCert); andre@0: andre@0: PKIX_RETURN(CERT); andre@0: }