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_basicconstraints.c andre@0: * andre@0: * BasicConstraints Object Functions andre@0: * andre@0: */ andre@0: andre@0: #include "pkix_pl_basicconstraints.h" andre@0: andre@0: /* andre@0: * FUNCTION: pkix_pl_CertBasicConstraints_Create andre@0: * DESCRIPTION: andre@0: * andre@0: * Creates a new CertBasicConstraints object whose CA Flag has the value andre@0: * given by the Boolean value of "isCA" and whose path length field has the andre@0: * value given by the "pathLen" argument and stores it at "pObject". andre@0: * andre@0: * PARAMETERS andre@0: * "isCA" andre@0: * Boolean value with the desired value of CA Flag. andre@0: * "pathLen" andre@0: * a PKIX_Int32 with the desired value of path length andre@0: * "pObject" andre@0: * Address of object pointer's destination. Must be non-NULL. andre@0: * "plContext" - 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 CertBasicConstraints Error if the function fails andre@0: * 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_CertBasicConstraints_Create( andre@0: PKIX_Boolean isCA, andre@0: PKIX_Int32 pathLen, andre@0: PKIX_PL_CertBasicConstraints **pObject, andre@0: void *plContext) andre@0: { andre@0: PKIX_PL_CertBasicConstraints *basic = NULL; andre@0: andre@0: PKIX_ENTER(CERTBASICCONSTRAINTS, andre@0: "pkix_pl_CertBasicConstraints_Create"); andre@0: PKIX_NULLCHECK_ONE(pObject); andre@0: andre@0: PKIX_CHECK(PKIX_PL_Object_Alloc andre@0: (PKIX_CERTBASICCONSTRAINTS_TYPE, andre@0: sizeof (PKIX_PL_CertBasicConstraints), andre@0: (PKIX_PL_Object **)&basic, andre@0: plContext), andre@0: PKIX_COULDNOTCREATECERTBASICCONSTRAINTSOBJECT); andre@0: andre@0: basic->isCA = isCA; andre@0: andre@0: /* pathLen has meaning only for CAs, but it's not worth checking */ andre@0: basic->pathLen = pathLen; andre@0: andre@0: *pObject = basic; andre@0: andre@0: cleanup: andre@0: andre@0: PKIX_RETURN(CERTBASICCONSTRAINTS); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_pl_CertBasicConstraints_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_CertBasicConstraints_Destroy( andre@0: PKIX_PL_Object *object, andre@0: void *plContext) andre@0: { andre@0: PKIX_PL_CertBasicConstraints *certB = NULL; andre@0: andre@0: PKIX_ENTER(CERTBASICCONSTRAINTS, andre@0: "pkix_pl_CertBasicConstraints_Destroy"); andre@0: PKIX_NULLCHECK_ONE(object); andre@0: andre@0: PKIX_CHECK(pkix_CheckType andre@0: (object, PKIX_CERTBASICCONSTRAINTS_TYPE, plContext), andre@0: PKIX_OBJECTNOTCERTBASICCONSTRAINTS); andre@0: andre@0: certB = (PKIX_PL_CertBasicConstraints*)object; andre@0: andre@0: certB->isCA = PKIX_FALSE; andre@0: certB->pathLen = 0; andre@0: andre@0: cleanup: andre@0: andre@0: PKIX_RETURN(CERTBASICCONSTRAINTS); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_pl_CertBasicConstraints_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_CertBasicConstraints_ToString( andre@0: PKIX_PL_Object *object, andre@0: PKIX_PL_String **pString, andre@0: void *plContext) andre@0: { andre@0: PKIX_PL_String *certBasicConstraintsString = NULL; andre@0: PKIX_PL_CertBasicConstraints *certB = NULL; andre@0: PKIX_Boolean isCA = PKIX_FALSE; andre@0: PKIX_Int32 pathLen = 0; andre@0: PKIX_PL_String *outString = NULL; andre@0: char *fmtString = NULL; andre@0: PKIX_Boolean pathlenArg = PKIX_FALSE; andre@0: andre@0: PKIX_ENTER(CERTBASICCONSTRAINTS, andre@0: "pkix_pl_CertBasicConstraints_toString"); andre@0: PKIX_NULLCHECK_TWO(object, pString); andre@0: andre@0: PKIX_CHECK(pkix_CheckType andre@0: (object, PKIX_CERTBASICCONSTRAINTS_TYPE, plContext), andre@0: PKIX_FIRSTARGUMENTNOTCERTBASICCONSTRAINTSOBJECT); andre@0: andre@0: certB = (PKIX_PL_CertBasicConstraints *)object; andre@0: andre@0: /* andre@0: * if CA == TRUE andre@0: * if pathLen == CERT_UNLIMITED_PATH_CONSTRAINT andre@0: * print "CA(-1)" andre@0: * else print "CA(nnn)" andre@0: * if CA == FALSE, print "~CA" andre@0: */ andre@0: andre@0: isCA = certB->isCA; andre@0: andre@0: if (isCA) { andre@0: pathLen = certB->pathLen; andre@0: andre@0: if (pathLen == CERT_UNLIMITED_PATH_CONSTRAINT) { andre@0: /* print "CA(-1)" */ andre@0: fmtString = "CA(-1)"; andre@0: pathlenArg = PKIX_FALSE; andre@0: } else { andre@0: /* print "CA(pathLen)" */ andre@0: fmtString = "CA(%d)"; andre@0: pathlenArg = PKIX_TRUE; andre@0: } andre@0: } else { andre@0: /* print "~CA" */ andre@0: fmtString = "~CA"; andre@0: pathlenArg = PKIX_FALSE; andre@0: } andre@0: andre@0: PKIX_CHECK(PKIX_PL_String_Create andre@0: (PKIX_ESCASCII, andre@0: fmtString, andre@0: 0, andre@0: &certBasicConstraintsString, andre@0: plContext), andre@0: PKIX_STRINGCREATEFAILED); andre@0: andre@0: if (pathlenArg) { andre@0: PKIX_CHECK(PKIX_PL_Sprintf andre@0: (&outString, andre@0: plContext, andre@0: certBasicConstraintsString, andre@0: pathLen), andre@0: PKIX_SPRINTFFAILED); andre@0: } else { andre@0: PKIX_CHECK(PKIX_PL_Sprintf andre@0: (&outString, andre@0: plContext, andre@0: certBasicConstraintsString), andre@0: PKIX_SPRINTFFAILED); andre@0: } andre@0: andre@0: *pString = outString; andre@0: andre@0: cleanup: andre@0: andre@0: PKIX_DECREF(certBasicConstraintsString); andre@0: andre@0: PKIX_RETURN(CERTBASICCONSTRAINTS); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_pl_CertBasicConstraints_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_CertBasicConstraints_Hashcode( andre@0: PKIX_PL_Object *object, andre@0: PKIX_UInt32 *pHashcode, andre@0: void *plContext) andre@0: { andre@0: PKIX_PL_CertBasicConstraints *certB = NULL; andre@0: PKIX_Boolean isCA = PKIX_FALSE; andre@0: PKIX_Int32 pathLen = 0; andre@0: PKIX_Int32 hashInput = 0; andre@0: PKIX_UInt32 cbcHash = 0; andre@0: andre@0: PKIX_ENTER(CERTBASICCONSTRAINTS, andre@0: "pkix_pl_CertBasicConstraints_Hashcode"); andre@0: PKIX_NULLCHECK_TWO(object, pHashcode); andre@0: andre@0: PKIX_CHECK(pkix_CheckType andre@0: (object, PKIX_CERTBASICCONSTRAINTS_TYPE, plContext), andre@0: PKIX_OBJECTNOTCERTBASICCONSTRAINTS); andre@0: andre@0: certB = (PKIX_PL_CertBasicConstraints *)object; andre@0: andre@0: /* andre@0: * if CA == TRUE andre@0: * hash(pathLen + 1 - PKIX_UNLIMITED_PATH_CONSTRAINT) andre@0: * if CA == FALSE, hash(0) andre@0: */ andre@0: andre@0: isCA = certB->isCA; andre@0: andre@0: if (isCA) { andre@0: pathLen = certB->pathLen; andre@0: andre@0: hashInput = pathLen + 1 - PKIX_UNLIMITED_PATH_CONSTRAINT; andre@0: } andre@0: andre@0: PKIX_CHECK(pkix_hash andre@0: ((const unsigned char *)&hashInput, andre@0: sizeof (hashInput), andre@0: &cbcHash, andre@0: plContext), andre@0: PKIX_HASHFAILED); andre@0: andre@0: *pHashcode = cbcHash; andre@0: andre@0: cleanup: andre@0: andre@0: PKIX_RETURN(CERTBASICCONSTRAINTS); andre@0: } andre@0: andre@0: andre@0: /* andre@0: * FUNCTION: pkix_pl_CertBasicConstraints_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_CertBasicConstraints_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: PKIX_PL_CertBasicConstraints *firstCBC = NULL; andre@0: PKIX_PL_CertBasicConstraints *secondCBC = NULL; andre@0: PKIX_UInt32 secondType; andre@0: PKIX_Boolean firstIsCA = PKIX_FALSE; andre@0: PKIX_Boolean secondIsCA = PKIX_FALSE; andre@0: PKIX_Int32 firstPathLen = 0; andre@0: PKIX_Int32 secondPathLen = 0; andre@0: andre@0: PKIX_ENTER(CERTBASICCONSTRAINTS, andre@0: "pkix_pl_CertBasicConstraints_Equals"); andre@0: PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); andre@0: andre@0: /* test that firstObject is a CertBasicConstraints */ andre@0: PKIX_CHECK(pkix_CheckType andre@0: (firstObject, PKIX_CERTBASICCONSTRAINTS_TYPE, plContext), andre@0: PKIX_FIRSTOBJECTNOTCERTBASICCONSTRAINTS); andre@0: andre@0: /* andre@0: * Since we know firstObject is a CertBasicConstraints, andre@0: * if both references are 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 CertBasicConstraints, we andre@0: * don't throw an error. We simply return FALSE. andre@0: */ andre@0: PKIX_CHECK(PKIX_PL_Object_GetType andre@0: (secondObject, &secondType, plContext), andre@0: PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); andre@0: if (secondType != PKIX_CERTBASICCONSTRAINTS_TYPE) { andre@0: *pResult = PKIX_FALSE; andre@0: goto cleanup; andre@0: } andre@0: andre@0: firstCBC = (PKIX_PL_CertBasicConstraints *)firstObject; andre@0: secondCBC = (PKIX_PL_CertBasicConstraints *)secondObject; andre@0: andre@0: /* andre@0: * Compare the value of the CAFlag components andre@0: */ andre@0: andre@0: firstIsCA = firstCBC->isCA; andre@0: andre@0: /* andre@0: * Failure here would be an error, not merely a miscompare, andre@0: * since we know second is a CertBasicConstraints. andre@0: */ andre@0: secondIsCA = secondCBC->isCA; andre@0: andre@0: /* andre@0: * If isCA flags differ, the objects are not equal. andre@0: */ andre@0: if (secondIsCA != firstIsCA) { andre@0: *pResult = PKIX_FALSE; andre@0: goto cleanup; andre@0: } andre@0: andre@0: /* andre@0: * If isCA was FALSE, the objects are equal, because andre@0: * pathLen is meaningless in that case. andre@0: */ andre@0: if (!firstIsCA) { andre@0: *pResult = PKIX_TRUE; andre@0: goto cleanup; andre@0: } andre@0: andre@0: firstPathLen = firstCBC->pathLen; andre@0: secondPathLen = secondCBC->pathLen; andre@0: andre@0: *pResult = (secondPathLen == firstPathLen); andre@0: andre@0: cleanup: andre@0: andre@0: PKIX_RETURN(CERTBASICCONSTRAINTS); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_pl_CertBasicConstraints_RegisterSelf andre@0: * DESCRIPTION: andre@0: * Registers PKIX_CERTBASICCONSTRAINTS_TYPE and its related andre@0: * 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, andre@0: * which should only be called once, it is acceptable that andre@0: * this function is not thread-safe. andre@0: */ andre@0: PKIX_Error * andre@0: pkix_pl_CertBasicConstraints_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(CERTBASICCONSTRAINTS, andre@0: "pkix_pl_CertBasicConstraints_RegisterSelf"); andre@0: andre@0: entry.description = "CertBasicConstraints"; andre@0: entry.objCounter = 0; andre@0: entry.typeObjectSize = sizeof(PKIX_PL_CertBasicConstraints); andre@0: entry.destructor = pkix_pl_CertBasicConstraints_Destroy; andre@0: entry.equalsFunction = pkix_pl_CertBasicConstraints_Equals; andre@0: entry.hashcodeFunction = pkix_pl_CertBasicConstraints_Hashcode; andre@0: entry.toStringFunction = pkix_pl_CertBasicConstraints_ToString; andre@0: entry.comparator = NULL; andre@0: entry.duplicateFunction = pkix_duplicateImmutable; andre@0: andre@0: systemClasses[PKIX_CERTBASICCONSTRAINTS_TYPE] = entry; andre@0: andre@0: PKIX_RETURN(CERTBASICCONSTRAINTS); andre@0: } andre@0: andre@0: /* --Public-Functions------------------------------------------------------- */ andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_BasicConstraints_GetCAFlag andre@0: * (see comments in pkix_pl_pki.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_BasicConstraints_GetCAFlag( andre@0: PKIX_PL_CertBasicConstraints *basicConstraints, andre@0: PKIX_Boolean *pResult, andre@0: void *plContext) andre@0: { andre@0: PKIX_ENTER(CERTBASICCONSTRAINTS, andre@0: "PKIX_PL_BasicConstraintsGetCAFlag"); andre@0: PKIX_NULLCHECK_TWO(basicConstraints, pResult); andre@0: andre@0: *pResult = basicConstraints->isCA; andre@0: andre@0: PKIX_RETURN(CERTBASICCONSTRAINTS); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_BasicConstraints_GetPathLenConstraint andre@0: * (see comments in pkix_pl_pki.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_BasicConstraints_GetPathLenConstraint( andre@0: PKIX_PL_CertBasicConstraints *basicConstraints, andre@0: PKIX_Int32 *pPathLenConstraint, andre@0: void *plContext) andre@0: { andre@0: PKIX_ENTER(CERTBASICCONSTRAINTS, andre@0: "PKIX_PL_BasicConstraintsGetPathLenConstraint"); andre@0: PKIX_NULLCHECK_TWO(basicConstraints, pPathLenConstraint); andre@0: andre@0: *pPathLenConstraint = basicConstraints->pathLen; andre@0: andre@0: PKIX_RETURN(CERTBASICCONSTRAINTS); andre@0: }