Use statically-sized stack buffers to fix building on Windows.
authorJustin Dolske <dolske@mozilla.com>
Thu, 26 Jun 2008 15:22:48 -0700
changeset 44772 eb9363d272d51339689779475bd37daf03f9cee9
parent 44771 ecc6163e17aaeec265787783cbd99df3058cba29
child 44773 c434b6719a01fc3dbf0d1c8c2545270a134e3508
push idunknown
push userunknown
push dateunknown
Use statically-sized stack buffers to fix building on Windows.
services/crypto/WeaveCrypto.cpp
--- a/services/crypto/WeaveCrypto.cpp
+++ b/services/crypto/WeaveCrypto.cpp
@@ -45,16 +45,22 @@
 #include "plbase64.h"
 #include "prmem.h"
 #include "secerr.h"
 
 #include "pk11func.h"
 #include "keyhi.h"
 #include "nss.h"
 
+/*
+ * In a number of places we use stack buffers to hold smallish temporary data.
+ * 4K is plenty big for the exptected uses, and avoids poking holes in the
+ * heap for small allocations. (Yes, we still check for overflow.)
+ */
+#define STACK_BUFFER_SIZE 4096
 
 NS_IMPL_ISUPPORTS1(WeaveCrypto, IWeaveCrypto)
 
 WeaveCrypto::WeaveCrypto() :
   mAlgorithm(SEC_OID_AES_256_CBC),
   mKeypairBits(2048)
 {
 }
