Add a scriptable hash function API. basically what this does is moves the hashing function out of the nsISignatureVerifier.idl and creates a new interface nsICryptoHash which is scriptable. Because of this change, we needed to fix up all of the call sites. r=darin, sr=dveditz, a=shaver

This commit is contained in:
dougt%meer.net 2005-06-01 16:06:53 +00:00
parent 3decf98b20
commit 4c7f9052d3
21 changed files with 537 additions and 437 deletions

View File

@ -46,6 +46,7 @@ MODULE = caps
GRE_MODULE = 1
XPIDLSRCS = \
nsICryptoHash.idl \
nsIScriptSecurityManager.idl \
nsIPrincipal.idl \
nsISignatureVerifier.idl \

123
caps/idl/nsICryptoHash.idl Executable file
View File

@ -0,0 +1,123 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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
* Doug Turner <dougt@meer.net>.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
interface nsIInputStream;
/**
* nsICryptoHash
* This interface provides crytographic hashing algorithms.
*/
[scriptable, uuid(8751865e-b01d-4f33-bc13-b361dde165ed)]
interface nsICryptoHash : nsISupports
{
/**
* Hashing Algorithms. These values are to be used by the
* |init| method to indicate which hashing function to
* use. These values map directly onto the values defined
* in mozilla/security/nss/lib/cryptohi/hasht.h.
*/
const short MD2 = 1;
const short MD5 = 2;
const short SHA1 = 3;
const short SHA256 = 4;
const short SHA384 = 5;
const short SHA512 = 6;
/**
* Initialize the hashing object. This method may be
* called multiple times with different algorithm types.
*
* @param aAlgorithm the algorithm type to be used.
* This value must be one of the above valid
* algorithm types.
*
* @throws NS_ERROR_INVALID_ARG if an unsupported algorithm
* type is passed.
*
* NOTE: This method must be called before any other method on
* this interface is called.
*/
void init(in unsigned long aAlgorithm);
/**
* @param aData a buffer to calculate the hash over
*
* @param aLen the length of the buffer |aData|
*
* @throws NS_ERROR_NOT_INITIALIZED if |init| has not been
* called.
*/
void update([const, array, size_is(aLen)] in octet aData, in unsigned long aLen);
/**
* Calculates and updates a new hash based on a given data stream.
*
* @param aStream an input stream to read from.
*
* @param aLen how much to read from the given |aStream|. Passing
* PR_UINT32_MAX indicates that all data available will be used
* to update the hash.
*
* @throws NS_ERROR_NOT_INITIALIZED if |init| has not been
* called.
*
* @throws NS_ERROR_NOT_AVAILABLE if the requested amount of
* data to be calculated into the hash is not available.
*
*/
void updateFromStream(in nsIInputStream aStream, in unsigned long aLen);
/**
* Completes this hash object and produces the actual hash data.
*
* @param aASCII if true then the returned value is a base-64
* encoded string. if false, then the returned value is
* binary data.
*
* @return a hash of the data that was read by this object. This can
* be either binary data or base 64 encoded.
*
* @throws NS_ERROR_NOT_INITIALIZED if |init| has not been
* called.
*
* NOTE: This method may be called any time after |init|
* is called. This call resets the object to its
* pre-init state.
*/
ACString finish(in PRBool aASCII);
};

View File

