зеркало из https://github.com/mozilla/gecko-dev.git
Removed dependency of libjar on psm-glue, bug 36853. Fixed out parameter type problem in PSMComponent::HashEnd
This commit is contained in:
Родитель
871012c4bd
Коммит
74488c46a3
|
@ -2,3 +2,5 @@ nsICertificatePrincipal.idl
|
|||
nsICodebasePrincipal.idl
|
||||
nsIPrincipal.idl
|
||||
nsIScriptSecurityManager.idl
|
||||
nsISignatureVerifier.idl
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ XPIDLSRCS = \
|
|||
nsICodebasePrincipal.idl \
|
||||
nsICertificatePrincipal.idl \
|
||||
nsIAggregatePrincipal.idl \
|
||||
nsISignatureVerifier.idl \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -29,6 +29,7 @@ XPIDLSRCS= \
|
|||
.\nsICertificatePrincipal.idl \
|
||||
.\nsICodebasePrincipal.idl \
|
||||
.\nsIAggregatePrincipal.idl \
|
||||
.\nsISignatureVerifier.idl \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mitchell Stoltz <mstoltz@netscape.com>
|
||||
*/
|
||||
|
||||
/* An interface for calculating secure hashes and verifying signatures*/
|
||||
#include "nsIPrincipal.idl"
|
||||
|
||||
[ptr] native UnsignedCharPtr(unsigned char);
|
||||
|
||||
[uuid(7bdbdb36-1dd2-11b2-a44f-e303037f214d)]
|
||||
interface nsISignatureVerifier : nsISupports
|
||||
{
|
||||
/* Sig Verification Error Codes */
|
||||
const long VERIFY_OK = 0;
|
||||
const long VERIFY_ERROR_UNKNOWN_CA = -8172; /* -8172 is the error code returned by PSM */
|
||||
|
||||
/* Hash Algorithms (based on cmtcmn.h) */
|
||||
const short MD2 = 1;
|
||||
const short MD5 = 2;
|
||||
const short SHA1 = 3;
|
||||
const unsigned long MD2_LENGTH = 16;
|
||||
const unsigned long MD5_LENGTH = 16;
|
||||
const unsigned long SHA1_LENGTH = 20;
|
||||
const unsigned long MAX_HASH_LENGTH = SHA1_LENGTH;
|
||||
|
||||
/* Secure Hashing functions */
|
||||
void hashBegin(in unsigned long alg, out unsigned long id);
|
||||
void hashUpdate(in unsigned long id, in string buf, in unsigned long buflen);
|
||||
[noscript] void hashEnd(in unsigned long id, out UnsignedCharPtr hash,
|
||||
out unsigned long hashlen, in unsigned long maxLen);
|
||||
|
||||
/* Signature Verification functions */
|
||||
nsIPrincipal createPrincipalFromSignature(in string aSignature,
|
||||
in unsigned long aSignatureLen);
|
||||
nsIPrincipal verifySignature(in string aSignature,
|
||||
in unsigned long aSignatureLen,
|
||||
in string plaintext,
|
||||
in unsigned long plaintextLen,
|
||||
out long errorCode);
|
||||
};
|
||||
|
||||
|
||||
%{C++
|
||||
#define SIGNATURE_VERIFIER_PROGID "component://netscape/psm"
|
||||
%}
|
|
@ -49,35 +49,6 @@ interface nsIPSMComponent : nsISupports
|
|||
* This will send PSM all preferences that we know about.
|
||||
*/
|
||||
void passPrefs();
|
||||
|
||||
/* Sig Verification Error Codes */
|
||||
const long VERIFY_OK = 0;
|
||||
const long VERIFY_NOSIG = -2;
|
||||
const long VERIFY_ERROR_UNKNOWN_CA = -8172;
|
||||
|
||||
/* Hash Algorithms (based on cmtcmn.h) */
|
||||
const short MD2 = 1;
|
||||
const short MD5 = 2;
|
||||
const short SHA1 = 3;
|
||||
const unsigned long MD2_LENGTH = 16;
|
||||
const unsigned long MD5_LENGTH = 16;
|
||||
const unsigned long SHA1_LENGTH = 20;
|
||||
const unsigned long MAX_HASH_LENGTH = SHA1_LENGTH;
|
||||
|
||||
/* Secure Hashing functions */
|
||||
void hashBegin(in unsigned long alg, out unsigned long id);
|
||||
void hashUpdate(in unsigned long id, in string buf, in unsigned long buflen);
|
||||
void hashEnd(in unsigned long id, out string hash, out unsigned long hashlen,
|
||||
in unsigned long maxLen);
|
||||
|
||||
/* Signature Verification functions */
|
||||
void verifyRSABegin(out unsigned long id);
|
||||
void verifyRSAUpdate(in unsigned long id, in string buf,
|
||||
in unsigned long buflen);
|
||||
void verifyRSAEnd(in unsigned long id, in string plaintext,
|
||||
in unsigned long plaintextLen,
|
||||
in boolean keepCert, out nsIPrincipal principal, out long result);
|
||||
nsIPrincipal CreatePrincipalFromCert(in unsigned long certID);
|
||||
};
|
||||
|
||||
%{C++
|
||||
|
|
|
@ -120,9 +120,10 @@ nsPSMComponent::CreatePSMComponent(nsISupports* aOuter, REFNSIID aIID, void **aR
|
|||
}
|
||||
|
||||
/* nsISupports Implementation for the class */
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS2(nsPSMComponent,
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS3(nsPSMComponent,
|
||||
nsIPSMComponent,
|
||||
nsIContentHandler);
|
||||
nsIContentHandler,
|
||||
nsISignatureVerifier);
|
||||
|
||||
#define INIT_NUM_PREFS 100
|
||||
/* preference types */
|
||||
|
@ -758,9 +759,9 @@ nsPSMComponent::HandleContent(const char * aContentType,
|
|||
}
|
||||
|
||||
|
||||
//-----------------------------------------
|
||||
// Secure Hash Functions
|
||||
//-----------------------------------------
|
||||
//---------------------------------------------
|
||||
// Functions Implenenting NSISignatureVerifier
|
||||
//---------------------------------------------
|
||||
NS_IMETHODIMP
|
||||
nsPSMComponent::HashBegin(PRUint32 alg, PRUint32* id)
|
||||
{
|
||||
|
@ -791,8 +792,8 @@ nsPSMComponent::HashUpdate(PRUint32 id, const char* buf, PRUint32 buflen)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPSMComponent::HashEnd(PRUint32 id, char** hash, PRUint32* hashlen,
|
||||
PRUint32 maxLen)
|
||||
nsPSMComponent::HashEnd(PRUint32 id, unsigned char** hash,
|
||||
PRUint32* hashLen, PRUint32 maxLen)
|
||||
{
|
||||
if (!hash)
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
|
@ -801,147 +802,105 @@ nsPSMComponent::HashEnd(PRUint32 id, char** hash, PRUint32* hashlen,
|
|||
if (NS_FAILED(GetControlConnection( &controlConnection )))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if(CMT_HASH_End(controlConnection, id, (unsigned char*)*hash,
|
||||
(CMUint32*)hashlen, maxLen) != CMTSuccess)
|
||||
if(CMT_HASH_End(controlConnection, id, *hash,
|
||||
(CMUint32*)hashLen, maxLen) != CMTSuccess)
|
||||
return NS_ERROR_FAILURE;
|
||||
CMT_HASH_Destroy(controlConnection, id);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-----------------------------------------
|
||||
// Signature Verification Functions
|
||||
//-----------------------------------------
|
||||
NS_IMETHODIMP
|
||||
nsPSMComponent::CreatePrincipalFromSignature(const char* aRSABuf, PRUint32 aRSABufLen,
|
||||
nsIPrincipal** aPrincipal)
|
||||
{
|
||||
PRInt32 errorCode;
|
||||
return VerifySignature(aRSABuf, aRSABufLen, nsnull, 0, &errorCode, aPrincipal);
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(void)
|
||||
UselessPK7DataSink(void* arg, const char* buf, CMUint32 len)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPSMComponent::VerifyRSABegin(PRUint32* id)
|
||||
nsPSMComponent::VerifySignature(const char* aRSABuf, PRUint32 aRSABufLen,
|
||||
const char* aPlaintext, PRUint32 aPlaintextLen,
|
||||
PRInt32* aErrorCode,
|
||||
nsIPrincipal** aPrincipal)
|
||||
{
|
||||
if (!id)
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
if (!aPrincipal || !aErrorCode)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
*aErrorCode = 0;
|
||||
*aPrincipal = nsnull;
|
||||
|
||||
CMT_CONTROL *controlConnection;
|
||||
if (NS_FAILED(GetControlConnection( &controlConnection )))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
//-- Decode the signature stream
|
||||
CMUint32 decoderID;
|
||||
CMInt32* blah = nsnull;
|
||||
CMTStatus result = CMT_PKCS7DecoderStart(controlConnection, nsnull,
|
||||
(CMUint32*)id, blah,
|
||||
&decoderID, blah,
|
||||
UselessPK7DataSink, nsnull);
|
||||
if (result == CMTSuccess)
|
||||
return NS_OK;
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPSMComponent::VerifyRSAUpdate(PRUint32 id, const char* buf, PRUint32 buflen)
|
||||
{
|
||||
CMT_CONTROL *controlConnection;
|
||||
if (NS_FAILED(GetControlConnection( &controlConnection )))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
CMTStatus result = CMT_PKCS7DecoderUpdate(controlConnection, id, buf, buflen);
|
||||
if (result == CMTSuccess)
|
||||
return NS_OK;
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPSMComponent::VerifyRSAEnd(PRUint32 id, const char* plaintext,
|
||||
PRUint32 plaintextLen,
|
||||
PRBool aKeepCert,
|
||||
nsIPrincipal** aPrincipal,
|
||||
PRInt32* aVerifyError)
|
||||
{
|
||||
*aVerifyError = -1;
|
||||
CMT_CONTROL *controlConnection;
|
||||
if (NS_FAILED(GetControlConnection( &controlConnection )))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (result != CMTSuccess) return NS_ERROR_FAILURE;
|
||||
result = CMT_PKCS7DecoderUpdate(controlConnection, decoderID, aRSABuf, aRSABufLen);
|
||||
if (result != CMTSuccess) return NS_ERROR_FAILURE;
|
||||
CMUint32 contentInfo;
|
||||
CMTStatus result = CMT_PKCS7DecoderFinish(controlConnection,
|
||||
id, &contentInfo);
|
||||
if (result != CMTSuccess)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
//-- Make sure a signature is present
|
||||
CMInt32 isSigned;
|
||||
result = CMT_GetNumericAttribute(controlConnection, contentInfo,
|
||||
SSM_FID_P7CINFO_IS_SIGNED, &isSigned);
|
||||
if (result != CMTSuccess) return NS_ERROR_FAILURE;
|
||||
if (!isSigned)
|
||||
{
|
||||
*aPrincipal = nsnull;
|
||||
*aVerifyError = nsIPSMComponent::VERIFY_NOSIG;
|
||||
return NS_OK;
|
||||
}
|
||||
// SHA1 hash the plaintext to compare it to the signature
|
||||
CMUint32 hashId;
|
||||
CMT_HashCreate(controlConnection, nsIPSMComponent::SHA1, &hashId);
|
||||
CMT_HASH_Begin(controlConnection, hashId);
|
||||
result = CMT_HASH_Update(controlConnection, hashId,
|
||||
(const unsigned char*)plaintext, plaintextLen);
|
||||
result = CMT_PKCS7DecoderFinish(controlConnection,
|
||||
decoderID, &contentInfo);
|
||||
if (result != CMTSuccess) return NS_ERROR_FAILURE;
|
||||
|
||||
unsigned char* hash = (unsigned char*)PR_MALLOC(nsIPSMComponent::SHA1_LENGTH);
|
||||
if (!hash) return NS_ERROR_OUT_OF_MEMORY;
|
||||
CMUint32 hashLen;
|
||||
result = CMT_HASH_End(controlConnection, hashId, hash,
|
||||
&hashLen, nsIPSMComponent::SHA1_LENGTH);
|
||||
NS_ASSERTION(hashLen == nsIPSMComponent::SHA1_LENGTH,
|
||||
"PSMComponent: Hash too short.");
|
||||
CMT_HASH_Destroy(controlConnection, hashId);
|
||||
if (result != CMTSuccess)
|
||||
CMTItem hashItem;
|
||||
hashItem.data = 0;
|
||||
hashItem.len = 0;
|
||||
//-- If a plaintext was provided, hash it.
|
||||
if (aPlaintext)
|
||||
{
|
||||
PR_FREEIF(hash);
|
||||
return NS_ERROR_FAILURE;
|
||||
CMUint32 hashId;
|
||||
CMT_HashCreate(controlConnection, nsISignatureVerifier::SHA1, &hashId);
|
||||
CMT_HASH_Begin(controlConnection, hashId);
|
||||
CMTStatus result = CMT_HASH_Update(controlConnection, hashId,
|
||||
(const unsigned char*)aPlaintext, aPlaintextLen);
|
||||
if (result != CMTSuccess) return NS_ERROR_FAILURE;
|
||||
|
||||
unsigned char* hash = (unsigned char*)PR_MALLOC(nsISignatureVerifier::SHA1_LENGTH);
|
||||
if (!hash) return NS_ERROR_OUT_OF_MEMORY;
|
||||
CMUint32 hashLen;
|
||||
result = CMT_HASH_End(controlConnection, hashId, hash,
|
||||
&hashLen, nsISignatureVerifier::SHA1_LENGTH);
|
||||
if (result != CMTSuccess)
|
||||
{
|
||||
PR_FREEIF(hash);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
NS_ASSERTION(hashLen == nsISignatureVerifier::SHA1_LENGTH,
|
||||
"PSMComponent: Hash too short.");
|
||||
CMT_HASH_Destroy(controlConnection, hashId);
|
||||
hashItem.data = hash;
|
||||
hashItem.len = hashLen;
|
||||
}
|
||||
|
||||
//-- Verify signature
|
||||
CMTItemStr hashItem;
|
||||
hashItem.data = hash;
|
||||
hashItem.len = hashLen;
|
||||
// We need to call this function even if we're only creating a principal, not
|
||||
// verifying, because PSM won't give us certificate information unless this
|
||||
// function has been called.
|
||||
result = CMT_PKCS7VerifyDetachedSignature(controlConnection, contentInfo,
|
||||
6 /* =Object Signing Cert */,
|
||||
3 /* =SHA1 algorithm (MD5=2)*/,
|
||||
(CMUint32)aKeepCert,
|
||||
&hashItem, (CMInt32*)aVerifyError);
|
||||
PR_FREEIF(hash);
|
||||
1,/* Save Certificate */
|
||||
&hashItem, (CMInt32*)aErrorCode);
|
||||
|
||||
if (result != CMTSuccess) return NS_ERROR_FAILURE;
|
||||
//-- Did it verify?
|
||||
if (aPlaintext && *aErrorCode != 0) return NS_OK; // Verification failed.
|
||||
|
||||
CMUint32 certID;
|
||||
result = CMT_GetRIDAttribute(controlConnection, contentInfo,
|
||||
SSM_FID_P7CINFO_SIGNER_CERT, &certID);
|
||||
if ((result != CMTSuccess) || !certID) return NS_OK; // No signature present
|
||||
|
||||
if (*aVerifyError != 0)
|
||||
*aPrincipal = nsnull;
|
||||
else
|
||||
{
|
||||
//-- Generate a principal from the cert
|
||||
CMUint32 certID;
|
||||
result = CMT_GetRIDAttribute(controlConnection, contentInfo,
|
||||
SSM_FID_P7CINFO_SIGNER_CERT, &certID);
|
||||
if (result != CMTSuccess) return NS_ERROR_FAILURE;
|
||||
if (NS_FAILED(CreatePrincipalFromCert(certID, aPrincipal)))
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
CMT_PKCS7DestroyContentInfo(controlConnection, contentInfo);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPSMComponent::CreatePrincipalFromCert(PRUint32 aCertID, nsIPrincipal** aPrincipal)
|
||||
{
|
||||
CMT_CONTROL *controlConnection;
|
||||
if (NS_FAILED(GetControlConnection( &controlConnection )))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
//-- Read cert ID
|
||||
CMTStatus result;
|
||||
|
||||
CMTItem fingerprint;
|
||||
result = CMT_GetStringAttribute(controlConnection, aCertID,
|
||||
result = CMT_GetStringAttribute(controlConnection, certID,
|
||||
SSM_FID_CERT_FINGERPRINT, &fingerprint);
|
||||
if (result != CMTSuccess) return NS_ERROR_FAILURE;
|
||||
|
||||
|
@ -960,11 +919,11 @@ nsPSMComponent::CreatePrincipalFromCert(PRUint32 aCertID, nsIPrincipal** aPrinci
|
|||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
|
||||
CMTItem common;
|
||||
result = CMT_GetStringAttribute(controlConnection, aCertID,
|
||||
result = CMT_GetStringAttribute(controlConnection, certID,
|
||||
SSM_FID_CERT_COMMON_NAME, &common);
|
||||
if (result != CMTSuccess) return NS_ERROR_FAILURE;
|
||||
CMTItem subject;
|
||||
result = CMT_GetStringAttribute(controlConnection, aCertID,
|
||||
result = CMT_GetStringAttribute(controlConnection, certID,
|
||||
SSM_FID_CERT_SUBJECT_NAME, &subject);
|
||||
if (result != CMTSuccess) return NS_ERROR_FAILURE;
|
||||
|
||||
|
@ -990,4 +949,3 @@ nsPSMComponent::CreatePrincipalFromCert(PRUint32 aCertID, nsIPrincipal** aPrinci
|
|||
Recycle(commonChar);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include "nscore.h"
|
||||
#include "nsIPSMComponent.h"
|
||||
#include "nsISignatureVerifier.h"
|
||||
#include "nsIStringBundle.h"
|
||||
|
||||
#include "nsIContentHandler.h"
|
||||
|
@ -33,7 +34,9 @@
|
|||
#define NS_PSMCOMPONENT_CID {0xddcae170, 0x5412, 0x11d3, {0xbb, 0xc8, 0x00, 0x00, 0x86, 0x1d, 0x12, 0x37}}
|
||||
|
||||
// Implementation of the PSM component interface.
|
||||
class nsPSMComponent : public nsIPSMComponent, public nsIContentHandler
|
||||
class nsPSMComponent : public nsIPSMComponent,
|
||||
public nsIContentHandler,
|
||||
public nsISignatureVerifier
|
||||
{
|
||||
public:
|
||||
NS_DEFINE_STATIC_CID_ACCESSOR( NS_PSMCOMPONENT_CID );
|
||||
|
@ -44,6 +47,7 @@ public:
|
|||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIPSMCOMPONENT
|
||||
NS_DECL_NSICONTENTHANDLER
|
||||
NS_DECL_NSISIGNATUREVERIFIER
|
||||
|
||||
static NS_METHOD CreatePSMComponent(nsISupports* aOuter, REFNSIID aIID, void **aResult);
|
||||
|
||||
|
|
|
@ -100,6 +100,13 @@ interface nsIZipReader : nsISupports
|
|||
* be called before getPrincipal.
|
||||
*/
|
||||
void getCertificatePrincipal(in string aEntryName, out nsIPrincipal aPrincipal);
|
||||
|
||||
/**
|
||||
* Verifies aData against a digital signature stored in the archive. Returns
|
||||
* a principal if verification succeeds, null otherwise.
|
||||
*/
|
||||
nsIPrincipal verifyExternalData(in string aEntryName, in string aData,
|
||||
in unsigned long aLength);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -33,10 +33,6 @@
|
|||
#include "plbase64.h"
|
||||
#include "nsIConsoleService.h"
|
||||
|
||||
#ifndef XP_MAC
|
||||
#include "nsIPSMComponent.h"
|
||||
#endif
|
||||
|
||||
#ifdef XP_UNIX
|
||||
#include <sys/stat.h>
|
||||
#elif defined (XP_PC)
|
||||
|
@ -298,18 +294,11 @@ nsJAR::GetInputStream(const char *aFilename, nsIInputStream **result)
|
|||
NS_IMETHODIMP
|
||||
nsJAR::GetCertificatePrincipal(const char* aFilename, nsIPrincipal** aPrincipal)
|
||||
{
|
||||
#ifdef XP_MAC
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
#else
|
||||
//-- Parameter check
|
||||
if (!aPrincipal)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
*aPrincipal = nsnull;
|
||||
|
||||
DumpMetadata("GetPrincipal");
|
||||
if (!mParsedManifest)
|
||||
ParseManifest();
|
||||
|
||||
PRInt16 requestedStatus;
|
||||
if (aFilename)
|
||||
{
|
||||
|
@ -323,18 +312,24 @@ nsJAR::GetCertificatePrincipal(const char* aFilename, nsIPrincipal** aPrincipal)
|
|||
}
|
||||
if (!manItem->step2Complete)
|
||||
{
|
||||
//-- Creating an input stream causes step 2 of verification
|
||||
nsCOMPtr<nsIInputStream> tempStream;
|
||||
if (NS_FAILED(CreateInputStream(aFilename, PR_TRUE, getter_AddRefs(tempStream))))
|
||||
return NS_ERROR_FAILURE;
|
||||
NS_ASSERTION(manItem->step2Complete, "Verification step 2 is not complete");
|
||||
if (!manItem->step2Complete)
|
||||
return NS_ERROR_FAILURE;
|
||||
NS_ASSERTION(manItem->step2Complete,
|
||||
"nsJAR: Attempt to get principal before verification.");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
requestedStatus = manItem->status;
|
||||
}
|
||||
else // User wants identity of signer w/o verifying any entries
|
||||
{
|
||||
if (!mParsedManifest)
|
||||
{
|
||||
nsresult rv;
|
||||
NS_WITH_SERVICE(nsISignatureVerifier, verifier, SIGNATURE_VERIFIER_PROGID, &rv);
|
||||
if (NS_FAILED(rv)) // No signature verifier available
|
||||
return NS_ERROR_FAILURE;
|
||||
ParseManifest(verifier);
|
||||
}
|
||||
requestedStatus = mGlobalStatus;
|
||||
}
|
||||
|
||||
if (requestedStatus != nsIZipReader::VALID)
|
||||
ReportError(aFilename, requestedStatus);
|
||||
|
@ -344,7 +339,15 @@ nsJAR::GetCertificatePrincipal(const char* aFilename, nsIPrincipal** aPrincipal)
|
|||
NS_IF_ADDREF(*aPrincipal);
|
||||
}
|
||||
return NS_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsJAR::VerifyExternalData(const char* aFilename, const char* aData, PRUint32 aLen,
|
||||
nsIPrincipal** result)
|
||||
{
|
||||
if (NS_FAILED(VerifyEntry(aFilename, aData, aLen)))
|
||||
return NS_ERROR_FAILURE;
|
||||
return GetCertificatePrincipal(aFilename, result);
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
|
@ -431,11 +434,8 @@ nsJAR::ReadLine(const char** src)
|
|||
#define JAR_SF_HEADER (const char*)"Signature-Version: 1.0"
|
||||
|
||||
nsresult
|
||||
nsJAR::ParseManifest()
|
||||
nsJAR::ParseManifest(nsISignatureVerifier* verifier)
|
||||
{
|
||||
#ifdef XP_MAC
|
||||
return NS_OK;
|
||||
#else
|
||||
//-- Verification Step 1
|
||||
if (mParsedManifest)
|
||||
return NS_OK;
|
||||
|
@ -464,7 +464,7 @@ return NS_OK;
|
|||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
//-- Parse it
|
||||
rv = ParseOneFile(manifestBuffer, JAR_MF);
|
||||
rv = ParseOneFile(verifier, manifestBuffer, JAR_MF);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
DumpMetadata("PM Pass 1 End");
|
||||
|
||||
|
@ -497,23 +497,30 @@ return NS_OK;
|
|||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
//-- Verify that the signature file is a valid signature of the SF file
|
||||
rv = VerifySignature(manifestBuffer, manifestLen,
|
||||
sigBuffer, sigLen, getter_AddRefs(mPrincipal), &mGlobalStatus);
|
||||
PRInt32 verifyError;
|
||||
rv = verifier->VerifySignature(sigBuffer, sigLen, manifestBuffer, manifestLen,
|
||||
&verifyError, getter_AddRefs(mPrincipal));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (mPrincipal)
|
||||
mGlobalStatus = nsIZipReader::VALID;
|
||||
else if (verifyError == nsISignatureVerifier::VERIFY_ERROR_UNKNOWN_CA)
|
||||
mGlobalStatus = nsIZipReader::INVALID_UNKNOWN_CA;
|
||||
else
|
||||
mGlobalStatus = nsIZipReader::INVALID_SIG;
|
||||
|
||||
//-- Parse the SF file. If the verification above failed, principal
|
||||
// is null, and ParseOneFile will mark the relevant entries as invalid.
|
||||
// if ParseOneFile fails, then it has no effect, and we can safely
|
||||
// continue to the next SF file, or return.
|
||||
ParseOneFile(manifestBuffer, JAR_SF);
|
||||
ParseOneFile(verifier, manifestBuffer, JAR_SF);
|
||||
DumpMetadata("PM Pass 2 End");
|
||||
|
||||
return NS_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsJAR::ParseOneFile(const char* filebuf, PRInt16 aFileType)
|
||||
nsJAR::ParseOneFile(nsISignatureVerifier* verifier,
|
||||
const char* filebuf, PRInt16 aFileType)
|
||||
{
|
||||
//-- Check file header
|
||||
const char* nextLineStart = filebuf;
|
||||
|
@ -579,7 +586,7 @@ nsJAR::ParseOneFile(const char* filebuf, PRInt16 aFileType)
|
|||
else //-- calculate section digest
|
||||
{
|
||||
PRUint32 sectionLength = curPos - sectionStart;
|
||||
CalculateDigest(sectionStart, sectionLength,
|
||||
CalculateDigest(verifier, sectionStart, sectionLength,
|
||||
&(curItemMF->calculatedSectionDigest));
|
||||
//-- Save item in the hashtable
|
||||
nsStringKey itemKey(curItemName);
|
||||
|
@ -691,15 +698,17 @@ nsJAR::ParseOneFile(const char* filebuf, PRInt16 aFileType)
|
|||
} //ParseOneFile()
|
||||
|
||||
nsresult
|
||||
nsJAR::VerifyEntry(const char* aEntryName, char* aEntryData,
|
||||
nsJAR::VerifyEntry(const char* aEntryName, const char* aEntryData,
|
||||
PRUint32 aLen)
|
||||
{
|
||||
#ifndef XP_MAC
|
||||
nsresult rv;
|
||||
NS_WITH_SERVICE(nsISignatureVerifier, verifier, SIGNATURE_VERIFIER_PROGID, &rv);
|
||||
if (NS_FAILED(rv)) return NS_OK; // No verifier available; just continue.
|
||||
|
||||
//-- Verification Step 2
|
||||
// Check that verification is supported and step 1 has been done
|
||||
|
||||
if (!mParsedManifest)
|
||||
ParseManifest();
|
||||
ParseManifest(verifier);
|
||||
NS_ASSERTION(mParsedManifest,
|
||||
"Verification step 2 called before step 1 complete");
|
||||
if (!mParsedManifest) return NS_ERROR_FAILURE;
|
||||
|
@ -717,25 +726,25 @@ nsJAR::VerifyEntry(const char* aEntryName, char* aEntryData,
|
|||
else
|
||||
{ //-- Calculate and compare digests
|
||||
char* calculatedEntryDigest;
|
||||
nsresult rv = CalculateDigest(aEntryData, aLen, &calculatedEntryDigest);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = CalculateDigest(verifier, aEntryData, aLen, &calculatedEntryDigest);
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
if (PL_strcmp(manItem->storedEntryDigest, calculatedEntryDigest) != 0)
|
||||
manItem->status = nsIZipReader::INVALID_ENTRY;
|
||||
JAR_NULLFREE(calculatedEntryDigest)
|
||||
JAR_NULLFREE(manItem->storedEntryDigest)
|
||||
}
|
||||
}
|
||||
|
||||
manItem->step2Complete = PR_TRUE;
|
||||
if (NS_SUCCEEDED(rv))
|
||||
manItem->step2Complete = PR_TRUE;
|
||||
DumpMetadata("VerifyEntry end");
|
||||
#endif
|
||||
return NS_OK;
|
||||
return rv;
|
||||
}
|
||||
|
||||
void nsJAR::ReportError(const char* aFilename, PRInt16 errorCode)
|
||||
{
|
||||
//-- Generate error message
|
||||
nsAutoString message; message.AssignWithConversion("Signature Verification Error: the signature on ");
|
||||
nsAutoString message;
|
||||
message.AssignWithConversion("Signature Verification Error: the signature on ");
|
||||
if (aFilename)
|
||||
message.AppendWithConversion(aFilename);
|
||||
else
|
||||
|
@ -747,27 +756,23 @@ void nsJAR::ReportError(const char* aFilename, PRInt16 errorCode)
|
|||
message.AppendWithConversion("the archive did not contain a valid PKCS7 signature.");
|
||||
break;
|
||||
case nsIZipReader::INVALID_SIG:
|
||||
message.AppendWithConversion("the digital signature (*.RSA) file is not a valid signature of ");
|
||||
message.AppendWithConversion("the signature instruction file (*.SF).");
|
||||
message.AppendWithConversion("the digital signature (*.RSA) file is not a valid signature of the signature instruction file (*.SF).");
|
||||
break;
|
||||
case nsIZipReader::INVALID_UNKNOWN_CA:
|
||||
message.AppendWithConversion("the certificate used to sign this file has an unrecognized issuer.");
|
||||
break;
|
||||
case nsIZipReader::INVALID_MANIFEST:
|
||||
message.AppendWithConversion("the signature instruction file (*.SF) does not contain a valid hash ");
|
||||
message.AppendWithConversion("of the MANIFEST.MF file.");
|
||||
message.AppendWithConversion("the signature instruction file (*.SF) does not contain a valid hash of the MANIFEST.MF file.");
|
||||
break;
|
||||
case nsIZipReader::INVALID_ENTRY:
|
||||
message.AppendWithConversion("the MANIFEST.MF file does not contain a valid hash of the file ");
|
||||
message.AppendWithConversion("being verified.");
|
||||
message.AppendWithConversion("the MANIFEST.MF file does not contain a valid hash of the file being verified.");
|
||||
break;
|
||||
default:
|
||||
message.AppendWithConversion("of an unknown problem.");
|
||||
}
|
||||
|
||||
// Report error in JS console
|
||||
nsCOMPtr<nsIConsoleService> console
|
||||
(do_GetService("mozilla.consoleservice.1"));
|
||||
nsCOMPtr<nsIConsoleService> console(do_GetService("mozilla.consoleservice.1"));
|
||||
if (console)
|
||||
{
|
||||
PRUnichar* messageUni = message.ToNewUnicode();
|
||||
|
@ -775,7 +780,9 @@ void nsJAR::ReportError(const char* aFilename, PRInt16 errorCode)
|
|||
console->LogStringMessage(messageUni);
|
||||
nsAllocator::Free(messageUni);
|
||||
}
|
||||
#ifndef DEBUG
|
||||
else // If JS console reporting failed, print to stderr.
|
||||
#endif
|
||||
{
|
||||
char* messageCstr = message.ToNewCString();
|
||||
if (!messageCstr) return;
|
||||
|
@ -813,77 +820,38 @@ nsJAR::RestoreModTime(nsZipItem *aItem, nsIFile *aExtractedFile)
|
|||
return rv;
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
// Hashing and verification functions
|
||||
//----------------------------------------------
|
||||
|
||||
nsresult nsJAR::CalculateDigest(const char* aInBuf, PRUint32 aLen,
|
||||
char** digest)
|
||||
nsresult nsJAR::CalculateDigest(nsISignatureVerifier* verifier,
|
||||
const char* aInBuf, PRUint32 aLen,
|
||||
char** digest)
|
||||
{
|
||||
#ifndef XP_MAC
|
||||
*digest = nsnull;
|
||||
nsresult rv;
|
||||
NS_WITH_SERVICE(nsIPSMComponent, psmComp, PSM_COMPONENT_PROGID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
//-- Calculate the digest
|
||||
PRUint32 id;
|
||||
rv = psmComp->HashBegin(nsIPSMComponent::SHA1, &id);
|
||||
rv = verifier->HashBegin(nsISignatureVerifier::SHA1, &id);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = psmComp->HashUpdate(id, aInBuf, aLen);
|
||||
rv = verifier->HashUpdate(id, aInBuf, aLen);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
PRUint32 len;
|
||||
char* rawDigest = (char*)PR_MALLOC(nsIPSMComponent::SHA1_LENGTH);
|
||||
unsigned char* rawDigest = (unsigned char*)PR_MALLOC(nsISignatureVerifier::SHA1_LENGTH);
|
||||
if (rawDigest == nsnull) return NS_ERROR_OUT_OF_MEMORY;
|
||||
rv = psmComp->HashEnd(id, &rawDigest, &len, nsIPSMComponent::SHA1_LENGTH);
|
||||
rv = verifier->HashEnd(id, &rawDigest, &len, nsISignatureVerifier::SHA1_LENGTH);
|
||||
if (NS_FAILED(rv)) { PR_FREEIF(rawDigest); return rv; }
|
||||
|
||||
//-- Encode the digest in base64
|
||||
*digest = PL_Base64Encode(rawDigest, len, *digest);
|
||||
*digest = PL_Base64Encode((char*)rawDigest, len, *digest);
|
||||
if (!(*digest)) { PR_FREEIF(rawDigest); return NS_ERROR_OUT_OF_MEMORY; }
|
||||
|
||||
PR_FREEIF(rawDigest);
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsJAR::VerifySignature(const char* sfBuf, PRUint32 sfBufLen,
|
||||
const char* rsaBuf, PRUint32 rsaBufLen,
|
||||
nsIPrincipal** aPrincipal, PRInt16* status)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
#ifndef XP_MAC
|
||||
NS_WITH_SERVICE(nsIPSMComponent, psmComp, PSM_COMPONENT_PROGID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
PRUint32 id;
|
||||
rv = psmComp->VerifyRSABegin(&id);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = psmComp->VerifyRSAUpdate(id, rsaBuf, rsaBufLen);
|
||||
PRInt32 psmStatus;
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = psmComp->VerifyRSAEnd(id, sfBuf, sfBufLen, PR_TRUE, aPrincipal, &psmStatus);
|
||||
switch (psmStatus)
|
||||
{
|
||||
case nsIPSMComponent::VERIFY_NOSIG:
|
||||
*status = nsIZipReader::NOT_SIGNED; break;
|
||||
case nsIPSMComponent::VERIFY_OK:
|
||||
*status = nsIZipReader::VALID; break;
|
||||
case nsIPSMComponent::VERIFY_ERROR_UNKNOWN_CA:
|
||||
*status = nsIZipReader::INVALID_UNKNOWN_CA; break;
|
||||
default:
|
||||
*status = nsIZipReader::INVALID_SIG;
|
||||
}
|
||||
#endif
|
||||
return rv;
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
// Debugging functions
|
||||
//----------------------------------------------
|
||||
|
||||
#if 0
|
||||
PR_STATIC_CALLBACK(PRBool)
|
||||
PrintManItem(nsHashKey* aKey, void* aData, void* closure)
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include "nsZipArchive.h"
|
||||
#include "zipfile.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsISignatureVerifier.h"
|
||||
|
||||
class nsIInputStream;
|
||||
|
||||
|
@ -87,23 +88,22 @@ class nsJAR : public nsIZipReader
|
|||
PRInt16 mGlobalStatus; // Global signature verification status
|
||||
|
||||
//-- Private functions
|
||||
nsresult ParseManifest();
|
||||
nsresult ParseManifest(nsISignatureVerifier* verifier);
|
||||
void ReportError(const char* aFilename, PRInt16 errorCode);
|
||||
nsresult CreateInputStream(const char* aFilename, PRBool verify,
|
||||
nsIInputStream** result);
|
||||
nsresult LoadEntry(const char* aFilename, char** aBuf,
|
||||
PRUint32* aBufLen = nsnull);
|
||||
PRInt32 ReadLine(const char** src);
|
||||
nsresult ParseOneFile(const char* filebuf, PRInt16 aFileType);
|
||||
nsresult VerifyEntry(const char* aEntryName, char* aEntryData,
|
||||
nsresult ParseOneFile(nsISignatureVerifier* verifier,
|
||||
const char* filebuf, PRInt16 aFileType);
|
||||
nsresult VerifyEntry(const char* aEntryName, const char* aEntryData,
|
||||
PRUint32 aLen);
|
||||
nsresult RestoreModTime(nsZipItem *aItem, nsIFile *aExtractedFile);
|
||||
|
||||
nsresult CalculateDigest(const char* aInBuf, PRUint32 aInBufLen,
|
||||
nsresult CalculateDigest(nsISignatureVerifier* verifier,
|
||||
const char* aInBuf, PRUint32 aInBufLen,
|
||||
char** digest);
|
||||
nsresult VerifySignature(const char* sfBuf, PRUint32 sfBufLen,
|
||||
const char* rsaBuf, PRUint32 rsaBufLen,
|
||||
nsIPrincipal** aPrincipal, PRInt16* status);
|
||||
|
||||
//-- Debugging
|
||||
void DumpMetadata(const char* aMessage);
|
||||
|
|
Загрузка…
Ссылка в новой задаче