@@ -268,19 +274,19 @@ WeaveCrypto::CommonCrypt(const char *inp
 {
   nsresult rv = NS_OK;
   PK11SymKey   *symKey  = nsnull;
   PK11Context  *ctx     = nsnull;
   PK11SlotInfo *slot    = nsnull;
   SECItem      *ivParam = nsnull;
   PRUint32 maxOutputSize;
 
-  char keyData[aSymmetricKey.Length()];
+  char keyData[STACK_BUFFER_SIZE];
   PRUint32 keyDataSize = sizeof(keyData);
-  char ivData[aIV.Length()];
+  char ivData[STACK_BUFFER_SIZE];
   PRUint32 ivDataSize = sizeof(ivData);
 
   rv = DecodeBase64(aSymmetricKey, keyData, &keyDataSize);
   NS_ENSURE_SUCCESS(rv, rv);
   rv = DecodeBase64(aIV, ivData, &ivDataSize);
   NS_ENSURE_SUCCESS(rv, rv);
 
   SECItem keyItem = {siBuffer, (unsigned char*)keyData, keyDataSize}; 
@@ -463,18 +469,18 @@ WeaveCrypto::DeriveKeyFromPassphrase(con
                                      const nsACString& aSalt,
                                      PK11SymKey **aSymKey)
 {
   nsresult rv;
 
   PromiseFlatCString fPass(aPassphrase);
   SECItem passphrase = {siBuffer, (unsigned char *)fPass.get(), fPass.Length()}; 
 
-  char saltBytes[aSalt.Length()];
-  PRUint32 saltBytesLength = aSalt.Length();
+  char saltBytes[STACK_BUFFER_SIZE];
+  PRUint32 saltBytesLength = sizeof(saltBytes);
   rv = DecodeBase64(aSalt, saltBytes, &saltBytesLength);
   NS_ENSURE_SUCCESS(rv, rv);
   SECItem salt = {siBuffer, (unsigned char*)saltBytes, saltBytesLength}; 
 
   // http://mxr.mozilla.org/seamonkey/source/security/nss/lib/pk11wrap/pk11pbe.c#1261
 
   // Bug 436577 prevents us from just using SEC_OID_PKCS5_PBKDF2 here
   SECOidTag pbeAlg = mAlgorithm;
@@ -526,17 +532,17 @@ WeaveCrypto::WrapPrivateKey(SECKEYPrivat
   nsresult rv;
   SECStatus s;
   PK11SymKey *pbeKey = nsnull;
 
   // Convert our passphrase to a symkey and get the IV in the form we want.
   rv = DeriveKeyFromPassphrase(aPassphrase, aSalt, &pbeKey);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  char ivData[aIV.Length()];
+  char ivData[STACK_BUFFER_SIZE];
   PRUint32 ivDataSize = sizeof(ivData);
   rv = DecodeBase64(aIV, ivData, &ivDataSize);
   NS_ENSURE_SUCCESS(rv, rv);
   SECItem ivItem  = {siBuffer, (unsigned char*)ivData,  ivDataSize}; 
 
   // AES_128_CBC --> CKM_AES_CBC --> CKM_AES_CBC_PAD
   CK_MECHANISM_TYPE wrapMech = PK11_AlgtagToMechanism(mAlgorithm);
   wrapMech = PK11_GetPadMechanism(wrapMech);
@@ -549,17 +555,17 @@ WeaveCrypto::WrapPrivateKey(SECKEYPrivat
   if (!ivParam) {
     NS_WARNING("Couldn't create IV param");
     return NS_ERROR_FAILURE;
   }
 
 
   // Use a stack buffer to hold the wrapped key. NSS says about 1200 bytes for
   // a 2048-bit RSA key, so our 4096 byte buffer should be plenty.
-  unsigned char stackBuffer[4096];
+  unsigned char stackBuffer[STACK_BUFFER_SIZE];
   SECItem wrappedKey = {siBuffer, stackBuffer, sizeof(stackBuffer)}; 
 
   s = PK11_WrapPrivKey(aPrivateKey->pkcs11Slot,
                        pbeKey, aPrivateKey,
                        wrapMech, ivParam,
                        &wrappedKey, nsnull);
 
   SECITEM_FreeItem(ivParam, PR_TRUE);
@@ -603,17 +609,20 @@ WeaveCrypto::EncodePublicKey(SECKEYPubli
 /*
  * GenerateRandomBytes
  */
 NS_IMETHODIMP
 WeaveCrypto::GenerateRandomBytes(PRUint32 aByteCount,
                                  nsACString& aEncodedBytes)
 {
   nsresult rv;
-  char random[aByteCount];
+  char random[STACK_BUFFER_SIZE];
+
+  if (aByteCount > STACK_BUFFER_SIZE)
+    return NS_ERROR_OUT_OF_MEMORY;
 
   rv = PK11_GenerateRandom((unsigned char *)random, aByteCount);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = EncodeBase64(random, aByteCount, aEncodedBytes);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
@@ -626,17 +635,20 @@ WeaveCrypto::GenerateRandomBytes(PRUint3
 NS_IMETHODIMP
 WeaveCrypto::GenerateRandomIV(nsACString& aEncodedBytes)
 {
   nsresult rv;
 
   CK_MECHANISM_TYPE mech = PK11_AlgtagToMechanism(mAlgorithm);
   PRUint32 size = PK11_GetIVLength(mech);
 
-  char random[size];
+  char random[STACK_BUFFER_SIZE];
+
+  if (size > STACK_BUFFER_SIZE)
+    return NS_ERROR_OUT_OF_MEMORY;
  
   rv = PK11_GenerateRandom((unsigned char *)random, size);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = EncodeBase64(random, size, aEncodedBytes);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
@@ -737,29 +749,29 @@ WeaveCrypto::WrapSymmetricKey(const nsAC
   PK11SlotInfo *slot = nsnull;
   PK11SymKey *symKey = nsnull;
   SECKEYPublicKey *pubKey = nsnull;
   CERTSubjectPublicKeyInfo *pubKeyInfo = nsnull;
   CK_MECHANISM_TYPE keyMech, wrapMech;
 
   // Step 1. Get rid of the base64 encoding on the inputs.
 
-  char publicKeyBuffer[aPublicKey.Length()];
-  PRUint32 publicKeyBufferSize = aPublicKey.Length();
+  char publicKeyBuffer[STACK_BUFFER_SIZE];
+  PRUint32 publicKeyBufferSize = sizeof(publicKeyBuffer);
   rv = DecodeBase64(aPublicKey, publicKeyBuffer, &publicKeyBufferSize);
   NS_ENSURE_SUCCESS(rv, rv);
   SECItem pubKeyData = {siBuffer, (unsigned char *)publicKeyBuffer, publicKeyBufferSize};
 
-  char symKeyBuffer[aSymmetricKey.Length()];
-  PRUint32 symKeyBufferSize = aSymmetricKey.Length();
+  char symKeyBuffer[STACK_BUFFER_SIZE];
+  PRUint32 symKeyBufferSize = sizeof(symKeyBuffer);
   rv = DecodeBase64(aSymmetricKey, symKeyBuffer, &symKeyBufferSize);
   NS_ENSURE_SUCCESS(rv, rv);
   SECItem symKeyData = {siBuffer, (unsigned char *)symKeyBuffer, symKeyBufferSize};
 
-  char wrappedBuffer[4096];
+  char wrappedBuffer[STACK_BUFFER_SIZE];
   SECItem wrappedKey = {siBuffer, (unsigned char *)wrappedBuffer, sizeof(wrappedBuffer)};
 
 
   // Step 2. Put the symmetric key bits into a P11 key object.
 
   slot = PK11_GetInternalSlot();
   if (!slot) {
     NS_WARNING("Can't get internal PK11 slot");
@@ -864,34 +876,34 @@ WeaveCrypto::UnwrapSymmetricKey(const ns
   SECItem *keyID = nsnull;
 
   CK_ATTRIBUTE_TYPE privKeyUsage[] = { CKA_UNWRAP };
   PRUint32 privKeyUsageLength = sizeof(privKeyUsage) / sizeof(CK_ATTRIBUTE_TYPE);
 
 
   // Step 1. Get rid of the base64 encoding on the inputs.
 
-  char privateKeyBuffer[aWrappedPrivateKey.Length()];
-  PRUint32 privateKeyBufferSize = aWrappedPrivateKey.Length();
+  char privateKeyBuffer[STACK_BUFFER_SIZE];
+  PRUint32 privateKeyBufferSize = sizeof(privateKeyBuffer);
   rv = DecodeBase64(aWrappedPrivateKey, privateKeyBuffer, &privateKeyBufferSize);
   NS_ENSURE_SUCCESS(rv, rv);
   SECItem wrappedPrivKey = {siBuffer, (unsigned char *)privateKeyBuffer, privateKeyBufferSize};
 
-  char wrappedKeyBuffer[aWrappedSymmetricKey.Length()];
-  PRUint32 wrappedKeyBufferSize = aWrappedSymmetricKey.Length();
+  char wrappedKeyBuffer[STACK_BUFFER_SIZE];
+  PRUint32 wrappedKeyBufferSize = sizeof(wrappedKeyBuffer);
   rv = DecodeBase64(aWrappedSymmetricKey, wrappedKeyBuffer, &wrappedKeyBufferSize);
   NS_ENSURE_SUCCESS(rv, rv);
   SECItem wrappedSymKey = {siBuffer, (unsigned char *)wrappedKeyBuffer, wrappedKeyBufferSize};
 
 
   // Step 2. Convert the passphrase to a symmetric key and get the IV in the proper form.
   rv = DeriveKeyFromPassphrase(aPassphrase, aSalt, &pbeKey);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  char ivData[aIV.Length()];
+  char ivData[STACK_BUFFER_SIZE];
   PRUint32 ivDataSize = sizeof(ivData);
   rv = DecodeBase64(aIV, ivData, &ivDataSize);
   NS_ENSURE_SUCCESS(rv, rv);
   SECItem ivItem  = {siBuffer, (unsigned char*)ivData,  ivDataSize}; 
 
   // AES_128_CBC --> CKM_AES_CBC --> CKM_AES_CBC_PAD
   CK_MECHANISM_TYPE wrapMech = PK11_AlgtagToMechanism(mAlgorithm);
   wrapMech = PK11_GetPadMechanism(wrapMech);