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_trustanchor.c andre@0: * andre@0: * TrustAnchor Object Functions andre@0: * andre@0: */ andre@0: andre@0: #include "pkix_trustanchor.h" andre@0: andre@0: /* --Private-Functions-------------------------------------------- */ andre@0: andre@0: /* andre@0: * FUNCTION: pkix_TrustAnchor_Destroy andre@0: * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) andre@0: */ andre@0: static PKIX_Error * andre@0: pkix_TrustAnchor_Destroy( andre@0: PKIX_PL_Object *object, andre@0: void *plContext) andre@0: { andre@0: PKIX_TrustAnchor *anchor = NULL; andre@0: andre@0: PKIX_ENTER(TRUSTANCHOR, "pkix_TrustAnchor_Destroy"); andre@0: PKIX_NULLCHECK_ONE(object); andre@0: andre@0: /* Check that this object is a trust anchor */ andre@0: PKIX_CHECK(pkix_CheckType(object, PKIX_TRUSTANCHOR_TYPE, plContext), andre@0: PKIX_OBJECTNOTTRUSTANCHOR); andre@0: andre@0: anchor = (PKIX_TrustAnchor *)object; andre@0: andre@0: PKIX_DECREF(anchor->trustedCert); andre@0: PKIX_DECREF(anchor->caName); andre@0: PKIX_DECREF(anchor->caPubKey); andre@0: PKIX_DECREF(anchor->nameConstraints); andre@0: andre@0: cleanup: andre@0: andre@0: PKIX_RETURN(TRUSTANCHOR); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_TrustAnchor_Equals andre@0: * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h) andre@0: */ andre@0: static PKIX_Error * andre@0: pkix_TrustAnchor_Equals( andre@0: PKIX_PL_Object *first, andre@0: PKIX_PL_Object *second, andre@0: PKIX_Boolean *pResult, andre@0: void *plContext) andre@0: { andre@0: PKIX_UInt32 secondType; andre@0: PKIX_Boolean cmpResult; andre@0: PKIX_TrustAnchor *firstAnchor = NULL; andre@0: PKIX_TrustAnchor *secondAnchor = NULL; andre@0: PKIX_PL_Cert *firstCert = NULL; andre@0: PKIX_PL_Cert *secondCert = NULL; andre@0: andre@0: PKIX_ENTER(TRUSTANCHOR, "pkix_TrustAnchor_Equals"); andre@0: PKIX_NULLCHECK_THREE(first, second, pResult); andre@0: andre@0: PKIX_CHECK(pkix_CheckType(first, PKIX_TRUSTANCHOR_TYPE, plContext), andre@0: PKIX_FIRSTOBJECTNOTTRUSTANCHOR); andre@0: andre@0: PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext), andre@0: PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); andre@0: andre@0: *pResult = PKIX_FALSE; andre@0: andre@0: if (secondType != PKIX_TRUSTANCHOR_TYPE) goto cleanup; andre@0: andre@0: firstAnchor = (PKIX_TrustAnchor *)first; andre@0: secondAnchor = (PKIX_TrustAnchor *)second; andre@0: andre@0: firstCert = firstAnchor->trustedCert; andre@0: secondCert = secondAnchor->trustedCert; andre@0: andre@0: if ((firstCert && !secondCert) || (!firstCert && secondCert)){ andre@0: goto cleanup; andre@0: } andre@0: andre@0: if (firstCert && secondCert){ andre@0: PKIX_CHECK(PKIX_PL_Object_Equals andre@0: ((PKIX_PL_Object *)firstCert, andre@0: (PKIX_PL_Object *)secondCert, andre@0: &cmpResult, andre@0: plContext), andre@0: PKIX_OBJECTEQUALSFAILED); andre@0: } else { andre@0: PKIX_CHECK(PKIX_PL_Object_Equals andre@0: ((PKIX_PL_Object *)firstAnchor->caName, andre@0: (PKIX_PL_Object *)secondAnchor->caName, andre@0: &cmpResult, andre@0: plContext), andre@0: PKIX_OBJECTEQUALSFAILED); andre@0: andre@0: if (!cmpResult) goto cleanup; andre@0: andre@0: PKIX_CHECK(PKIX_PL_Object_Equals andre@0: ((PKIX_PL_Object *)firstAnchor->caPubKey, andre@0: (PKIX_PL_Object *)secondAnchor->caPubKey, andre@0: &cmpResult, andre@0: plContext), andre@0: PKIX_OBJECTEQUALSFAILED); andre@0: andre@0: if (!cmpResult) goto cleanup; andre@0: andre@0: PKIX_EQUALS andre@0: (firstAnchor->nameConstraints, andre@0: secondAnchor->nameConstraints, andre@0: &cmpResult, andre@0: plContext, andre@0: PKIX_OBJECTEQUALSFAILED); andre@0: andre@0: if (!cmpResult) goto cleanup; andre@0: andre@0: } andre@0: andre@0: *pResult = cmpResult; andre@0: andre@0: cleanup: andre@0: andre@0: PKIX_RETURN(TRUSTANCHOR); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_TrustAnchor_Hashcode andre@0: * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) andre@0: */ andre@0: static PKIX_Error * andre@0: pkix_TrustAnchor_Hashcode( andre@0: PKIX_PL_Object *object, andre@0: PKIX_UInt32 *pHashcode, andre@0: void *plContext) andre@0: { andre@0: PKIX_TrustAnchor *anchor = NULL; andre@0: PKIX_PL_Cert *cert = NULL; andre@0: PKIX_UInt32 hash = 0; andre@0: PKIX_UInt32 certHash = 0; andre@0: PKIX_UInt32 nameHash = 0; andre@0: PKIX_UInt32 pubKeyHash = 0; andre@0: PKIX_UInt32 ncHash = 0; andre@0: andre@0: PKIX_ENTER(TRUSTANCHOR, "pkix_TrustAnchor_Hashcode"); andre@0: PKIX_NULLCHECK_TWO(object, pHashcode); andre@0: andre@0: PKIX_CHECK(pkix_CheckType(object, PKIX_TRUSTANCHOR_TYPE, plContext), andre@0: PKIX_OBJECTNOTTRUSTANCHOR); andre@0: andre@0: anchor = (PKIX_TrustAnchor*)object; andre@0: cert = anchor->trustedCert; andre@0: andre@0: if (cert){ andre@0: PKIX_CHECK(PKIX_PL_Object_Hashcode andre@0: ((PKIX_PL_Object *)cert, andre@0: &certHash, andre@0: plContext), andre@0: PKIX_OBJECTHASHCODEFAILED); andre@0: andre@0: hash = certHash; andre@0: andre@0: } else { andre@0: PKIX_CHECK(PKIX_PL_Object_Hashcode andre@0: ((PKIX_PL_Object *)anchor->caName, andre@0: &nameHash, andre@0: plContext), andre@0: PKIX_OBJECTHASHCODEFAILED); andre@0: andre@0: PKIX_CHECK(PKIX_PL_Object_Hashcode andre@0: ((PKIX_PL_Object *)anchor->caPubKey, andre@0: &pubKeyHash, andre@0: plContext), andre@0: PKIX_OBJECTHASHCODEFAILED); andre@0: andre@0: PKIX_HASHCODE(anchor->nameConstraints, &ncHash, plContext, andre@0: PKIX_OBJECTHASHCODEFAILED); andre@0: andre@0: hash = 31 * nameHash + pubKeyHash + ncHash; andre@0: andre@0: } andre@0: andre@0: *pHashcode = hash; andre@0: andre@0: cleanup: andre@0: andre@0: PKIX_RETURN(TRUSTANCHOR); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_TrustAnchor_ToString andre@0: * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) andre@0: */ andre@0: static PKIX_Error * andre@0: pkix_TrustAnchor_ToString( andre@0: PKIX_PL_Object *object, andre@0: PKIX_PL_String **pString, andre@0: void *plContext) andre@0: { andre@0: PKIX_TrustAnchor *anchor = NULL; andre@0: char *asciiFormat = NULL; andre@0: PKIX_PL_String *formatString = NULL; andre@0: PKIX_PL_String *anchorString = NULL; andre@0: PKIX_PL_String *certString = NULL; andre@0: PKIX_PL_String *nameString = NULL; andre@0: PKIX_PL_String *pubKeyString = NULL; andre@0: PKIX_PL_String *nameConstraintsString = NULL; andre@0: andre@0: PKIX_ENTER(TRUSTANCHOR, "pkix_TrustAnchor_ToString"); andre@0: PKIX_NULLCHECK_TWO(object, pString); andre@0: andre@0: PKIX_CHECK(pkix_CheckType(object, PKIX_TRUSTANCHOR_TYPE, plContext), andre@0: PKIX_OBJECTNOTTRUSTANCHOR); andre@0: andre@0: anchor = (PKIX_TrustAnchor*)object; andre@0: andre@0: if (anchor->trustedCert){ andre@0: asciiFormat = andre@0: "[\n" andre@0: "\tTrusted Cert: %s\n" andre@0: "]\n"; andre@0: andre@0: PKIX_CHECK(PKIX_PL_String_Create andre@0: (PKIX_ESCASCII, andre@0: asciiFormat, andre@0: 0, andre@0: &formatString, andre@0: plContext), andre@0: PKIX_STRINGCREATEFAILED); andre@0: andre@0: PKIX_CHECK(PKIX_PL_Object_ToString andre@0: ((PKIX_PL_Object *)anchor->trustedCert, andre@0: &certString, andre@0: plContext), andre@0: PKIX_OBJECTTOSTRINGFAILED); andre@0: andre@0: PKIX_CHECK(PKIX_PL_Sprintf andre@0: (&anchorString, andre@0: plContext, andre@0: formatString, andre@0: certString), andre@0: PKIX_SPRINTFFAILED); andre@0: } else { andre@0: asciiFormat = andre@0: "[\n" andre@0: "\tTrusted CA Name: %s\n" andre@0: "\tTrusted CA PublicKey: %s\n" andre@0: "\tInitial Name Constraints:%s\n" andre@0: "]\n"; andre@0: andre@0: PKIX_CHECK(PKIX_PL_String_Create andre@0: (PKIX_ESCASCII, andre@0: asciiFormat, andre@0: 0, andre@0: &formatString, andre@0: plContext), andre@0: PKIX_STRINGCREATEFAILED); andre@0: andre@0: PKIX_CHECK(PKIX_PL_Object_ToString andre@0: ((PKIX_PL_Object *)anchor->caName, andre@0: &nameString, andre@0: plContext), andre@0: PKIX_OBJECTTOSTRINGFAILED); andre@0: andre@0: PKIX_CHECK(PKIX_PL_Object_ToString andre@0: ((PKIX_PL_Object *)anchor->caPubKey, andre@0: &pubKeyString, andre@0: plContext), andre@0: PKIX_OBJECTTOSTRINGFAILED); andre@0: andre@0: PKIX_TOSTRING andre@0: (anchor->nameConstraints, andre@0: &nameConstraintsString, andre@0: plContext, andre@0: PKIX_OBJECTTOSTRINGFAILED); andre@0: andre@0: PKIX_CHECK(PKIX_PL_Sprintf andre@0: (&anchorString, andre@0: plContext, andre@0: formatString, andre@0: nameString, andre@0: pubKeyString, andre@0: nameConstraintsString), andre@0: PKIX_SPRINTFFAILED); andre@0: } andre@0: andre@0: *pString = anchorString; andre@0: andre@0: cleanup: andre@0: andre@0: PKIX_DECREF(formatString); andre@0: PKIX_DECREF(certString); andre@0: PKIX_DECREF(nameString); andre@0: PKIX_DECREF(pubKeyString); andre@0: PKIX_DECREF(nameConstraintsString); andre@0: andre@0: PKIX_RETURN(TRUSTANCHOR); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_TrustAnchor_RegisterSelf andre@0: * DESCRIPTION: andre@0: * Registers PKIX_TRUSTANCHOR_TYPE and its related functions with andre@0: * 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_TrustAnchor_RegisterSelf(void *plContext) andre@0: { andre@0: extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; andre@0: pkix_ClassTable_Entry entry; andre@0: andre@0: PKIX_ENTER(TRUSTANCHOR, "pkix_TrustAnchor_RegisterSelf"); andre@0: andre@0: entry.description = "TrustAnchor"; andre@0: entry.objCounter = 0; andre@0: entry.typeObjectSize = sizeof(PKIX_TrustAnchor); andre@0: entry.destructor = pkix_TrustAnchor_Destroy; andre@0: entry.equalsFunction = pkix_TrustAnchor_Equals; andre@0: entry.hashcodeFunction = pkix_TrustAnchor_Hashcode; andre@0: entry.toStringFunction = pkix_TrustAnchor_ToString; andre@0: entry.comparator = NULL; andre@0: entry.duplicateFunction = pkix_duplicateImmutable; andre@0: andre@0: systemClasses[PKIX_TRUSTANCHOR_TYPE] = entry; andre@0: andre@0: PKIX_RETURN(TRUSTANCHOR); andre@0: } andre@0: andre@0: /* --Public-Functions--------------------------------------------- */ andre@0: andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_TrustAnchor_CreateWithCert (see comments in pkix_params.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_TrustAnchor_CreateWithCert( andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_TrustAnchor **pAnchor, andre@0: void *plContext) andre@0: { andre@0: PKIX_TrustAnchor *anchor = NULL; andre@0: andre@0: PKIX_ENTER(TRUSTANCHOR, "PKIX_TrustAnchor_CreateWithCert"); andre@0: PKIX_NULLCHECK_TWO(cert, pAnchor); andre@0: andre@0: PKIX_CHECK(PKIX_PL_Object_Alloc andre@0: (PKIX_TRUSTANCHOR_TYPE, andre@0: sizeof (PKIX_TrustAnchor), andre@0: (PKIX_PL_Object **)&anchor, andre@0: plContext), andre@0: PKIX_COULDNOTCREATETRUSTANCHOROBJECT); andre@0: andre@0: /* initialize fields */ andre@0: PKIX_CHECK( andre@0: PKIX_PL_Cert_SetAsTrustAnchor(cert, plContext), andre@0: PKIX_CERTSETASTRUSTANCHORFAILED); andre@0: andre@0: PKIX_INCREF(cert); andre@0: anchor->trustedCert = cert; andre@0: andre@0: anchor->caName = NULL; andre@0: anchor->caPubKey = NULL; andre@0: andre@0: PKIX_CHECK(PKIX_PL_Cert_GetNameConstraints andre@0: (anchor->trustedCert, &anchor->nameConstraints, plContext), andre@0: PKIX_CERTGETNAMECONSTRAINTSFAILED); andre@0: andre@0: andre@0: *pAnchor = anchor; andre@0: anchor = NULL; andre@0: andre@0: cleanup: andre@0: andre@0: PKIX_DECREF(anchor); andre@0: andre@0: PKIX_RETURN(TRUSTANCHOR); andre@0: andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_TrustAnchor_CreateWithNameKeyPair andre@0: * (see comments in pkix_params.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_TrustAnchor_CreateWithNameKeyPair( andre@0: PKIX_PL_X500Name *name, andre@0: PKIX_PL_PublicKey *pubKey, andre@0: PKIX_PL_CertNameConstraints *nameConstraints, andre@0: PKIX_TrustAnchor **pAnchor, andre@0: void *plContext) andre@0: { andre@0: PKIX_TrustAnchor *anchor = NULL; andre@0: andre@0: PKIX_ENTER(TRUSTANCHOR, "PKIX_TrustAnchor_CreateWithNameKeyPair"); andre@0: andre@0: #ifndef BUILD_LIBPKIX_TESTS andre@0: /* Nss creates trust anchors by using PKIX_TrustAnchor_CreateWithCert andre@0: * function as the complete trusted cert structure, and not only cert andre@0: * public key, is required for chain building and validation processes. andre@0: * Restricting this function for been used only in libpkix unit andre@0: * tests. */ andre@0: PKIX_ERROR(PKIX_FUNCTIONMUSTNOTBEUSED); andre@0: #endif andre@0: andre@0: PKIX_NULLCHECK_THREE(name, pubKey, pAnchor); andre@0: andre@0: PKIX_CHECK(PKIX_PL_Object_Alloc andre@0: (PKIX_TRUSTANCHOR_TYPE, andre@0: sizeof (PKIX_TrustAnchor), andre@0: (PKIX_PL_Object **)&anchor, andre@0: plContext), andre@0: PKIX_COULDNOTCREATETRUSTANCHOROBJECT); andre@0: andre@0: /* initialize fields */ andre@0: anchor->trustedCert = NULL; andre@0: andre@0: PKIX_INCREF(name); andre@0: anchor->caName = name; andre@0: andre@0: PKIX_INCREF(pubKey); andre@0: anchor->caPubKey = pubKey; andre@0: andre@0: PKIX_INCREF(nameConstraints); andre@0: anchor->nameConstraints = nameConstraints; andre@0: andre@0: *pAnchor = anchor; andre@0: anchor = NULL; andre@0: cleanup: andre@0: andre@0: PKIX_DECREF(anchor); andre@0: andre@0: PKIX_RETURN(TRUSTANCHOR); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_TrustAnchor_GetTrustedCert (see comments in pkix_params.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_TrustAnchor_GetTrustedCert( andre@0: PKIX_TrustAnchor *anchor, andre@0: PKIX_PL_Cert **pCert, andre@0: void *plContext) andre@0: { andre@0: PKIX_ENTER(TRUSTANCHOR, "PKIX_TrustAnchor_GetTrustedCert"); andre@0: PKIX_NULLCHECK_TWO(anchor, pCert); andre@0: andre@0: PKIX_INCREF(anchor->trustedCert); andre@0: andre@0: *pCert = anchor->trustedCert; andre@0: andre@0: cleanup: andre@0: PKIX_RETURN(TRUSTANCHOR); andre@0: andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_TrustAnchor_GetCAName (see comments in pkix_params.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_TrustAnchor_GetCAName( andre@0: PKIX_TrustAnchor *anchor, andre@0: PKIX_PL_X500Name **pCAName, andre@0: void *plContext) andre@0: { andre@0: PKIX_ENTER(TRUSTANCHOR, "PKIX_TrustAnchor_GetCAName"); andre@0: PKIX_NULLCHECK_TWO(anchor, pCAName); andre@0: andre@0: PKIX_INCREF(anchor->caName); andre@0: andre@0: *pCAName = anchor->caName; andre@0: andre@0: cleanup: andre@0: PKIX_RETURN(TRUSTANCHOR); andre@0: andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_TrustAnchor_GetCAPublicKey (see comments in pkix_params.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_TrustAnchor_GetCAPublicKey( andre@0: PKIX_TrustAnchor *anchor, andre@0: PKIX_PL_PublicKey **pPubKey, andre@0: void *plContext) andre@0: { andre@0: PKIX_ENTER(TRUSTANCHOR, "PKIX_TrustAnchor_GetCAPublicKey"); andre@0: PKIX_NULLCHECK_TWO(anchor, pPubKey); andre@0: andre@0: PKIX_INCREF(anchor->caPubKey); andre@0: andre@0: *pPubKey = anchor->caPubKey; andre@0: andre@0: cleanup: andre@0: PKIX_RETURN(TRUSTANCHOR); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_TrustAnchor_GetNameConstraints andre@0: * (see comments in pkix_params.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_TrustAnchor_GetNameConstraints( andre@0: PKIX_TrustAnchor *anchor, andre@0: PKIX_PL_CertNameConstraints **pNameConstraints, andre@0: void *plContext) andre@0: { andre@0: PKIX_ENTER(TRUSTANCHOR, "PKIX_TrustAnchor_GetNameConstraints"); andre@0: PKIX_NULLCHECK_TWO(anchor, pNameConstraints); andre@0: andre@0: PKIX_INCREF(anchor->nameConstraints); andre@0: andre@0: *pNameConstraints = anchor->nameConstraints; andre@0: andre@0: cleanup: andre@0: PKIX_RETURN(TRUSTANCHOR); andre@0: }