Removed dependency of libjar on psm-glue, bug 36853. Fixed out parameter type problem in PSMComponent::HashEnd

This commit is contained in:
mstoltz%netscape.com 2000-05-10 01:49:33 +00:00
Родитель 871012c4bd
Коммит 74488c46a3
10 изменённых файлов: 229 добавлений и 253 удалений

Просмотреть файл

@ -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);