@ -36,40 +36,16 @@
*
* ***** END LICENSE BLOCK ***** */
/* An interface for calculating secure hashes and verifying signatures*/
/* An interface for verifying signatures */
#include "nsIPrincipal.idl"
//interface nsIX509Cert;
%{C++
struct HASHContextStr;
%}
[ptr] native UnsignedCharPtr(unsigned char);
[ptr] native HASHContextPtr(HASHContextStr);
[uuid(7bdbdb36-1dd2-11b2-a44f-e303037f214d)]
[uuid(dea87f65-e91e-4119-aa13-aaa2be80cac2)]
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 */
HASHContextPtr hashBegin(in unsigned long alg);
void hashUpdate(in HASHContextPtr id, in string buf, in unsigned long buflen);
[noscript] void hashEnd(in HASHContextPtr id, out UnsignedCharPtr hash,
out unsigned long hashlen, in unsigned long maxLen);
nsIPrincipal verifySignature(in string aSignature,
in unsigned long aSignatureLen,
in string plaintext,

View File

@ -69,6 +69,7 @@
#include "nsCategoryManagerUtils.h"
#include "nsISpamSettings.h"
#include "nsISignatureVerifier.h"
#include "nsICryptoHash.h"
#include "nsNativeCharsetUtils.h"
#include "nsIRssIncomingServer.h"
#include "nsIMsgFolder.h"
@ -847,10 +848,9 @@ nsresult IsRSSArticle(nsIURI * aMsgURI, PRBool *aIsRSSArticle)
nsresult MSGCramMD5(const char *text, PRInt32 text_len, const char *key, PRInt32 key_len, unsigned char *digest)
{
nsresult rv;
unsigned char result[DIGEST_LENGTH];
unsigned char *presult = result;
nsCOMPtr<nsISignatureVerifier> verifier = do_GetService(SIGNATURE_VERIFIER_CONTRACTID, &rv);
nsCAutoString hash;
nsCOMPtr<nsICryptoHash> hasher = do_CreateInstance("@mozilla.org/security/hash;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
@ -863,17 +863,16 @@ nsresult MSGCramMD5(const char *text, PRInt32 text_len, const char *key, PRInt32
if (key_len > 64)
{
HASHContextStr *tctx;
PRUint32 resultLen;
rv = verifier->HashBegin(nsISignatureVerifier::MD5, &tctx);
NS_ENSURE_SUCCESS(rv, rv);
rv = verifier->HashUpdate(tctx, key, key_len);
NS_ENSURE_SUCCESS(rv, rv);
rv = verifier->HashEnd(tctx, &presult, &resultLen, DIGEST_LENGTH);
rv = hasher->Init(nsICryptoHash::MD5);
NS_ENSURE_SUCCESS(rv, rv);
key = (const char *) result;
rv = hasher->Update((const PRUint8*) key, key_len);
NS_ENSURE_SUCCESS(rv, rv);
rv = hasher->Finish(PR_FALSE, hash);
NS_ENSURE_SUCCESS(rv, rv);
key = hash.get();
key_len = DIGEST_LENGTH;
}
@ -903,21 +902,25 @@ nsresult MSGCramMD5(const char *text, PRInt32 text_len, const char *key, PRInt32
/*
* perform inner MD5
*/
HASHContextStr *context;
PRUint32 resultLen;
nsCAutoString result;
rv = hasher->Init(nsICryptoHash::MD5); /* init context for 1st pass */
rv = hasher->Update((const PRUint8*)innerPad, 64); /* start with inner pad */
rv = hasher->Update((const PRUint8*)text, text_len); /* then text of datagram */
rv = hasher->Finish(PR_FALSE, result); /* finish up 1st pass */
rv = verifier->HashBegin(nsISignatureVerifier::MD5, &context); /* init context for 1st pass */
rv = verifier->HashUpdate(context, innerPad, 64); /* start with inner pad */
rv = verifier->HashUpdate(context, text, text_len); /* then text of datagram */
rv = verifier->HashEnd(context, &presult, &resultLen, DIGEST_LENGTH); /* finish up 1st pass */
/*
* perform outer MD5
*/
verifier->HashBegin(nsISignatureVerifier::MD5, &context); /* init context for 2nd pass */
rv = verifier->HashUpdate(context, outerPad, 64); /* start with outer pad */
rv = verifier->HashUpdate(context, (const char *) result, 16); /* then results of 1st hash */
rv = verifier->HashEnd(context, &presult, &resultLen, DIGEST_LENGTH); /* finish up 2nd pass */
memcpy(digest, result, DIGEST_LENGTH);
hasher->Init(nsICryptoHash::MD5); /* init context for 2nd pass */
rv = hasher->Update((const PRUint8*)outerPad, 64); /* start with outer pad */
rv = hasher->Update((const PRUint8*)result.get(), 16);/* then results of 1st hash */
rv = hasher->Finish(PR_FALSE, result); /* finish up 2nd pass */
if (result.Length() != DIGEST_LENGTH)
return NS_ERROR_UNEXPECTED;
memcpy(digest, result.get(), DIGEST_LENGTH);
return rv;
}
@ -927,25 +930,27 @@ nsresult MSGCramMD5(const char *text, PRInt32 text_len, const char *key, PRInt32
nsresult MSGApopMD5(const char *text, PRInt32 text_len, const char *password, PRInt32 password_len, unsigned char *digest)
{
nsresult rv;
unsigned char result[DIGEST_LENGTH];
unsigned char *presult = result;
nsCAutoString result;
nsCOMPtr<nsISignatureVerifier> verifier = do_GetService(SIGNATURE_VERIFIER_CONTRACTID, &rv);
nsCOMPtr<nsICryptoHash> hasher = do_CreateInstance("@mozilla.org/security/hash;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = hasher->Init(nsICryptoHash::MD5);
NS_ENSURE_SUCCESS(rv, rv);
HASHContextStr *context;
PRUint32 resultLen;
rv = hasher->Update((const PRUint8*) text, text_len);
NS_ENSURE_SUCCESS(rv, rv);
rv = verifier->HashBegin(nsISignatureVerifier::MD5, &context);
rv = hasher->Update((const PRUint8*) password, password_len);
NS_ENSURE_SUCCESS(rv, rv);
rv = verifier->HashUpdate(context, text, text_len);
rv = hasher->Finish(PR_FALSE, result);
NS_ENSURE_SUCCESS(rv, rv);
rv = verifier->HashUpdate(context, password, password_len);
NS_ENSURE_SUCCESS(rv, rv);
rv = verifier->HashEnd(context, &presult, &resultLen, DIGEST_LENGTH);
NS_ENSURE_SUCCESS(rv, rv);
memcpy(digest, result, DIGEST_LENGTH);
if (result.Length() != DIGEST_LENGTH)
return NS_ERROR_UNEXPECTED;
memcpy(digest, result.get(), DIGEST_LENGTH);
return rv;
}

View File

@ -60,6 +60,7 @@ REQUIRES = xpcom \
pipnss \
necko \
intl \
caps \
$(NULL)
ifndef MOZ_STATIC_MAIL_BUILD

View File

@ -57,6 +57,7 @@ REQUIRES = xpcom \
msgcompose \
necko \
intl \
caps \
$(NULL)
CPPSRCS = \

View File

@ -71,12 +71,12 @@ nsCOMPtr<nsIStringBundle> nsMsgComposeSecure::mSMIMEBundle = nsnull;
#define SMIME_STRBUNDLE_URL "chrome://messenger/locale/am-smime.properties"
static void mime_crypto_write_base64 (void *closure, const char *buf,
unsigned long size);
unsigned long size);
static nsresult PR_CALLBACK mime_encoder_output_fn(const char *buf, PRInt32 size, void *closure);
static nsresult PR_CALLBACK mime_nested_encoder_output_fn (const char *buf, PRInt32 size, void *closure);
static int make_multipart_signed_header_string(PRBool outer_p,
char **header_return,
char **boundary_return);
char **header_return,
char **boundary_return);
static char *mime_make_separator(const char *prefix);
// mscott --> FIX ME...for now cloning code from compose\nsMsgEncode.h/.cpp
@ -101,7 +101,7 @@ MIME_B64EncoderInit(nsresult (*PR_CALLBACK output_fn) (const char *buf, PRInt32
return NS_SUCCEEDED(res) ? returnEncoderData : nsnull;
}
MimeEncoderData *
MimeEncoderData *
MIME_QPEncoderInit(nsresult (*PR_CALLBACK output_fn) (const char *buf, PRInt32 size, void *closure), void *closure)
{
MimeEncoderData *returnEncoderData = nsnull;
@ -115,7 +115,7 @@ MIME_QPEncoderInit(nsresult (*PR_CALLBACK output_fn) (const char *buf, PRInt32 s
return NS_SUCCEEDED(res) ? returnEncoderData : nsnull;
}
MimeEncoderData *
MimeEncoderData *
MIME_UUEncoderInit(char *filename, nsresult (*PR_CALLBACK output_fn) (const char *buf, PRInt32 size, void *closure), void *closure)
{
MimeEncoderData *returnEncoderData = nsnull;
@ -180,17 +180,17 @@ GenerateGlobalRandomBytes(unsigned char *buf, PRInt32 len)
char
*mime_make_separator(const char *prefix)
{
unsigned char rand_buf[13];
GenerateGlobalRandomBytes(rand_buf, 12);
unsigned char rand_buf[13];
GenerateGlobalRandomBytes(rand_buf, 12);
return PR_smprintf("------------%s"
"%02X%02X%02X%02X"
"%02X%02X%02X%02X"
"%02X%02X%02X%02X",
prefix,
rand_buf[0], rand_buf[1], rand_buf[2], rand_buf[3],
rand_buf[4], rand_buf[5], rand_buf[6], rand_buf[7],
rand_buf[8], rand_buf[9], rand_buf[10], rand_buf[11]);
"%02X%02X%02X%02X"
"%02X%02X%02X%02X"
"%02X%02X%02X%02X",
prefix,
rand_buf[0], rand_buf[1], rand_buf[2], rand_buf[3],
rand_buf[4], rand_buf[5], rand_buf[6], rand_buf[7],
rand_buf[8], rand_buf[9], rand_buf[10], rand_buf[11]);
}
// end of copied code which needs fixed....
@ -269,10 +269,10 @@ nsMsgComposeSecure::~nsMsgComposeSecure()
}
if (mSigEncoderData) {
MIME_EncoderDestroy (mSigEncoderData, PR_TRUE);
MIME_EncoderDestroy (mSigEncoderData, PR_TRUE);
}
if (mCryptoEncoderData) {
MIME_EncoderDestroy (mCryptoEncoderData, PR_TRUE);
MIME_EncoderDestroy (mCryptoEncoderData, PR_TRUE);
}
delete [] mBuffer;
@ -477,13 +477,13 @@ NS_IMETHODIMP nsMsgComposeSecure::BeginCryptoEncapsulation(nsOutputFileStream *
mIsDraft = aIsDraft;
if (encryptMessages && signMessage)
mCryptoState = mime_crypto_signed_encrypted;
mCryptoState = mime_crypto_signed_encrypted;
else if (encryptMessages)
mCryptoState = mime_crypto_encrypted;
mCryptoState = mime_crypto_encrypted;
else if (signMessage)
mCryptoState = mime_crypto_clear_signed;
mCryptoState = mime_crypto_clear_signed;
else
PR_ASSERT(0);
PR_ASSERT(0);
aIdentity->GetUnicharAttribute("signing_cert_name", getter_Copies(mSigningCertName));
aIdentity->GetUnicharAttribute("encryption_cert_name", getter_Copies(mEncryptionCertName));
@ -494,23 +494,23 @@ NS_IMETHODIMP nsMsgComposeSecure::BeginCryptoEncapsulation(nsOutputFileStream *
}
switch (mCryptoState)
{
case mime_crypto_clear_signed:
{
case mime_crypto_clear_signed:
rv = MimeInitMultipartSigned(PR_TRUE, sendReport);
break;
case mime_crypto_opaque_signed:
case mime_crypto_opaque_signed:
PR_ASSERT(0); /* #### no api for this yet */
rv = NS_ERROR_NOT_IMPLEMENTED;
break;
case mime_crypto_signed_encrypted:
break;
case mime_crypto_signed_encrypted:
rv = MimeInitEncryption(PR_TRUE, sendReport);
break;
case mime_crypto_encrypted:
break;
case mime_crypto_encrypted:
rv = MimeInitEncryption(PR_FALSE, sendReport);
break;
case mime_crypto_none:
/* This can happen if mime_crypto_hack_certs() decided to turn off
encryption (by asking the user.) */
break;
case mime_crypto_none:
/* This can happen if mime_crypto_hack_certs() decided to turn off
encryption (by asking the user.) */
rv = 1;
break;
default:
@ -528,8 +528,8 @@ NS_IMETHODIMP nsMsgComposeSecure::FinishCryptoEncapsulation(PRBool aAbort, nsIMs
nsresult rv = NS_OK;
if (!aAbort) {
switch (mCryptoState) {
case mime_crypto_clear_signed:
switch (mCryptoState) {
case mime_crypto_clear_signed:
rv = MimeFinishMultipartSigned (PR_TRUE, sendReport);
break;
case mime_crypto_opaque_signed:
@ -538,16 +538,16 @@ NS_IMETHODIMP nsMsgComposeSecure::FinishCryptoEncapsulation(PRBool aAbort, nsIMs
break;
case mime_crypto_signed_encrypted:
rv = MimeFinishEncryption (PR_TRUE, sendReport);
break;
case mime_crypto_encrypted:
rv = MimeFinishEncryption (PR_FALSE, sendReport);
break;
default:
PR_ASSERT(0);
rv = NS_ERROR_FAILURE;
break;
}
}
break;
case mime_crypto_encrypted:
rv = MimeFinishEncryption (PR_FALSE, sendReport);
break;
default:
PR_ASSERT(0);
rv = NS_ERROR_FAILURE;
break;
}
}
return rv;
}
@ -560,41 +560,40 @@ nsresult nsMsgComposeSecure::MimeInitMultipartSigned(PRBool aOuter, nsIMsgSendRe
PRInt32 L;
rv = make_multipart_signed_header_string(aOuter, &header,
&mMultipartSignedBoundary);
&mMultipartSignedBoundary);
if (NS_FAILED(rv)) goto FAIL;
L = strlen(header);
if (aOuter){
/* If this is the outer block, write it to the file. */
/* If this is the outer block, write it to the file. */
if (PRInt32(mStream->write(header, L)) < L) {
rv = MK_MIME_ERROR_WRITING_FILE;
rv = MK_MIME_ERROR_WRITING_FILE;
}
} else {
/* If this is an inner block, feed it through the crypto stream. */
rv = MimeCryptoWriteBlock (header, L);
}
/* If this is an inner block, feed it through the crypto stream. */
rv = MimeCryptoWriteBlock (header, L);
}
PR_Free(header);
if (NS_FAILED(rv)) goto FAIL;
/* Now initialize the crypto library, so that we can compute a hash
on the object which we are signing.
on the object which we are signing.
*/
mHashType = nsIHash::HASH_AlgSHA1;
mHashType = nsICryptoHash::SHA1;
PR_SetError(0,0);
mDataHash = do_CreateInstance(NS_HASH_CONTRACTID, &rv);
mDataHash = do_CreateInstance("@mozilla.org/security/hash;1", &rv);
if (NS_FAILED(rv)) return 0;
rv = mDataHash->Create(mHashType);
rv = mDataHash->Init(mHashType);
if (NS_FAILED(rv)) {
goto FAIL;
}
goto FAIL;
}
PR_SetError(0,0);
rv = mDataHash->Begin();
FAIL:
return rv;
}
@ -607,40 +606,40 @@ nsresult nsMsgComposeSecure::MimeInitEncryption(PRBool aSign, nsIMsgSendReport *
*/
char *s =
PR_smprintf("Content-Type: " APPLICATION_XPKCS7_MIME
"; name=\"smime.p7m\"" CRLF
"Content-Transfer-Encoding: " ENCODING_BASE64 CRLF
"Content-Disposition: attachment"
"; filename=\"smime.p7m\"" CRLF
"Content-Description: %s" CRLF
CRLF,
MIME_SMIME_ENCRYPTED_CONTENT_DESCRIPTION);
PR_smprintf("Content-Type: " APPLICATION_XPKCS7_MIME
"; name=\"smime.p7m\"" CRLF
"Content-Transfer-Encoding: " ENCODING_BASE64 CRLF
"Content-Disposition: attachment"
"; filename=\"smime.p7m\"" CRLF
"Content-Description: %s" CRLF
CRLF,
MIME_SMIME_ENCRYPTED_CONTENT_DESCRIPTION);
PRInt32 L;
if (!s) return NS_ERROR_OUT_OF_MEMORY;
L = strlen(s);
if (PRInt32(mStream->write(s, L)) < L) {
return NS_ERROR_FAILURE;
return NS_ERROR_FAILURE;
}
PR_Free(s);
s = 0;
/* Now initialize the crypto library, so that we can filter the object
to be encrypted through it.
to be encrypted through it.
*/
if (!mIsDraft) {
PRUint32 numCerts;
mCerts->GetLength(&numCerts);
PR_ASSERT(numCerts > 0);
if (numCerts == 0) return NS_ERROR_FAILURE;
if (numCerts == 0) return NS_ERROR_FAILURE;
}
/* Initialize the base64 encoder. */
PR_ASSERT(!mCryptoEncoderData);
mCryptoEncoderData = MIME_B64EncoderInit(mime_encoder_output_fn,
this);
this);
if (!mCryptoEncoderData) {
return NS_ERROR_OUT_OF_MEMORY;
return NS_ERROR_OUT_OF_MEMORY;
}
/* Initialize the encrypter (and add the sender's cert.) */
@ -651,8 +650,8 @@ nsresult nsMsgComposeSecure::MimeInitEncryption(PRBool aSign, nsIMsgSendReport *
rv = mEncryptionCinfo->CreateEncrypted(mCerts);
if (NS_FAILED(rv)) {
SetError(sendReport, NS_LITERAL_STRING("ErrorCanNotEncrypt").get());
goto FAIL;
}
goto FAIL;
}
mEncryptionContext = do_CreateInstance(NS_CMSENCODER_CONTRACTID, &rv);
if (NS_FAILED(rv)) return rv;
@ -668,16 +667,16 @@ nsresult nsMsgComposeSecure::MimeInitEncryption(PRBool aSign, nsIMsgSendReport *
rv = mEncryptionContext->Start(mEncryptionCinfo, mime_crypto_write_base64, mCryptoEncoderData);
if (NS_FAILED(rv)) {
SetError(sendReport, NS_LITERAL_STRING("ErrorCanNotEncrypt").get());
goto FAIL;
}
goto FAIL;
}
/* If we're signing, tack a multipart/signed header onto the front of
the data to be encrypted, and initialize the sign-hashing code too.
the data to be encrypted, and initialize the sign-hashing code too.
*/
if (aSign) {
rv = MimeInitMultipartSigned(PR_FALSE, sendReport);
if (NS_FAILED(rv)) goto FAIL;
}
rv = MimeInitMultipartSigned(PR_FALSE, sendReport);
if (NS_FAILED(rv)) goto FAIL;
}
FAIL:
return rv;
@ -687,30 +686,16 @@ nsresult nsMsgComposeSecure::MimeFinishMultipartSigned (PRBool aOuter, nsIMsgSen
{
int status;
nsresult rv;
PRUint32 sec_item_len;
unsigned char * sec_item_data;
nsCOMPtr<nsICMSMessage> cinfo = do_CreateInstance(NS_CMSMESSAGE_CONTRACTID, &rv);
nsCOMPtr<nsICMSEncoder> encoder = do_CreateInstance(NS_CMSENCODER_CONTRACTID, &rv);
char * header = nsnull;
/* Compute the hash...
*/
mDataHash->ResultLen(mHashType, &sec_item_len);
sec_item_data = (unsigned char *) PR_MALLOC(sec_item_len);
if (!sec_item_data) {
status = NS_ERROR_OUT_OF_MEMORY;
goto FAIL;
}
PR_SetError(0,0);
mDataHash->End(sec_item_data, &sec_item_len, sec_item_len);
status = PR_GetError();
if (status < 0) {
rv = NS_ERROR_FAILURE;
goto FAIL;
}
nsCAutoString hashString;
mDataHash->Finish(PR_FALSE, hashString);
PR_SetError(0,0);
mDataHash = 0;
status = PR_GetError();
@ -718,62 +703,65 @@ nsresult nsMsgComposeSecure::MimeFinishMultipartSigned (PRBool aOuter, nsIMsgSen
/* Write out the headers for the signature.
*/
PRInt32 L;
header =
PR_smprintf(CRLF
"--%s" CRLF
"Content-Type: " APPLICATION_XPKCS7_SIGNATURE
"; name=\"smime.p7s\"" CRLF
"Content-Transfer-Encoding: " ENCODING_BASE64 CRLF
"Content-Disposition: attachment; "
"filename=\"smime.p7s\"" CRLF
"Content-Description: %s" CRLF
CRLF,
mMultipartSignedBoundary,
MIME_SMIME_SIGNATURE_CONTENT_DESCRIPTION);
if (!header) {
PRInt32 L;
header =
PR_smprintf(CRLF
"--%s" CRLF
"Content-Type: " APPLICATION_XPKCS7_SIGNATURE
"; name=\"smime.p7s\"" CRLF
"Content-Transfer-Encoding: " ENCODING_BASE64 CRLF
"Content-Disposition: attachment; "
"filename=\"smime.p7s\"" CRLF
"Content-Description: %s" CRLF
CRLF,
mMultipartSignedBoundary,
MIME_SMIME_SIGNATURE_CONTENT_DESCRIPTION);
if (!header) {
rv = NS_ERROR_OUT_OF_MEMORY;
goto FAIL;
}
goto FAIL;
}
L = strlen(header);
if (aOuter) {
/* If this is the outer block, write it to the file. */
L = strlen(header);
if (aOuter) {
/* If this is the outer block, write it to the file. */
if (PRInt32(mStream->write(header, L)) < L) {
rv = MK_MIME_ERROR_WRITING_FILE;
rv = MK_MIME_ERROR_WRITING_FILE;
}
} else {
/* If this is an inner block, feed it through the crypto stream. */
rv = MimeCryptoWriteBlock (header, L);
rv = MimeCryptoWriteBlock (header, L);
}
PR_Free(header);
PR_Free(header);
/* Create the signature...
*/
PR_ASSERT(mHashType == nsIHash::HASH_AlgSHA1);
PR_ASSERT(mHashType == nsICryptoHash::SHA1);
PR_ASSERT (mSelfSigningCert);
PR_SetError(0,0);
rv = cinfo->CreateSigned(mSelfSigningCert, mSelfEncryptionCert, sec_item_data, sec_item_len);
if (NS_FAILED(rv)) {
rv = cinfo->CreateSigned(mSelfSigningCert, mSelfEncryptionCert, (unsigned char*)hashString.get(), hashString.Length());
if (NS_FAILED(rv)) {
SetError(sendReport, NS_LITERAL_STRING("ErrorCanNotSign").get());
goto FAIL;
}
goto FAIL;
}
/* Initialize the base64 encoder for the signature data.
*/
PR_ASSERT(!mSigEncoderData);
mSigEncoderData =
MIME_B64EncoderInit((aOuter
? mime_encoder_output_fn
: mime_nested_encoder_output_fn),
this);
MIME_B64EncoderInit((aOuter
? mime_encoder_output_fn
: mime_nested_encoder_output_fn),
this);
if (!mSigEncoderData) {
rv = NS_ERROR_OUT_OF_MEMORY;
goto FAIL;
}
rv = NS_ERROR_OUT_OF_MEMORY;
goto FAIL;
}
/* Write out the signature.
*/
@ -781,15 +769,15 @@ nsresult nsMsgComposeSecure::MimeFinishMultipartSigned (PRBool aOuter, nsIMsgSen
rv = encoder->Start(cinfo, mime_crypto_write_base64, mSigEncoderData);
if (NS_FAILED(rv)) {
SetError(sendReport, NS_LITERAL_STRING("ErrorCanNotSign").get());
goto FAIL;
}
goto FAIL;
}
// We're not passing in any data, so no update needed.
rv = encoder->Finish();
if (NS_FAILED(rv)) {
SetError(sendReport, NS_LITERAL_STRING("ErrorCanNotSign").get());
goto FAIL;
}
goto FAIL;
}
/* Shut down the sig's base64 encoder.
*/
@ -802,29 +790,28 @@ nsresult nsMsgComposeSecure::MimeFinishMultipartSigned (PRBool aOuter, nsIMsgSen
/* Now write out the terminating boundary.
*/
{
PRInt32 L;
char *header = PR_smprintf(CRLF "--%s--" CRLF,
mMultipartSignedBoundary);
PR_Free(mMultipartSignedBoundary);
mMultipartSignedBoundary = 0;
PRInt32 L;
char *header = PR_smprintf(CRLF "--%s--" CRLF,
mMultipartSignedBoundary);
PR_Free(mMultipartSignedBoundary);
mMultipartSignedBoundary = 0;
if (!header) {
rv = NS_ERROR_OUT_OF_MEMORY;
goto FAIL;
}
L = strlen(header);
if (aOuter) {
/* If this is the outer block, write it to the file. */
if (PRInt32(mStream->write(header, L)) < L)
rv = MK_MIME_ERROR_WRITING_FILE;
if (!header) {
rv = NS_ERROR_OUT_OF_MEMORY;
goto FAIL;
}
L = strlen(header);
if (aOuter) {
/* If this is the outer block, write it to the file. */
if (PRInt32(mStream->write(header, L)) < L)
rv = MK_MIME_ERROR_WRITING_FILE;
} else {
/* If this is an inner block, feed it through the crypto stream. */
rv = MimeCryptoWriteBlock (header, L);
}
/* If this is an inner block, feed it through the crypto stream. */
rv = MimeCryptoWriteBlock (header, L);
}
}
FAIL:
PR_FREEIF(sec_item_data);
return rv;
}
@ -837,13 +824,13 @@ nsresult nsMsgComposeSecure::MimeFinishEncryption (PRBool aSign, nsIMsgSendRepor
nsresult rv;
/* If this object is both encrypted and signed, close off the
signature first (since it's inside.) */
signature first (since it's inside.) */
if (aSign) {
rv = MimeFinishMultipartSigned (PR_FALSE, sendReport);
rv = MimeFinishMultipartSigned (PR_FALSE, sendReport);
if (NS_FAILED(rv)) {
goto FAIL;
}
}
}
/* Close off the opaque encrypted blob.
*/
@ -862,7 +849,7 @@ nsresult nsMsgComposeSecure::MimeFinishEncryption (PRBool aSign, nsIMsgSendRepor
if (NS_FAILED(rv)) {
SetError(sendReport, NS_LITERAL_STRING("ErrorCanNotEncrypt").get());
goto FAIL;
}
}
mEncryptionContext = 0;
@ -910,13 +897,13 @@ nsresult nsMsgComposeSecure::MimeCryptoHackCerts(const char *aRecipients,
certdb->FindEmailSigningCert(mSigningCertName, getter_AddRefs(mSelfSigningCert));
// must have both the signing and encryption certs to sign
if ((mSelfSigningCert == nsnull) && aSign) {
if ((mSelfSigningCert == nsnull) && aSign) {
SetError(sendReport, NS_LITERAL_STRING("NoSenderSigningCert").get());
res = NS_ERROR_FAILURE;
goto FAIL;
}
goto FAIL;
}
if ((mSelfEncryptionCert == nsnull) && aEncrypt) {
if ((mSelfEncryptionCert == nsnull) && aEncrypt) {
SetError(sendReport, NS_LITERAL_STRING("NoSenderEncryptionCert").get());
res = NS_ERROR_FAILURE;
goto FAIL;
@ -930,7 +917,7 @@ nsresult nsMsgComposeSecure::MimeCryptoHackCerts(const char *aRecipients,
}
if (mailboxes) {
pHeader->ParseHeaderAddresses (nsnull, mailboxes, 0, &mailbox_list, &count);
pHeader->ParseHeaderAddresses (nsnull, mailboxes, 0, &mailbox_list, &count);
nsMemory::Free(mailboxes);
mailboxes = nsnull;
}
@ -948,18 +935,18 @@ nsresult nsMsgComposeSecure::MimeCryptoHackCerts(const char *aRecipients,
/* If the message is to be encrypted, then get the recipient certs */
if (aEncrypt) {
mailbox = mailbox_list;
mailbox = mailbox_list;
PRBool already_added_self_cert = PR_FALSE;
for (; count > 0; count--) {
nsCString mailbox_lowercase;
ToLowerCase(nsDependentCString(mailbox), mailbox_lowercase);
for (; count > 0; count--) {
nsCString mailbox_lowercase;
ToLowerCase(nsDependentCString(mailbox), mailbox_lowercase);
nsCOMPtr<nsIX509Cert> cert;
certdb->FindCertByEmailAddress(nsnull, mailbox_lowercase.get(), getter_AddRefs(cert));
PRBool foundValidCert = PR_FALSE;
if (cert) {
if (cert) {
PRUint32 verification_result;
if (NS_SUCCEEDED(
@ -977,14 +964,14 @@ nsresult nsMsgComposeSecure::MimeCryptoHackCerts(const char *aRecipients,
SetErrorWithParam(sendReport, NS_LITERAL_STRING("MissingRecipientEncryptionCert").get(), mailbox);
res = NS_ERROR_FAILURE;
goto FAIL;
}
}
/* #### see if recipient requests `signedData'.
if (...) no_clearsigning_p = PR_TRUE;
(This is the only reason we even bother looking up the certs
of the recipients if we're sending a signed-but-not-encrypted
message.)
*/
/* #### see if recipient requests `signedData'.
if (...) no_clearsigning_p = PR_TRUE;
(This is the only reason we even bother looking up the certs
of the recipients if we're sending a signed-but-not-encrypted
message.)
*/
PRBool isSame;
if (NS_SUCCEEDED(cert->Equals(mSelfEncryptionCert, &isSame))
@ -995,13 +982,13 @@ nsresult nsMsgComposeSecure::MimeCryptoHackCerts(const char *aRecipients,
mCerts->AppendElement(cert, PR_FALSE);
// To understand this loop, especially the "+= strlen +1", look at the documentation
// of ParseHeaderAddresses. Basically, it returns a list of zero terminated strings.
mailbox += strlen(mailbox) + 1;
}
mailbox += strlen(mailbox) + 1;
}
if (!already_added_self_cert) {
mCerts->AppendElement(mSelfEncryptionCert, PR_FALSE);
}
}
}
FAIL:
if (mailbox_list) {
nsMemory::Free(mailbox_list);
@ -1015,25 +1002,25 @@ NS_IMETHODIMP nsMsgComposeSecure::MimeCryptoWriteBlock (const char *buf, PRInt32
nsresult rv;
/* If this is a From line, mangle it before signing it. You just know
that something somewhere is going to mangle it later, and that's
going to cause the signature check to fail.
that something somewhere is going to mangle it later, and that's
going to cause the signature check to fail.
(This assumes that, in the cases where From-mangling must happen,
this function is called a line at a time. That happens to be the
case.)
(This assumes that, in the cases where From-mangling must happen,
this function is called a line at a time. That happens to be the
case.)
*/
if (size >= 5 && buf[0] == 'F' && !nsCRT::strncmp(buf, "From ", 5)) {
char mangle[] = ">";
status = MimeCryptoWriteBlock (mangle, 1);
if (status < 0)
return status;
}
if (size >= 5 && buf[0] == 'F' && !nsCRT::strncmp(buf, "From ", 5)) {
char mangle[] = ">";
status = MimeCryptoWriteBlock (mangle, 1);
if (status < 0)
return status;
}
/* If we're signing, or signing-and-encrypting, feed this data into
the computation of the hash. */
the computation of the hash. */
if (mDataHash) {
PR_SetError(0,0);
mDataHash->Update((unsigned char *) buf, size);
PR_SetError(0,0);
mDataHash->Update((const PRUint8*) buf, size);
status = PR_GetError();
if (status < 0) goto FAIL;
}

View File

@ -45,7 +45,7 @@
#include "nsIX509Cert.h"
#include "nsIMimeConverter.h"
#include "nsIStringBundle.h"
#include "nsIHash.h"
#include "nsICryptoHash.h"
#include "nsICMSMessage.h"
#include "nsIArray.h"
#include "nsString.h"
@ -102,7 +102,7 @@ private:
mimeDeliveryCryptoState mCryptoState;
nsOutputFileStream *mStream;
PRInt16 mHashType;
nsCOMPtr<nsIHash> mDataHash;
nsCOMPtr<nsICryptoHash> mDataHash;
MimeEncoderData *mSigEncoderData;
char *mMultipartSignedBoundary;
nsXPIDLString mSigningCertName;

View File

@ -108,9 +108,6 @@ PRLogModuleInfo *IMAP;
#include "nsIProxyInfo.h"
#include "nsEventQueueUtils.h"
#include "nsISSLSocketControl.h"
#if 0
#include "nsIHashAlgorithm.h"
#endif
#define ONE_SECOND ((PRUint32)1000) // one second

View File

@ -38,7 +38,7 @@
#include "nsICMSMessage.h"
#include "nsICMSMessageErrors.h"
#include "nsICMSDecoder.h"
#include "nsIHash.h"
#include "nsICryptoHash.h"
#include "mimemcms.h"
#include "mimecryp.h"
#include "nsMimeTypes.h"
@ -107,7 +107,7 @@ MimeMultipartSignedCMS_initialize (MimeObject *object)
typedef struct MimeMultCMSdata
{
PRInt16 hash_type;
nsCOMPtr<nsIHash> data_hash_context;
nsCOMPtr<nsICryptoHash> data_hash_context;
nsCOMPtr<nsICMSDecoder> sig_decoder_context;
nsCOMPtr<nsICMSMessage> content_info;
char *sender_addr;
@ -201,22 +201,22 @@ MimeMultCMS_init (MimeObject *obj)
if (!nsCRT::strcasecmp(micalg, PARAM_MICALG_MD5) ||
!nsCRT::strcasecmp(micalg, PARAM_MICALG_MD5_2))
hash_type = nsIHash::HASH_AlgMD5;
hash_type = nsICryptoHash::MD5;
else if (!nsCRT::strcasecmp(micalg, PARAM_MICALG_SHA1) ||
!nsCRT::strcasecmp(micalg, PARAM_MICALG_SHA1_2) ||
!nsCRT::strcasecmp(micalg, PARAM_MICALG_SHA1_3) ||
!nsCRT::strcasecmp(micalg, PARAM_MICALG_SHA1_4) ||
!nsCRT::strcasecmp(micalg, PARAM_MICALG_SHA1_5))
hash_type = nsIHash::HASH_AlgSHA1;
hash_type = nsICryptoHash::SHA1;
else if (!nsCRT::strcasecmp(micalg, PARAM_MICALG_MD2))
hash_type = nsIHash::HASH_AlgMD2;
hash_type = nsICryptoHash::MD2;
else
hash_type = nsIHash::HASH_AlgNULL;
hash_type = -1;
PR_Free(micalg);
micalg = 0;
if (hash_type == nsIHash::HASH_AlgNULL) return 0; /* #### bogus message? */
if (hash_type == -1) return 0; /* #### bogus message? */
data = new MimeMultCMSdata;
if (!data)
@ -225,14 +225,14 @@ MimeMultCMS_init (MimeObject *obj)
data->self = obj;
data->hash_type = hash_type;
data->data_hash_context = do_CreateInstance(NS_HASH_CONTRACTID, &rv);
data->data_hash_context = do_CreateInstance("@mozilla.org/security/hash;1", &rv);
if (NS_FAILED(rv)) return 0;
rv = data->data_hash_context->Create(data->hash_type);
rv = data->data_hash_context->Init(data->hash_type);
if (NS_FAILED(rv)) return 0;
PR_SetError(0,0);
data->data_hash_context->Begin();
if (!data->decode_error)
{
data->decode_error = PR_GetError();
@ -335,17 +335,21 @@ MimeMultCMS_data_eof (void *crypto_closure, PRBool abort_p)
return -1;
}
data->data_hash_context->ResultLen(data->hash_type, &data->item_len);
nsCAutoString hashString;
data->data_hash_context->Finish(PR_FALSE, hashString);
PR_SetError(0, 0);
data->item_len = hashString.Length();
data->item_data = new unsigned char[data->item_len];
if (!data->item_data) return MIME_OUT_OF_MEMORY;
memcpy(data->item_data, hashString.get(), data->item_len);
PR_SetError(0, 0);
data->data_hash_context->End(data->item_data, &data->item_len, data->item_len);
if (!data->verify_error) {
data->verify_error = PR_GetError();
}
// Release our reference to nsIHash //
// Release our reference to nsICryptoHash //
data->data_hash_context = 0;
/* At this point, data->item.data contains a digest for the first part.

View File

@ -50,6 +50,7 @@
#include "nsIConsoleService.h"
#include "nscore.h"
#include "nsCRT.h"
#include "nsICryptoHash.h"
#ifdef XP_UNIX
#include <sys/stat.h>
@ -711,7 +712,7 @@ nsJAR::ParseOneFile(nsISignatureVerifier* verifier,
else //-- calculate section digest
{
PRUint32 sectionLength = curPos - sectionStart;
CalculateDigest(verifier, sectionStart, sectionLength,
CalculateDigest(sectionStart, sectionLength,
&(curItemMF->calculatedSectionDigest));
//-- Save item in the hashtable
nsCStringKey itemKey(curItemName);
@ -839,7 +840,7 @@ nsJAR::VerifyEntry(nsISignatureVerifier* verifier,
else
{ //-- Calculate and compare digests
char* calculatedEntryDigest;
nsresult rv = CalculateDigest(verifier, aEntryData, aLen, &calculatedEntryDigest);
nsresult rv = CalculateDigest(aEntryData, aLen, &calculatedEntryDigest);
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
if (PL_strcmp(aManItem->storedEntryDigest, calculatedEntryDigest) != 0)
aManItem->status = nsIJAR::INVALID_ENTRY;
@ -897,33 +898,29 @@ void nsJAR::ReportError(const char* aFilename, PRInt16 errorCode)
}
nsresult nsJAR::CalculateDigest(nsISignatureVerifier* verifier,
const char* aInBuf, PRUint32 aLen,
nsresult nsJAR::CalculateDigest(const char* aInBuf, PRUint32 aLen,
char** digest)
{
*digest = nsnull;
nsresult rv;
//-- Calculate the digest
HASHContextStr* id;
rv = verifier->HashBegin(nsISignatureVerifier::SHA1, &id);
nsCOMPtr<nsICryptoHash> hasher = do_CreateInstance("@mozilla.org/security/hash;1", &rv);
if (NS_FAILED(rv)) return rv;
rv = verifier->HashUpdate(id, aInBuf, aLen);
rv = hasher->Init(nsICryptoHash::SHA1);
if (NS_FAILED(rv)) return rv;
PRUint32 len;
unsigned char* rawDigest = (unsigned char*)PR_MALLOC(nsISignatureVerifier::SHA1_LENGTH);
if (rawDigest == nsnull) return NS_ERROR_OUT_OF_MEMORY;
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((char*)rawDigest, len, *digest);
if (!(*digest)) { PR_FREEIF(rawDigest); return NS_ERROR_OUT_OF_MEMORY; }
PR_FREEIF(rawDigest);
return NS_OK;
rv = hasher->Update((const PRUint8*) aInBuf, aLen);
if (NS_FAILED(rv)) return rv;
nsCAutoString hashString;
rv = hasher->Finish(PR_TRUE, hashString);
if (NS_FAILED(rv)) return rv;
*digest = ToNewCString(hashString);
return *digest ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
}
//----------------------------------------------

View File

@ -144,8 +144,7 @@ class nsJAR : public nsIZipReader, public nsIJAR
nsJARManifestItem* aEntry, const char* aEntryData,
PRUint32 aLen);
nsresult CalculateDigest(nsISignatureVerifier* verifier,
const char* aInBuf, PRUint32 aInBufLen,
nsresult CalculateDigest(const char* aInBuf, PRUint32 aInBufLen,
char** digest);
//-- Debugging

View File

@ -66,6 +66,7 @@ REQUIRES = xpcom \
intl \
uconv \
unicharutil \
caps \
$(ZLIB_REQUIRES) \
$(NULL)

View File

@ -96,18 +96,19 @@ nsHttpDigestAuth::MD5Hash(const char *buf, PRUint32 len)
nsresult rv;
HASHContextStr *hid;
rv = mVerifier->HashBegin(nsISignatureVerifier::MD5, &hid);
rv = mVerifier->Init(nsICryptoHash::MD5);
if (NS_FAILED(rv)) return rv;
// must call HashEnd to destroy |hid|
unsigned char cbuf[DIGEST_LENGTH], *chash = cbuf;
PRUint32 clen;
rv = mVerifier->Update((unsigned char*)buf, len);
if (NS_FAILED(rv)) return rv;
rv = mVerifier->HashUpdate(hid, buf, len);
rv |= mVerifier->HashEnd(hid, &chash, &clen, DIGEST_LENGTH);
nsCAutoString hashString;
rv = mVerifier->Finish(PR_FALSE, hashString);
if (NS_FAILED(rv)) return rv;
if (NS_SUCCEEDED(rv))
memcpy(mHashBuf, chash, DIGEST_LENGTH);
memcpy(mHashBuf, hashString.get(), hashString.Length());
return rv;
}

View File

@ -43,6 +43,7 @@
#define nsDigestAuth_h__
#include "nsIHttpAuthenticator.h"
#include "nsICryptoHash.h"
#include "nsString.h"
#include "nsCOMPtr.h"
@ -111,7 +112,7 @@ class nsHttpDigestAuth : public nsIHttpAuthenticator
nsresult GetMethodAndPath(nsIHttpChannel *, PRBool, nsCString &, nsCString &);
protected:
nsCOMPtr<nsISignatureVerifier> mVerifier;
nsCOMPtr<nsICryptoHash> mVerifier;
char mHashBuf[DIGEST_LENGTH];
PRBool mGotVerifier;
};

View File

@ -80,7 +80,6 @@ XPIDLSRCS = \
nsICMSEncoder.idl \
nsICMSMessageErrors.idl \
nsICMSMessage.idl \
nsIHash.idl \
nsINSSCertCache.idl \
nsIOCSPResponder.idl \
nsIPK11Token.idl \

View File

@ -50,89 +50,8 @@ extern PRLogModuleInfo* gPIPNSSLog;
#endif
#include "nsNSSCleaner.h"
NSSCleanupAutoPtrClass(CERTCertificate, CERT_DestroyCertificate)
NS_IMPL_THREADSAFE_ISUPPORTS1(nsHash, nsIHash)
nsHash::nsHash() : m_ctxt(nsnull)
{
}
nsHash::~nsHash()
{
nsNSSShutDownPreventionLock locker;
if (isAlreadyShutDown())
return;
destructorSafeDestroyNSSReference();
shutdown(calledFromObject);
}
void nsHash::virtualDestroyNSSReference()
{
destructorSafeDestroyNSSReference();
}
void nsHash::destructorSafeDestroyNSSReference()
{
if (isAlreadyShutDown())
return;
if (m_ctxt) {
HASH_Destroy(m_ctxt);
m_ctxt = nsnull;
}
}
NS_IMETHODIMP nsHash::ResultLen(PRInt16 aAlg, PRUint32 * aLen)
{
*aLen = HASH_ResultLen((HASH_HashType)aAlg);
return NS_OK;
}
NS_IMETHODIMP nsHash::Create(PRInt16 aAlg)
{
nsNSSShutDownPreventionLock locker;
if (isAlreadyShutDown())
return NS_ERROR_NOT_AVAILABLE;
m_ctxt = HASH_Create((HASH_HashType)aAlg);
if (m_ctxt == nsnull) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
NS_IMETHODIMP nsHash::Begin()
{
nsNSSShutDownPreventionLock locker;
if (isAlreadyShutDown())
return NS_ERROR_NOT_AVAILABLE;
HASH_Begin(m_ctxt);
return NS_OK;
}
NS_IMETHODIMP nsHash::Update(unsigned char* aBuf, PRUint32 aLen)
{
nsNSSShutDownPreventionLock locker;
if (isAlreadyShutDown())
return NS_ERROR_NOT_AVAILABLE;
HASH_Update(m_ctxt, (const unsigned char*)aBuf, aLen);
return NS_OK;
}
NS_IMETHODIMP nsHash::End(unsigned char* aBuf, PRUint32* aResultLen, PRUint32 aMaxResultLen)
{
nsNSSShutDownPreventionLock locker;
if (isAlreadyShutDown())
return NS_ERROR_NOT_AVAILABLE;
HASH_End(m_ctxt, aBuf, aResultLen, aMaxResultLen);
return NS_OK;
}
NS_IMPL_THREADSAFE_ISUPPORTS1(nsCMSMessage, nsICMSMessage)
nsCMSMessage::nsCMSMessage()

View File

@ -41,7 +41,6 @@
#include "nsISupports.h"
#include "nsCOMPtr.h"
#include "nsIInterfaceRequestor.h"
#include "nsIHash.h"
#include "nsICMSMessage.h"
#include "nsICMSEncoder.h"
#include "nsICMSDecoder.h"
@ -49,26 +48,6 @@
#include "cms.h"
#include "nsNSSShutDown.h"
#define NS_HASH_CLASSNAME "Hash Object"
#define NS_HASH_CID \
{ 0xa31a3028, 0xae28, 0x11d5, { 0xba, 0x4b, 0x00, 0x10, 0x83, 0x03, 0xb1, 0x17 } }
class nsHash : public nsIHash,
public nsNSSShutDownObject
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIHASH
nsHash();
virtual ~nsHash();
private:
HASHContext * m_ctxt;
virtual void virtualDestroyNSSReference();
void destructorSafeDestroyNSSReference();
};
#define NS_CMSMESSAGE_CLASSNAME "CMS Message Object"
#define NS_CMSMESSAGE_CID \
{ 0xa4557478, 0xae16, 0x11d5, { 0xba,0x4b,0x00,0x10,0x83,0x03,0xb1,0x17 } }

View File

@ -89,6 +89,7 @@
#include "nsITokenPasswordDialogs.h"
#include "nsICRLManager.h"
#include "nsNSSShutDown.h"
#include "nsICryptoHash.h"
#include "nss.h"
#include "pk11func.h"
@ -100,6 +101,8 @@
#include "ocsp.h"
#include "cms.h"
#include "nssckbi.h"
#include "base64.h"
extern "C" {
#include "pkcs12.h"
#include "p12plcy.h"
@ -109,6 +112,8 @@ extern "C" {
PRLogModuleInfo* gPIPNSSLog = nsnull;
#endif
#define NS_CRYPTO_HASH_BUFFER_SIZE 4096
static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
int nsNSSComponent::mInstanceCount = 0;
@ -1326,36 +1331,6 @@ NS_IMPL_THREADSAFE_ISUPPORTS5(nsNSSComponent,
nsIObserver,
nsISupportsWeakReference)
//---------------------------------------------
// Functions Implementing nsISignatureVerifier
//---------------------------------------------
NS_IMETHODIMP
nsNSSComponent::HashBegin(PRUint32 alg, HASHContext** id)
{
*id = HASH_Create((HASH_HashType)alg);
if (*id) {
HASH_Begin(*id);
return NS_OK;
} else {
return NS_ERROR_FAILURE;
}
}
NS_IMETHODIMP
nsNSSComponent::HashUpdate(HASHContext* ctx, const char* buf, PRUint32 buflen)
{
HASH_Update(ctx, (const unsigned char*)buf, buflen);
return NS_OK;
}
NS_IMETHODIMP
nsNSSComponent::HashEnd(HASHContext* ctx, unsigned char** hash,
PRUint32* hashLen, PRUint32 maxLen)
{
HASH_End(ctx, *hash, hashLen, maxLen);
HASH_Destroy(ctx);
return NS_OK;
}
/* Callback functions for decoder. For now, use empty/default functions. */
static void ContentCallback(void *arg,
@ -1829,8 +1804,123 @@ nsNSSComponent::RememberCert(CERTCertificate *cert)
return NS_OK;
}
//---------------------------------------------
// Implementing nsICryptoHash
//---------------------------------------------
nsCryptoHash::nsCryptoHash()
: mHashContext(nsnull)
{
}
nsCryptoHash::~nsCryptoHash()
{
if (mHashContext)
HASH_Destroy(mHashContext);
}
NS_IMPL_ISUPPORTS1(nsCryptoHash, nsICryptoHash)
NS_IMETHODIMP
nsCryptoHash::Init(PRUint32 algorithm)
{
if (mHashContext)
HASH_Destroy(mHashContext);
mHashContext = HASH_Create((HASH_HashType) algorithm);
if (!mHashContext)
return NS_ERROR_INVALID_ARG;
HASH_Begin(mHashContext);
return NS_OK;
}
NS_IMETHODIMP
nsCryptoHash::Update(const PRUint8 *data, PRUint32 len)
{
if (!mHashContext)
return NS_ERROR_NOT_INITIALIZED;
HASH_Update(mHashContext, data, len);
return NS_OK;
}
NS_IMETHODIMP
nsCryptoHash::UpdateFromStream(nsIInputStream *data, PRUint32 len)
{
if (!mHashContext)
return NS_ERROR_NOT_INITIALIZED;
if (!data)
return NS_ERROR_INVALID_ARG;
PRUint32 n;
nsresult rv = data->Available(&n);
if (NS_FAILED(rv))
return rv;
// if the user has passed PR_UINT32_MAX, then read
// everything in the stream
if (len == PR_UINT32_MAX)
len = n;
// So, if the stream has NO data available for the hash,
// or if the data available is less then what the caller
// requested, we can not fulfill the hash update. In this
// case, just return NS_ERROR_NOT_AVAILABLE indicating
// that there is not enough data in the stream to satisify
// the request.
if (n == 0 || n < len)
return NS_ERROR_NOT_AVAILABLE;
char buffer[NS_CRYPTO_HASH_BUFFER_SIZE];
PRUint32 read;
while(NS_SUCCEEDED(rv) && len>0)
{
read = PR_MIN(NS_CRYPTO_HASH_BUFFER_SIZE, len);
rv = data->Read(buffer, read, &read);
if (NS_SUCCEEDED(rv))
rv = Update((const PRUint8*)buffer, read);
len -= read;
}
return rv;
}
NS_IMETHODIMP
nsCryptoHash::Finish(PRBool ascii, nsACString & _retval)
{
if (!mHashContext)
return NS_ERROR_NOT_INITIALIZED;
PRUint32 hashLen = 0;
unsigned char buffer[HASH_LENGTH_MAX];
unsigned char* pbuffer = buffer;
HASH_End(mHashContext, pbuffer, &hashLen, 32);
HASH_Destroy(mHashContext);
mHashContext = nsnull;
if (ascii)
{
char *asciiData = BTOA_DataToAscii(buffer, hashLen);
_retval.Assign(asciiData);
PORT_Free(asciiData);
}
else
{
_retval.Assign((const char*)buffer, hashLen);
}
return NS_OK;
}
NS_IMPL_ISUPPORTS1(PipUIContext, nsIInterfaceRequestor)

View File

@ -59,6 +59,8 @@
#include "nsNetUtil.h"
#include "nsHashtable.h"
#include "prlock.h"
#include "nsICryptoHash.h"
#include "hasht.h"
#include "nsNSSHelper.h"
@ -79,6 +81,10 @@
#define NS_PSMCONTENTLISTEN_CID {0xc94f4a30, 0x64d7, 0x11d4, {0x99, 0x60, 0x00, 0xb0, 0xd0, 0x23, 0x54, 0xa0}}
#define NS_PSMCONTENTLISTEN_CONTRACTID "@mozilla.org/security/psmdownload;1"
#define NS_CRYPTO_HASH_CLASSNAME "Mozilla Cryto Hash Function Component"
#define NS_CRYPTO_HASH_CONTRACTID "@mozilla.org/security/hash;1"
#define NS_CRYPTO_HASH_CID {0x36a1d3b3, 0xd886, 0x4317, {0x96, 0xff, 0x87, 0xb0, 0x00, 0x5c, 0xfe, 0xf7}}
//--------------------------------------------
// Now we need a content listener to register
//--------------------------------------------
@ -144,6 +150,19 @@ class NS_NO_VTABLE nsINSSComponent : public nsISupports {
};
class nsCryptoHash : public nsICryptoHash
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSICRYPTOHASH
nsCryptoHash();
private:
~nsCryptoHash();
HASHContext* mHashContext;
};
struct PRLock;
class nsNSSShutDownList;

View File

@ -179,11 +179,11 @@ NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(PR_FALSE, nsCMSSecureMessage)
NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(PR_FALSE, nsCMSDecoder)
NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(PR_FALSE, nsCMSEncoder)
NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(PR_FALSE, nsCMSMessage)
NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(PR_FALSE, nsHash)
NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(PR_FALSE, nsCertPicker)
NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(PR_FALSE, nsCRLManager)
NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(PR_FALSE, nsCipherInfoService)
NS_NSS_GENERIC_FACTORY_CONSTRUCTOR_INIT(PR_FALSE, nsNTLMAuthModule, InitTest)
NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(PR_FALSE, nsCryptoHash)
static NS_METHOD RegisterPSMContentListeners(
nsIComponentManager *aCompMgr,
@ -357,10 +357,10 @@ static const nsModuleComponentInfo components[] =
},
{
NS_HASH_CLASSNAME,
NS_HASH_CID,
NS_HASH_CONTRACTID,
nsHashConstructor
NS_CRYPTO_HASH_CLASSNAME,
NS_CRYPTO_HASH_CID,
NS_CRYPTO_HASH_CONTRACTID,
nsCryptoHashConstructor
},
{