Bug 617650: avoid unrooting string in makeSECItem. r=philiKON

This commit is contained in:
Richard Newman 2011-01-19 16:17:58 -08:00
parent 56f91610cc
commit 0b37a22351
2 changed files with 83 additions and 10 deletions

View File

@ -419,6 +419,17 @@ WeaveCrypto.prototype = {
this.nss.PK11_FreeSlot = nsslib.declare("PK11_FreeSlot",
ctypes.default_abi, ctypes.void_t,
this.nss_t.PK11SlotInfo.ptr);
// security/nss/lib/util/secitem.h#49
// extern SECItem *SECITEM_AllocItem(PRArenaPool *arena, SECItem *item, unsigned int len);
this.nss.SECITEM_AllocItem = nsslib.declare("SECITEM_AllocItem",
ctypes.default_abi, this.nss_t.SECItem.ptr,
this.nss_t.PLArenaPool.ptr, // Not used.
this.nss_t.SECItem.ptr, ctypes.unsigned_int);
// security/nss/lib/util/secitem.h#274
// extern void SECITEM_ZfreeItem(SECItem *zap, PRBool freeit);
this.nss.SECITEM_ZfreeItem = nsslib.declare("SECITEM_ZfreeItem",
ctypes.default_abi, ctypes.void_t,
this.nss_t.SECItem.ptr, this.nss_t.PRBool);
// security/nss/lib/util/secitem.h#114
// extern void SECITEM_FreeItem(SECItem *zap, PRBool freeit);
this.nss.SECITEM_FreeItem = nsslib.declare("SECITEM_FreeItem",
@ -515,7 +526,7 @@ WeaveCrypto.prototype = {
let ctx, symKey, slot, ivParam;
try {
ivParam = this.nss.PK11_ParamFromIV(mechanism, ivItem.address());
ivParam = this.nss.PK11_ParamFromIV(mechanism, ivItem);
if (ivParam.isNull())
throw Components.Exception("can't convert IV to param", Cr.NS_ERROR_FAILURE);
@ -523,7 +534,7 @@ WeaveCrypto.prototype = {
if (slot.isNull())
throw Components.Exception("can't get internal key slot", Cr.NS_ERROR_FAILURE);
symKey = this.nss.PK11_ImportSymKey(slot, mechanism, this.nss.PK11_OriginUnwrap, operation, keyItem.address(), null);
symKey = this.nss.PK11_ImportSymKey(slot, mechanism, this.nss.PK11_OriginUnwrap, operation, keyItem, null);
if (symKey.isNull())
throw Components.Exception("symkey import failed", Cr.NS_ERROR_FAILURE);
@ -563,6 +574,8 @@ WeaveCrypto.prototype = {
this.nss.PK11_FreeSlot(slot);
if (ivParam && !ivParam.isNull())
this.nss.SECITEM_FreeItem(ivParam, true);
this.freeSECItem(keyItem);
this.freeSECItem(ivItem);
}
},
@ -684,15 +697,28 @@ WeaveCrypto.prototype = {
return btoa(this.expandData(data, len));
},
// Returns a filled SECItem *, as returned by SECITEM_AllocItem.
//
// Note that this must be released with freeSECItem, which will also
// deallocate the internal buffer.
makeSECItem : function(input, isEncoded) {
if (isEncoded)
input = atob(input);
let outputData = new ctypes.ArrayType(ctypes.unsigned_char, input.length)();
this.byteCompress(input, outputData);
return new this.nss_t.SECItem(this.nss.SIBUFFER, outputData, outputData.length);
let len = input.length;
let item = this.nss.SECITEM_AllocItem(null, null, len);
if (item.isNull())
throw "SECITEM_AllocItem failed.";
let dest = ctypes.cast(item.contents.data, ctypes.unsigned_char.array(len).ptr);
this.byteCompress(input, dest.contents);
return item;
},
freeSECItem : function(zap) {
if (zap && !zap.isNull())
this.nss.SECITEM_ZfreeItem(zap, true);
},
/**
* Returns the expanded data string for the derived key.
@ -712,7 +738,8 @@ WeaveCrypto.prototype = {
let algid, slot, symKey, keyData;
try {
algid = this.nss.PK11_CreatePBEV2AlgorithmID(pbeAlg, cipherAlg, prfAlg,
keyLength, iterations, saltItem.address());
keyLength, iterations,
saltItem);
if (algid.isNull())
throw Components.Exception("PK11_CreatePBEV2AlgorithmID failed", Cr.NS_ERROR_FAILURE);
@ -720,7 +747,7 @@ WeaveCrypto.prototype = {
if (slot.isNull())
throw Components.Exception("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
symKey = this.nss.PK11_PBEKeyGen(slot, algid, passItem.address(), false, null);
symKey = this.nss.PK11_PBEKeyGen(slot, algid, passItem, false, null);
if (symKey.isNull())
throw Components.Exception("PK11_PBEKeyGen failed", Cr.NS_ERROR_FAILURE);
@ -748,6 +775,9 @@ WeaveCrypto.prototype = {
this.nss.PK11_FreeSlot(slot);
if (symKey && !symKey.isNull())
this.nss.PK11_FreeSymKey(symKey);
}
this.freeSECItem(passItem);
this.freeSECItem(saltItem);
}
},
};

View File

@ -8,7 +8,50 @@ try {
.getService(Ci.IWeaveCrypto);
}
function multiple_decrypts(iterations) {
let iv = cryptoSvc.generateRandomIV();
let key = cryptoSvc.generateRandomKey();
let cipherText = cryptoSvc.encrypt("Hello, world.", key, iv);
for (let i = 0; i < iterations; ++i) {
let clearText = cryptoSvc.decrypt(cipherText, key, iv);
do_check_eq(clearText + " " + i, "Hello, world. " + i);
}
_("Done with multiple_decrypts.");
}
function test_bug_617650() {
if (this.gczeal) {
gczeal(2);
// Few iterations, because gczeal(2) is expensive... and makes it fail much faster!
_("gczeal set to 2; attempting 10 iterations of multiple_decrypts.");
multiple_decrypts(10);
gczeal(0);
} else {
// We can't use gczeal on non-debug builds, so try lots of reps instead.
_("No gczeal (non-debug build?); attempting 10,000 iterations of multiple_decrypts.");
multiple_decrypts(10000);
}
}
// Just verify that it gets populated with the correct bytes.
function test_makeSECItem() {
Components.utils.import("resource://gre/modules/ctypes.jsm");
let item1 = cryptoSvc.makeSECItem("abcdefghi", false);
do_check_true(!item1.isNull());
let intData = ctypes.cast(item1.contents.data, ctypes.uint8_t.array(8).ptr).contents;
for (let i = 0; i < 8; ++i)
do_check_eq(intData[i], "abcdefghi".charCodeAt(i));
}
function run_test() {
if ("makeSECItem" in cryptoSvc) // Only for js-ctypes WeaveCrypto.
test_makeSECItem();
test_bug_617650();
// First, do a normal run with expected usage... Generate a random key and
// iv, encrypt and decrypt a string.
var iv = cryptoSvc.generateRandomIV();