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