diff options
Diffstat (limited to '')
-rw-r--r-- | security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_publickey.c | 489 |
1 files changed, 489 insertions, 0 deletions
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_publickey.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_publickey.c new file mode 100644 index 0000000000..2dfe9a9c2c --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_publickey.c @@ -0,0 +1,489 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +/* + * pkix_pl_publickey.c + * + * Certificate Object Functions + * + */ + +#include "pkix_pl_publickey.h" + +/* --Private-Cert-Functions------------------------------------- */ + +/* + * FUNCTION: pkix_pl_PublicKey_ToString_Helper + * DESCRIPTION: + * + * Helper function that creates a string representation of the PublicKey + * pointed to by "pkixPubKey" and stores it at "pString". + * + * PARAMETERS + * "pkixPubKey" + * Address of PublicKey whose string representation is desired. + * Must be non-NULL. + * "pString" + * Address where object pointer will be stored. Must be non-NULL. + * "plContext" - Platform-specific context pointer. + * THREAD SAFETY: + * Thread Safe (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a PublicKey Error if the function fails in a non-fatal way. + * Returns a Fatal Error if the function fails in an unrecoverable way. + */ +static PKIX_Error * +pkix_pl_PublicKey_ToString_Helper( + PKIX_PL_PublicKey *pkixPubKey, + PKIX_PL_String **pString, + void *plContext) +{ + SECAlgorithmID algorithm; + SECOidTag pubKeyTag; + char *asciiOID = NULL; + PKIX_Boolean freeAsciiOID = PKIX_FALSE; + SECItem oidBytes; + + PKIX_ENTER(PUBLICKEY, "pkix_pl_PublicKey_ToString_Helper"); + PKIX_NULLCHECK_THREE(pkixPubKey, pkixPubKey->nssSPKI, pString); + + /* + * XXX for now, we print out public key algorithm's + * description - add params and bytes later + */ + + /* + * If the algorithm OID is known to NSS, + * we print out the ASCII description that is + * registered with NSS. Otherwise, if unknown, + * we print out the OID numbers (eg. "1.2.840.3") + */ + + algorithm = pkixPubKey->nssSPKI->algorithm; + + PKIX_PUBLICKEY_DEBUG("\t\tCalling SECOID_GetAlgorithmTag).\n"); + pubKeyTag = SECOID_GetAlgorithmTag(&algorithm); + if (pubKeyTag != SEC_OID_UNKNOWN){ + PKIX_PUBLICKEY_DEBUG + ("\t\tCalling SECOID_FindOIDTagDescription).\n"); + asciiOID = (char *)SECOID_FindOIDTagDescription(pubKeyTag); + if (!asciiOID){ + PKIX_ERROR(PKIX_SECOIDFINDOIDTAGDESCRIPTIONFAILED); + } + } else { /* pubKeyTag == SEC_OID_UNKNOWN */ + oidBytes = algorithm.algorithm; + PKIX_CHECK(pkix_pl_oidBytes2Ascii + (&oidBytes, &asciiOID, plContext), + PKIX_OIDBYTES2ASCIIFAILED); + freeAsciiOID = PKIX_TRUE; + } + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, (void *)asciiOID, 0, pString, plContext), + PKIX_UNABLETOCREATEPSTRING); + +cleanup: + + /* + * we only free asciiOID if it was malloc'ed by pkix_pl_oidBytes2Ascii + */ + if (freeAsciiOID){ + PKIX_FREE(asciiOID); + } + + PKIX_RETURN(PUBLICKEY); +} + +/* + * FUNCTION: pkix_pl_DestroySPKI + * DESCRIPTION: + * Frees all memory associated with the CERTSubjectPublicKeyInfo pointed to + * by "nssSPKI". + * PARAMETERS + * "nssSPKI" + * Address of CERTSubjectPublicKeyInfo. Must be non-NULL. + * "plContext" - Platform-specific context pointer. + * THREAD SAFETY: + * Thread Safe (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns an Object Error if the function fails in a non-fatal way. + * Returns a Fatal Error if the function fails in an unrecoverable way. + */ +static PKIX_Error * +pkix_pl_DestroySPKI( + CERTSubjectPublicKeyInfo *nssSPKI, + void *plContext) +{ + PKIX_ENTER(PUBLICKEY, "pkix_pl_DestroySPKI"); + + PKIX_NULLCHECK_ONE(nssSPKI); + + PKIX_PUBLICKEY_DEBUG("\t\tCalling SECOID_DestroyAlgorithmID).\n"); + SECOID_DestroyAlgorithmID(&nssSPKI->algorithm, PKIX_FALSE); + + PKIX_PUBLICKEY_DEBUG("\t\tCalling SECITEM_FreeItem).\n"); + SECITEM_FreeItem(&nssSPKI->subjectPublicKey, PKIX_FALSE); + + PKIX_RETURN(PUBLICKEY); +} + +/* + * FUNCTION: pkix_pl_PublicKey_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_PublicKey_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_PL_PublicKey *pubKey = NULL; + + PKIX_ENTER(PUBLICKEY, "pkix_pl_PublicKey_Destroy"); + + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType(object, PKIX_PUBLICKEY_TYPE, plContext), + PKIX_OBJECTNOTPUBLICKEY); + + pubKey = (PKIX_PL_PublicKey *)object; + + if (pubKey->nssSPKI) { + + PKIX_CHECK(pkix_pl_DestroySPKI(pubKey->nssSPKI, plContext), + PKIX_DESTROYSPKIFAILED); + + PKIX_FREE(pubKey->nssSPKI); + } + +cleanup: + + PKIX_RETURN(PUBLICKEY); +} + +/* + * FUNCTION: pkix_pl_PublicKey_ToString + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_PublicKey_ToString( + PKIX_PL_Object *object, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_PL_PublicKey *pkixPubKey = NULL; + PKIX_PL_String *pubKeyString = NULL; + + PKIX_ENTER(PUBLICKEY, "pkix_pl_PublicKey_toString"); + PKIX_NULLCHECK_TWO(object, pString); + + PKIX_CHECK(pkix_CheckType(object, PKIX_PUBLICKEY_TYPE, plContext), + PKIX_OBJECTNOTPUBLICKEY); + + pkixPubKey = (PKIX_PL_PublicKey *)object; + + PKIX_CHECK(pkix_pl_PublicKey_ToString_Helper + (pkixPubKey, &pubKeyString, plContext), + PKIX_PUBLICKEYTOSTRINGHELPERFAILED); + + *pString = pubKeyString; + +cleanup: + + PKIX_RETURN(PUBLICKEY); +} + +/* + * FUNCTION: pkix_pl_PublicKey_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_PublicKey_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_PL_PublicKey *pkixPubKey = NULL; + SECItem algOID; + SECItem algParams; + SECItem nssPubKey; + PKIX_UInt32 algOIDHash; + PKIX_UInt32 algParamsHash; + PKIX_UInt32 pubKeyHash; + + PKIX_ENTER(PUBLICKEY, "pkix_pl_PublicKey_Hashcode"); + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType(object, PKIX_PUBLICKEY_TYPE, plContext), + PKIX_OBJECTNOTPUBLICKEY); + + pkixPubKey = (PKIX_PL_PublicKey *)object; + + PKIX_NULLCHECK_ONE(pkixPubKey->nssSPKI); + + algOID = pkixPubKey->nssSPKI->algorithm.algorithm; + algParams = pkixPubKey->nssSPKI->algorithm.parameters; + nssPubKey = pkixPubKey->nssSPKI->subjectPublicKey; + + PKIX_CHECK(pkix_hash + (algOID.data, algOID.len, &algOIDHash, plContext), + PKIX_HASHFAILED); + + PKIX_CHECK(pkix_hash + (algParams.data, algParams.len, &algParamsHash, plContext), + PKIX_HASHFAILED); + + PKIX_CHECK(pkix_hash + (nssPubKey.data, nssPubKey.len, &pubKeyHash, plContext), + PKIX_HASHFAILED); + + *pHashcode = pubKeyHash; + +cleanup: + + PKIX_RETURN(PUBLICKEY); +} + + +/* + * FUNCTION: pkix_pl_PublicKey_Equals + * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_PublicKey_Equals( + PKIX_PL_Object *firstObject, + PKIX_PL_Object *secondObject, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_PL_PublicKey *firstPKIXPubKey = NULL; + PKIX_PL_PublicKey *secondPKIXPubKey = NULL; + CERTSubjectPublicKeyInfo *firstSPKI = NULL; + CERTSubjectPublicKeyInfo *secondSPKI = NULL; + SECComparison cmpResult; + PKIX_UInt32 secondType; + + PKIX_ENTER(PUBLICKEY, "pkix_pl_PublicKey_Equals"); + PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); + + /* test that firstObject is a PublicKey */ + PKIX_CHECK(pkix_CheckType(firstObject, PKIX_PUBLICKEY_TYPE, plContext), + PKIX_FIRSTOBJECTNOTPUBLICKEY); + + /* + * Since we know firstObject is a PublicKey, if both references are + * identical, they must be equal + */ + if (firstObject == secondObject){ + *pResult = PKIX_TRUE; + goto cleanup; + } + + /* + * If secondObject isn't a PublicKey, we don't throw an error. + * We simply return a Boolean result of FALSE + */ + *pResult = PKIX_FALSE; + PKIX_CHECK(PKIX_PL_Object_GetType + (secondObject, &secondType, plContext), + PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); + if (secondType != PKIX_PUBLICKEY_TYPE) goto cleanup; + + firstPKIXPubKey = ((PKIX_PL_PublicKey *)firstObject); + secondPKIXPubKey = (PKIX_PL_PublicKey *)secondObject; + + firstSPKI = firstPKIXPubKey->nssSPKI; + secondSPKI = secondPKIXPubKey->nssSPKI; + + PKIX_NULLCHECK_TWO(firstSPKI, secondSPKI); + + PKIX_PL_NSSCALLRV(PUBLICKEY, cmpResult, SECOID_CompareAlgorithmID, + (&firstSPKI->algorithm, &secondSPKI->algorithm)); + + if (cmpResult == SECEqual){ + PKIX_PUBLICKEY_DEBUG("\t\tCalling SECITEM_CompareItem).\n"); + cmpResult = SECITEM_CompareItem + (&firstSPKI->subjectPublicKey, + &secondSPKI->subjectPublicKey); + } + + *pResult = (cmpResult == SECEqual)?PKIX_TRUE:PKIX_FALSE; + +cleanup: + + PKIX_RETURN(PUBLICKEY); +} + +/* + * FUNCTION: pkix_pl_PublicKey_RegisterSelf + * DESCRIPTION: + * Registers PKIX_PUBLICKEY_TYPE and its related functions with systemClasses[] + * THREAD SAFETY: + * Not Thread Safe - for performance and complexity reasons + * + * Since this function is only called by PKIX_PL_Initialize, which should + * only be called once, it is acceptable that this function is not + * thread-safe. + */ +PKIX_Error * +pkix_pl_PublicKey_RegisterSelf(void *plContext) +{ + + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(PUBLICKEY, "pkix_pl_PublicKey_RegisterSelf"); + + entry.description = "PublicKey"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_PL_PublicKey); + entry.destructor = pkix_pl_PublicKey_Destroy; + entry.equalsFunction = pkix_pl_PublicKey_Equals; + entry.hashcodeFunction = pkix_pl_PublicKey_Hashcode; + entry.toStringFunction = pkix_pl_PublicKey_ToString; + entry.comparator = NULL; + entry.duplicateFunction = pkix_duplicateImmutable; + systemClasses[PKIX_PUBLICKEY_TYPE] = entry; + + PKIX_RETURN(PUBLICKEY); +} + +/* --Public-Functions------------------------------------------------------- */ + +/* + * FUNCTION: PKIX_PL_PublicKey_NeedsDSAParameters + * (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_PublicKey_NeedsDSAParameters( + PKIX_PL_PublicKey *pubKey, + PKIX_Boolean *pNeedsParams, + void *plContext) +{ + CERTSubjectPublicKeyInfo *nssSPKI = NULL; + KeyType pubKeyType; + PKIX_Boolean needsParams = PKIX_FALSE; + + PKIX_ENTER(PUBLICKEY, "PKIX_PL_PublicKey_NeedsDSAParameters"); + PKIX_NULLCHECK_TWO(pubKey, pNeedsParams); + + nssSPKI = pubKey->nssSPKI; + + PKIX_PUBLICKEY_DEBUG("\t\tCalling CERT_GetCertKeyType).\n"); + pubKeyType = CERT_GetCertKeyType(nssSPKI); + if (!pubKeyType){ + PKIX_ERROR(PKIX_PUBKEYTYPENULLKEY); + } + + if ((pubKeyType == dsaKey) && + (nssSPKI->algorithm.parameters.len == 0)){ + needsParams = PKIX_TRUE; + } + + *pNeedsParams = needsParams; + +cleanup: + + PKIX_RETURN(PUBLICKEY); +} + +/* + * FUNCTION: PKIX_PL_PublicKey_MakeInheritedDSAPublicKey + * (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_PublicKey_MakeInheritedDSAPublicKey( + PKIX_PL_PublicKey *firstKey, + PKIX_PL_PublicKey *secondKey, + PKIX_PL_PublicKey **pResultKey, + void *plContext) +{ + CERTSubjectPublicKeyInfo *firstSPKI = NULL; + CERTSubjectPublicKeyInfo *secondSPKI = NULL; + CERTSubjectPublicKeyInfo *thirdSPKI = NULL; + PKIX_PL_PublicKey *resultKey = NULL; + KeyType firstPubKeyType; + KeyType secondPubKeyType; + SECStatus rv; + + PKIX_ENTER(PUBLICKEY, "PKIX_PL_PublicKey_MakeInheritedDSAPublicKey"); + PKIX_NULLCHECK_THREE(firstKey, secondKey, pResultKey); + PKIX_NULLCHECK_TWO(firstKey->nssSPKI, secondKey->nssSPKI); + + firstSPKI = firstKey->nssSPKI; + secondSPKI = secondKey->nssSPKI; + + PKIX_PUBLICKEY_DEBUG("\t\tCalling CERT_GetCertKeyType).\n"); + firstPubKeyType = CERT_GetCertKeyType(firstSPKI); + if (!firstPubKeyType){ + PKIX_ERROR(PKIX_FIRSTPUBKEYTYPENULLKEY); + } + + PKIX_PUBLICKEY_DEBUG("\t\tCalling CERT_GetCertKeyType).\n"); + secondPubKeyType = CERT_GetCertKeyType(secondSPKI); + if (!secondPubKeyType){ + PKIX_ERROR(PKIX_SECONDPUBKEYTYPENULLKEY); + } + + if ((firstPubKeyType == dsaKey) && + (firstSPKI->algorithm.parameters.len == 0)){ + if (secondPubKeyType != dsaKey) { + PKIX_ERROR(PKIX_SECONDKEYNOTDSAPUBLICKEY); + } else if (secondSPKI->algorithm.parameters.len == 0) { + PKIX_ERROR + (PKIX_SECONDKEYDSAPUBLICKEY); + } else { + PKIX_CHECK(PKIX_PL_Calloc + (1, + sizeof (CERTSubjectPublicKeyInfo), + (void **)&thirdSPKI, + plContext), + PKIX_CALLOCFAILED); + + PKIX_PUBLICKEY_DEBUG + ("\t\tCalling" + "SECKEY_CopySubjectPublicKeyInfo).\n"); + rv = SECKEY_CopySubjectPublicKeyInfo + (NULL, thirdSPKI, firstSPKI); + if (rv != SECSuccess) { + PKIX_ERROR + (PKIX_SECKEYCOPYSUBJECTPUBLICKEYINFOFAILED); + } + + PKIX_PUBLICKEY_DEBUG + ("\t\tCalling SECITEM_CopyItem).\n"); + rv = SECITEM_CopyItem(NULL, + &thirdSPKI->algorithm.parameters, + &secondSPKI->algorithm.parameters); + + if (rv != SECSuccess) { + PKIX_ERROR(PKIX_OUTOFMEMORY); + } + + /* create a PKIX_PL_PublicKey object */ + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_PUBLICKEY_TYPE, + sizeof (PKIX_PL_PublicKey), + (PKIX_PL_Object **)&resultKey, + plContext), + PKIX_COULDNOTCREATEOBJECT); + + /* populate the SPKI field */ + resultKey->nssSPKI = thirdSPKI; + *pResultKey = resultKey; + } + } else { + *pResultKey = NULL; + } + +cleanup: + + if (thirdSPKI && PKIX_ERROR_RECEIVED){ + PKIX_CHECK(pkix_pl_DestroySPKI(thirdSPKI, plContext), + PKIX_DESTROYSPKIFAILED); + PKIX_FREE(thirdSPKI); + } + + PKIX_RETURN(PUBLICKEY); +} |