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_oid.c andre@0: * andre@0: * OID Object Functions andre@0: * andre@0: */ andre@0: andre@0: #include "pkix_pl_oid.h" andre@0: andre@0: /* --Private-OID-Functions---------------------------------------- */ andre@0: andre@0: /* andre@0: * FUNCTION: pkix_pl_OID_Comparator andre@0: * (see comments for PKIX_PL_ComparatorCallback in pkix_pl_system.h) andre@0: */ andre@0: static PKIX_Error * andre@0: pkix_pl_OID_Comparator( andre@0: PKIX_PL_Object *firstObject, andre@0: PKIX_PL_Object *secondObject, andre@0: PKIX_Int32 *pRes, andre@0: void *plContext) andre@0: { andre@0: PKIX_PL_OID *firstOID = NULL; andre@0: PKIX_PL_OID *secondOID = NULL; andre@0: andre@0: PKIX_ENTER(OID, "pkix_pl_OID_Comparator"); andre@0: PKIX_NULLCHECK_THREE(firstObject, secondObject, pRes); andre@0: andre@0: PKIX_CHECK(pkix_CheckTypes andre@0: (firstObject, secondObject, PKIX_OID_TYPE, plContext), andre@0: PKIX_ARGUMENTSNOTOIDS); andre@0: andre@0: firstOID = (PKIX_PL_OID*)firstObject; andre@0: secondOID = (PKIX_PL_OID*)secondObject; andre@0: andre@0: *pRes = (PKIX_Int32)SECITEM_CompareItem(&firstOID->derOid, andre@0: &secondOID->derOid); andre@0: cleanup: andre@0: PKIX_RETURN(OID); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_pl_OID_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_OID_Destroy( andre@0: PKIX_PL_Object *object, andre@0: void *plContext) andre@0: { andre@0: PKIX_PL_OID *oid = NULL; andre@0: andre@0: PKIX_ENTER(OID, "pkix_pl_OID_Destroy"); andre@0: PKIX_NULLCHECK_ONE(object); andre@0: andre@0: PKIX_CHECK(pkix_CheckType(object, PKIX_OID_TYPE, plContext), andre@0: PKIX_OBJECTNOTANOID); andre@0: oid = (PKIX_PL_OID*)object; andre@0: SECITEM_FreeItem(&oid->derOid, PR_FALSE); andre@0: andre@0: cleanup: andre@0: PKIX_RETURN(OID); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_pl_OID_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_OID_Hashcode( andre@0: PKIX_PL_Object *object, andre@0: PKIX_UInt32 *pHashcode, andre@0: void *plContext) andre@0: { andre@0: PKIX_PL_OID *oid = NULL; andre@0: andre@0: PKIX_ENTER(OID, "pkix_pl_OID_HashCode"); andre@0: PKIX_NULLCHECK_TWO(object, pHashcode); andre@0: andre@0: PKIX_CHECK(pkix_CheckType(object, PKIX_OID_TYPE, plContext), andre@0: PKIX_OBJECTNOTANOID); andre@0: andre@0: oid = (PKIX_PL_OID *)object; andre@0: andre@0: PKIX_CHECK(pkix_hash andre@0: ((unsigned char *)oid->derOid.data, andre@0: oid->derOid.len * sizeof (char), andre@0: pHashcode, andre@0: plContext), andre@0: PKIX_HASHFAILED); andre@0: cleanup: andre@0: andre@0: PKIX_RETURN(OID); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_pl_OID_Equals andre@0: * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h) andre@0: */ andre@0: static PKIX_Error * andre@0: pkix_pl_OID_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_Int32 cmpResult; andre@0: andre@0: PKIX_ENTER(OID, "pkix_pl_OID_Equals"); andre@0: PKIX_NULLCHECK_THREE(first, second, pResult); andre@0: andre@0: PKIX_CHECK(pkix_pl_OID_Comparator andre@0: (first, second, &cmpResult, plContext), andre@0: PKIX_OIDCOMPARATORFAILED); andre@0: andre@0: *pResult = (cmpResult == 0); andre@0: cleanup: andre@0: andre@0: PKIX_RETURN(OID); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_pl_OID_ToString andre@0: * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) andre@0: * Use this function only for printing OIDs and not to make any andre@0: * critical security decision. andre@0: */ andre@0: static PKIX_Error * andre@0: pkix_pl_OID_ToString( andre@0: PKIX_PL_Object *object, andre@0: PKIX_PL_String **pString, andre@0: void *plContext) andre@0: { andre@0: PKIX_PL_OID *oid = NULL; andre@0: char *oidString = NULL; andre@0: andre@0: PKIX_ENTER(OID, "pkix_pl_OID_toString"); andre@0: PKIX_NULLCHECK_TWO(object, pString); andre@0: andre@0: PKIX_CHECK(pkix_CheckType(object, PKIX_OID_TYPE, plContext), andre@0: PKIX_OBJECTNOTANOID); andre@0: oid = (PKIX_PL_OID*)object; andre@0: oidString = CERT_GetOidString(&oid->derOid); andre@0: andre@0: PKIX_CHECK(PKIX_PL_String_Create andre@0: (PKIX_ESCASCII, oidString , 0, pString, plContext), andre@0: PKIX_STRINGCREATEFAILED); andre@0: cleanup: andre@0: PR_smprintf_free(oidString); andre@0: andre@0: PKIX_RETURN(OID); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_pl_OID_RegisterSelf andre@0: * DESCRIPTION: andre@0: * Registers PKIX_OID_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_OID_RegisterSelf( andre@0: void *plContext) andre@0: { andre@0: extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; andre@0: pkix_ClassTable_Entry *entry = &systemClasses[PKIX_OID_TYPE]; andre@0: andre@0: PKIX_ENTER(OID, "pkix_pl_OID_RegisterSelf"); andre@0: andre@0: entry->description = "OID"; andre@0: entry->typeObjectSize = sizeof(PKIX_PL_OID); andre@0: entry->destructor = pkix_pl_OID_Destroy; andre@0: entry->equalsFunction = pkix_pl_OID_Equals; andre@0: entry->hashcodeFunction = pkix_pl_OID_Hashcode; andre@0: entry->toStringFunction = pkix_pl_OID_ToString; andre@0: entry->comparator = pkix_pl_OID_Comparator; andre@0: entry->duplicateFunction = pkix_duplicateImmutable; andre@0: andre@0: PKIX_RETURN(OID); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_pl_OID_GetCriticalExtensionOIDs andre@0: * DESCRIPTION: andre@0: * andre@0: * Converts the extensions in "extensions" array that are critical to andre@0: * PKIX_PL_OID and returns the result as a PKIX_List in "pPidList". andre@0: * If there is no critical extension, an empty list is returned. andre@0: * andre@0: * PARAMETERS andre@0: * "extension" andre@0: * an array of extension pointers. May be NULL. andre@0: * "pOidsList" andre@0: * Address where the list of OIDs is returned. Must be non-NULL. 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 CRL 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_OID_GetCriticalExtensionOIDs( andre@0: CERTCertExtension **extensions, andre@0: PKIX_List **pOidsList, andre@0: void *plContext) andre@0: { andre@0: PKIX_List *oidsList = NULL; andre@0: PKIX_PL_OID *pkixOID = NULL; andre@0: andre@0: PKIX_ENTER(OID, "pkix_pl_OID_GetCriticalExtensionOIDs"); andre@0: PKIX_NULLCHECK_ONE(pOidsList); andre@0: andre@0: PKIX_CHECK(PKIX_List_Create(&oidsList, plContext), andre@0: PKIX_LISTCREATEFAILED); andre@0: andre@0: if (extensions) { andre@0: while (*extensions) { andre@0: CERTCertExtension *extension = NULL; andre@0: SECItem *critical = NULL; andre@0: SECItem *oid = NULL; andre@0: andre@0: extension = *extensions++; andre@0: /* extension is critical ? */ andre@0: critical = &extension->critical; andre@0: if (critical->len == 0 || critical->data[0] == 0) { andre@0: continue; andre@0: } andre@0: oid = &extension->id; andre@0: PKIX_CHECK( andre@0: PKIX_PL_OID_CreateBySECItem(oid, &pkixOID, plContext), andre@0: PKIX_OIDCREATEFAILED); andre@0: PKIX_CHECK( andre@0: PKIX_List_AppendItem(oidsList, (PKIX_PL_Object *)pkixOID, andre@0: plContext), andre@0: PKIX_LISTAPPENDITEMFAILED); andre@0: PKIX_DECREF(pkixOID); andre@0: } andre@0: } andre@0: andre@0: *pOidsList = oidsList; andre@0: oidsList = NULL; andre@0: andre@0: cleanup: andre@0: PKIX_DECREF(oidsList); andre@0: PKIX_DECREF(pkixOID); andre@0: PKIX_RETURN(OID); andre@0: } andre@0: andre@0: /* --Public-Functions------------------------------------------------------- */ andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_OID_CreateBySECItem (see comments in pkix_pl_system.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_OID_CreateBySECItem( andre@0: SECItem *derOid, andre@0: PKIX_PL_OID **pOID, andre@0: void *plContext) andre@0: { andre@0: PKIX_PL_OID *oid = NULL; andre@0: SECStatus rv; andre@0: andre@0: PKIX_ENTER(OID, "PKIX_PL_OID_CreateBySECItem"); andre@0: PKIX_NULLCHECK_TWO(pOID, derOid); andre@0: andre@0: PKIX_CHECK(PKIX_PL_Object_Alloc andre@0: (PKIX_OID_TYPE, andre@0: sizeof (PKIX_PL_OID), andre@0: (PKIX_PL_Object **)&oid, andre@0: plContext), andre@0: PKIX_COULDNOTCREATEOBJECT); andre@0: rv = SECITEM_CopyItem(NULL, &oid->derOid, derOid); andre@0: if (rv != SECSuccess) { andre@0: PKIX_ERROR(PKIX_OUTOFMEMORY); andre@0: } andre@0: *pOID = oid; andre@0: oid = NULL; andre@0: andre@0: cleanup: andre@0: PKIX_DECREF(oid); andre@0: andre@0: PKIX_RETURN(OID); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_OID_Create (see comments in pkix_pl_system.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_OID_Create( andre@0: SECOidTag idtag, andre@0: PKIX_PL_OID **pOID, andre@0: void *plContext) andre@0: { andre@0: SECOidData *oidData = NULL; andre@0: andre@0: PKIX_ENTER(OID, "PKIX_PL_OID_Create"); andre@0: PKIX_NULLCHECK_ONE(pOID); andre@0: andre@0: oidData = SECOID_FindOIDByTag((SECOidTag)idtag); andre@0: if (!oidData) { andre@0: PKIX_ERROR(PKIX_SECOIDFINDOIDTAGDESCRIPTIONFAILED); andre@0: } andre@0: andre@0: pkixErrorResult = andre@0: PKIX_PL_OID_CreateBySECItem(&oidData->oid, pOID, plContext); andre@0: cleanup: andre@0: PKIX_RETURN(OID); andre@0: }