Index: mozilla/security/nss/lib/libpkix/pkix/checker/pkix_signaturechecker.c |
=================================================================== |
--- mozilla/security/nss/lib/libpkix/pkix/checker/pkix_signaturechecker.c (revision 191424) |
+++ mozilla/security/nss/lib/libpkix/pkix/checker/pkix_signaturechecker.c (working copy) |
@@ -1,443 +0,0 @@ |
-/* 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_signaturechecker.c |
- * |
- * Functions for signature validation |
- * |
- */ |
- |
-#include "pkix_signaturechecker.h" |
- |
-/* |
- * FUNCTION: pkix_SignatureCheckerstate_Destroy |
- * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) |
- */ |
-static PKIX_Error * |
-pkix_SignatureCheckerState_Destroy( |
- PKIX_PL_Object *object, |
- void *plContext) |
-{ |
- pkix_SignatureCheckerState *state = NULL; |
- |
- PKIX_ENTER(SIGNATURECHECKERSTATE, |
- "pkix_SignatureCheckerState_Destroy"); |
- PKIX_NULLCHECK_ONE(object); |
- |
- /* Check that this object is a signature checker state */ |
- PKIX_CHECK(pkix_CheckType |
- (object, PKIX_SIGNATURECHECKERSTATE_TYPE, plContext), |
- PKIX_OBJECTNOTSIGNATURECHECKERSTATE); |
- |
- state = (pkix_SignatureCheckerState *) object; |
- |
- state->prevCertCertSign = PKIX_FALSE; |
- |
- PKIX_DECREF(state->prevPublicKey); |
- PKIX_DECREF(state->prevPublicKeyList); |
- PKIX_DECREF(state->keyUsageOID); |
- |
-cleanup: |
- |
- PKIX_RETURN(SIGNATURECHECKERSTATE); |
-} |
- |
-/* |
- * FUNCTION: pkix_SignatureCheckerState_RegisterSelf |
- * |
- * DESCRIPTION: |
- * Registers PKIX_SIGNATURECHECKERSTATE_TYPE and its related functions |
- * with systemClasses[] |
- * |
- * THREAD SAFETY: |
- * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
- * |
- * 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_SignatureCheckerState_RegisterSelf(void *plContext) |
-{ |
- extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; |
- pkix_ClassTable_Entry entry; |
- |
- PKIX_ENTER(SIGNATURECHECKERSTATE, |
- "pkix_SignatureCheckerState_RegisterSelf"); |
- |
- entry.description = "SignatureCheckerState"; |
- entry.objCounter = 0; |
- entry.typeObjectSize = sizeof(pkix_SignatureCheckerState); |
- entry.destructor = pkix_SignatureCheckerState_Destroy; |
- entry.equalsFunction = NULL; |
- entry.hashcodeFunction = NULL; |
- entry.toStringFunction = NULL; |
- entry.comparator = NULL; |
- entry.duplicateFunction = NULL; |
- |
- systemClasses[PKIX_SIGNATURECHECKERSTATE_TYPE] = entry; |
- |
- PKIX_RETURN(SIGNATURECHECKERSTATE); |
-} |
- |
-/* |
- * FUNCTION: pkix_SignatureCheckerState_Create |
- * |
- * DESCRIPTION: |
- * Allocate and initialize SignatureChecker state data. |
- * |
- * PARAMETERS |
- * "trustedPubKey" |
- * Address of trusted Anchor Public Key for verifying first Cert in the |
- * chain. Must be non-NULL. |
- * "certsRemaining" |
- * Number of certificates remaining in the chain. |
- * "pCheckerState" |
- * Address where SignatureCheckerState will be stored. Must be non-NULL. |
- * "plContext" |
- * Platform-specific context pointer. |
- * |
- * THREAD SAFETY: |
- * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
- * |
- * RETURNS: |
- * Returns NULL if the function succeeds. |
- * Returns a SignatureCheckerState 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_SignatureCheckerState_Create( |
- PKIX_PL_PublicKey *trustedPubKey, |
- PKIX_UInt32 certsRemaining, |
- pkix_SignatureCheckerState **pCheckerState, |
- void *plContext) |
-{ |
- pkix_SignatureCheckerState *state = NULL; |
- PKIX_PL_OID *keyUsageOID = NULL; |
- |
- PKIX_ENTER(SIGNATURECHECKERSTATE, "pkix_SignatureCheckerState_Create"); |
- PKIX_NULLCHECK_TWO(trustedPubKey, pCheckerState); |
- |
- PKIX_CHECK(PKIX_PL_Object_Alloc |
- (PKIX_SIGNATURECHECKERSTATE_TYPE, |
- sizeof (pkix_SignatureCheckerState), |
- (PKIX_PL_Object **)&state, |
- plContext), |
- PKIX_COULDNOTCREATESIGNATURECHECKERSTATEOBJECT); |
- |
- /* Initialize fields */ |
- |
- state->prevCertCertSign = PKIX_TRUE; |
- state->prevPublicKeyList = NULL; |
- state->certsRemaining = certsRemaining; |
- |
- PKIX_INCREF(trustedPubKey); |
- state->prevPublicKey = trustedPubKey; |
- |
- PKIX_CHECK(PKIX_PL_OID_Create |
- (PKIX_CERTKEYUSAGE_OID, |
- &keyUsageOID, |
- plContext), |
- PKIX_OIDCREATEFAILED); |
- |
- state->keyUsageOID = keyUsageOID; |
- keyUsageOID = NULL; |
- |
- *pCheckerState = state; |
- state = NULL; |
- |
-cleanup: |
- |
- PKIX_DECREF(keyUsageOID); |
- PKIX_DECREF(state); |
- |
- PKIX_RETURN(SIGNATURECHECKERSTATE); |
-} |
- |
-/* --Private-Functions-------------------------------------------- */ |
- |
-/* |
- * FUNCTION: pkix_SignatureChecker_Check |
- * (see comments for PKIX_CertChainChecker_CheckCallback in pkix_checker.h) |
- */ |
-PKIX_Error * |
-pkix_SignatureChecker_Check( |
- PKIX_CertChainChecker *checker, |
- PKIX_PL_Cert *cert, |
- PKIX_List *unresolvedCriticalExtensions, |
- void **pNBIOContext, |
- void *plContext) |
-{ |
- pkix_SignatureCheckerState *state = NULL; |
- PKIX_PL_PublicKey *prevPubKey = NULL; |
- PKIX_PL_PublicKey *currPubKey = NULL; |
- PKIX_PL_PublicKey *newPubKey = NULL; |
- PKIX_PL_PublicKey *pKey = NULL; |
- PKIX_PL_CertBasicConstraints *basicConstraints = NULL; |
- PKIX_Error *checkKeyUsageFail = NULL; |
- PKIX_Error *verifyFail = NULL; |
- PKIX_Boolean certVerified = PKIX_FALSE; |
- |
- PKIX_ENTER(CERTCHAINCHECKER, "pkix_SignatureChecker_Check"); |
- PKIX_NULLCHECK_THREE(checker, cert, pNBIOContext); |
- |
- *pNBIOContext = NULL; /* we never block on pending I/O */ |
- |
- PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState |
- (checker, (PKIX_PL_Object **)&state, plContext), |
- PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED); |
- |
- (state->certsRemaining)--; |
- |
- PKIX_INCREF(state->prevPublicKey); |
- prevPubKey = state->prevPublicKey; |
- |
- /* |
- * Previous Cert doesn't have CertSign bit on for signature |
- * verification and it is not a self-issued Cert so there is no |
- * old key saved. This is considered error. |
- */ |
- if (state->prevCertCertSign == PKIX_FALSE && |
- state->prevPublicKeyList == NULL) { |
- PKIX_ERROR(PKIX_KEYUSAGEKEYCERTSIGNBITNOTON); |
- } |
- |
- /* Previous Cert is valid for signature verification, try it first */ |
- if (state->prevCertCertSign == PKIX_TRUE) { |
- verifyFail = PKIX_PL_Cert_VerifySignature |
- (cert, prevPubKey, plContext); |
- if (verifyFail == NULL) { |
- certVerified = PKIX_TRUE; |
- } else { |
- certVerified = PKIX_FALSE; |
- } |
- } |
- |
-#ifdef NIST_TEST_4_5_4_AND_4_5_6 |
- |
- /* |
- * Following codes under this compiler flag is implemented for |
- * special cases of NIST tests 4.5.4 and 4.5.6. We are not sure |
- * we should handle these two tests as what is implemented so the |
- * codes are commented out, and the tests fails (for now). |
- * For Cert chain validation, our assumption is all the Certs on |
- * the chain are using its previous Cert's public key to decode |
- * its current key. But for thses two tests, keys are used not |
- * in this precedent order, we can either |
- * 1) Use what is implemented here: take in what Cert order NIST |
- * specified and for continuous self-issued Certs, stacking up |
- * their keys and tries all of them in FILO order. |
- * But this method breaks the idea of chain key presdency. |
- * 2) Use Build Chain facility: we will specify the valid Certs |
- * order (means key precedency is kept) and count on Build Chain |
- * to get the Certs that can fill for the needed keys. This may have |
- * performance impact. |
- * 3) Fetch Certs from CertStore: we will specifiy the valid Certs |
- * order and use CertSelector on SubjectName to get a list of |
- * candidates Certs to fill in for the needed keys. |
- * Anyhow, the codes are kept around just in case we want to use |
- * solution one... |
- */ |
- |
- /* If failed and previous key is self-issued, try its old key(s) */ |
- if (certVerified == PKIX_FALSE && state->prevPublicKeyList != NULL) { |
- |
- /* Verify from keys on the list */ |
- PKIX_CHECK(PKIX_List_GetLength |
- (state->prevPublicKeyList, &numKeys, plContext), |
- PKIX_LISTGETLENGTHFAILED); |
- |
- for (i = numKeys - 1; i >= 0; i--) { |
- |
- PKIX_CHECK(PKIX_List_GetItem |
- (state->prevPublicKeyList, |
- i, |
- (PKIX_PL_Object **) &pKey, |
- plContext), |
- PKIX_LISTGETITEMFAILED); |
- |
- PKIX_DECREF(verifyFail); |
- verifyFail = PKIX_PL_Cert_VerifySignature |
- (cert, pKey, plContext); |
- |
- if (verifyFail == NULL) { |
- certVerified = PKIX_TRUE; |
- break; |
- } else { |
- certVerified = PKIX_FALSE; |
- } |
- |
- PKIX_DECREF(pKey); |
- } |
- } |
-#endif |
- |
- if (certVerified == PKIX_FALSE) { |
- pkixErrorResult = verifyFail; |
- verifyFail = NULL; |
- PKIX_ERROR(PKIX_VALIDATIONFAILEDCERTSIGNATURECHECKING); |
- } |
- |
-#ifdef NIST_TEST_4_5_4_AND_4_5_6 |
- /* |
- * Check if Cert is self-issued. If so, the old key(s) is saved, in |
- * conjunction to the new key, for verifying CERT validity later. |
- */ |
- PKIX_CHECK(pkix_IsCertSelfIssued(cert, &selfIssued, plContext), |
- PKIX_ISCERTSELFISSUEFAILED); |
- |
- /* |
- * Check if Cert is self-issued. If so, the public key of the Cert |
- * that issues this Cert (old key) can be used together with this |
- * current key (new key) for key verification. If there are multiple |
- * self-issued certs, keys of those Certs (old keys) can also be used |
- * for key verification. Old key(s) is saved in a list (PrevPublickKey- |
- * List) and cleared when a Cert is no longer self-issued. PrevPublic- |
- * Key keep key of the previous Cert. |
- */ |
- if (selfIssued == PKIX_TRUE) { |
- |
- /* Make sure previous Cert is valid for signature verification */ |
- if (state->prevCertCertSign == PKIX_TRUE) { |
- |
- if (state->prevPublicKeyList == NULL) { |
- |
- PKIX_CHECK(PKIX_List_Create |
- (&state->prevPublicKeyList, plContext), |
- PKIX_LISTCREATEFALIED); |
- |
- } |
- |
- PKIX_CHECK(PKIX_List_AppendItem |
- (state->prevPublicKeyList, |
- (PKIX_PL_Object *) state->prevPublicKey, |
- plContext), |
- PKIX_LISTAPPENDITEMFAILED); |
- } |
- |
- } else { |
- /* Not self-issued Cert any more, clear old key(s) saved */ |
- PKIX_DECREF(state->prevPublicKeyList); |
- } |
-#endif |
- |
- /* Save current key as prevPublicKey */ |
- PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey |
- (cert, &currPubKey, plContext), |
- PKIX_CERTGETSUBJECTPUBLICKEYFAILED); |
- |
- PKIX_CHECK(PKIX_PL_PublicKey_MakeInheritedDSAPublicKey |
- (currPubKey, prevPubKey, &newPubKey, plContext), |
- PKIX_PUBLICKEYMAKEINHERITEDDSAPUBLICKEYFAILED); |
- |
- if (newPubKey == NULL){ |
- PKIX_INCREF(currPubKey); |
- newPubKey = currPubKey; |
- } |
- |
- PKIX_INCREF(newPubKey); |
- PKIX_DECREF(state->prevPublicKey); |
- |
- state->prevPublicKey = newPubKey; |
- |
- /* Save this Cert key usage CertSign bit */ |
- if (state->certsRemaining != 0) { |
- checkKeyUsageFail = PKIX_PL_Cert_VerifyKeyUsage |
- (cert, PKIX_KEY_CERT_SIGN, plContext); |
- |
- state->prevCertCertSign = (checkKeyUsageFail == NULL)? |
- PKIX_TRUE:PKIX_FALSE; |
- |
- PKIX_DECREF(checkKeyUsageFail); |
- } |
- |
- /* Remove Key Usage Extension OID from list */ |
- if (unresolvedCriticalExtensions != NULL) { |
- |
- PKIX_CHECK(pkix_List_Remove |
- (unresolvedCriticalExtensions, |
- (PKIX_PL_Object *) state->keyUsageOID, |
- plContext), |
- PKIX_LISTREMOVEFAILED); |
- } |
- |
- PKIX_CHECK(PKIX_CertChainChecker_SetCertChainCheckerState |
- (checker, (PKIX_PL_Object *)state, plContext), |
- PKIX_CERTCHAINCHECKERSETCERTCHAINCHECKERSTATEFAILED); |
- |
-cleanup: |
- |
- PKIX_DECREF(state); |
- PKIX_DECREF(pKey); |
- PKIX_DECREF(prevPubKey); |
- PKIX_DECREF(currPubKey); |
- PKIX_DECREF(newPubKey); |
- PKIX_DECREF(basicConstraints); |
- PKIX_DECREF(verifyFail); |
- PKIX_DECREF(checkKeyUsageFail); |
- |
- PKIX_RETURN(CERTCHAINCHECKER); |
- |
-} |
- |
-/* |
- * FUNCTION: pkix_SignatureChecker_Initialize |
- * DESCRIPTION: |
- * |
- * Creates a new CertChainChecker and stores it at "pChecker", where it will |
- * be used by pkix_SignatureChecker_Check to check that the public key in |
- * the checker's state is able to successfully validate the certificate's |
- * signature. The PublicKey pointed to by "trustedPubKey" is used to |
- * initialize the checker's state. |
- * |
- * PARAMETERS: |
- * "trustedPubKey" |
- * Address of PublicKey representing the trusted public key used to |
- * initialize the state of this checker. Must be non-NULL. |
- * "certsRemaining" |
- * Number of certificates remaining in the chain. |
- * "pChecker" |
- * 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 CertChainChecker Error if the function fails in a non-fatal way. |
- * Returns a Fatal Error if the function fails in an unrecoverable way. |
- */ |
-PKIX_Error * |
-pkix_SignatureChecker_Initialize( |
- PKIX_PL_PublicKey *trustedPubKey, |
- PKIX_UInt32 certsRemaining, |
- PKIX_CertChainChecker **pChecker, |
- void *plContext) |
-{ |
- pkix_SignatureCheckerState* state = NULL; |
- PKIX_ENTER(CERTCHAINCHECKER, "PKIX_SignatureChecker_Initialize"); |
- PKIX_NULLCHECK_TWO(pChecker, trustedPubKey); |
- |
- PKIX_CHECK(pkix_SignatureCheckerState_Create |
- (trustedPubKey, certsRemaining, &state, plContext), |
- PKIX_SIGNATURECHECKERSTATECREATEFAILED); |
- |
- PKIX_CHECK(PKIX_CertChainChecker_Create |
- (pkix_SignatureChecker_Check, |
- PKIX_FALSE, |
- PKIX_FALSE, |
- NULL, |
- (PKIX_PL_Object *) state, |
- pChecker, |
- plContext), |
- PKIX_CERTCHAINCHECKERCREATEFAILED); |
- |
-cleanup: |
- |
- PKIX_DECREF(state); |
- |
- PKIX_RETURN(CERTCHAINCHECKER); |
- |
-} |