summaryrefslogtreecommitdiffstats
path: root/core/ccm.js
diff options
context:
space:
mode:
Diffstat (limited to 'core/ccm.js')
-rw-r--r--core/ccm.js88
1 files changed, 60 insertions, 28 deletions
diff --git a/core/ccm.js b/core/ccm.js
index 8a32c5a..1efde02 100644
--- a/core/ccm.js
+++ b/core/ccm.js
@@ -15,6 +15,27 @@ sjcl.mode.ccm = {
*/
name: "ccm",
+ _progressListeners: [],
+
+ listenProgress: function (cb) {
+ sjcl.mode.ccm._progressListeners.push(cb);
+ },
+
+ unListenProgress: function (cb) {
+ var index = sjcl.mode.ccm._progressListeners.indexOf(cb);
+ if (index > -1) {
+ sjcl.mode.ccm._progressListeners.splice(index, 1);
+ }
+ },
+
+ _callProgressListener: function (val) {
+ var p = sjcl.mode.ccm._progressListeners.slice(), i;
+
+ for (i = 0; i < p.length; i += 1) {
+ p[i](val);
+ }
+ },
+
/** Encrypt in CCM mode.
* @static
* @param {Object} prf The pseudorandom function. It must have a block size of 16 bytes.
@@ -25,7 +46,7 @@ sjcl.mode.ccm = {
* @return {bitArray} The encrypted data, an array of bytes.
*/
encrypt: function(prf, plaintext, iv, adata, tlen) {
- var L, i, out = plaintext.slice(0), tag, w=sjcl.bitArray, ivl = w.bitLength(iv) / 8, ol = w.bitLength(out) / 8;
+ var L, out = plaintext.slice(0), tag, w=sjcl.bitArray, ivl = w.bitLength(iv) / 8, ol = w.bitLength(out) / 8;
tlen = tlen || 64;
adata = adata || [];
@@ -59,7 +80,7 @@ sjcl.mode.ccm = {
decrypt: function(prf, ciphertext, iv, adata, tlen) {
tlen = tlen || 64;
adata = adata || [];
- var L, i,
+ var L,
w=sjcl.bitArray,
ivl = w.bitLength(iv) / 8,
ol = w.bitLength(ciphertext),
@@ -90,6 +111,36 @@ sjcl.mode.ccm = {
return out.data;
},
+ _macAdditionalData: function (prf, adata, iv, tlen, ol, L) {
+ var mac, tmp, i, macData = [], w=sjcl.bitArray, xor = w._xor4;
+
+ // mac the flags
+ mac = [w.partial(8, (adata.length ? 1<<6 : 0) | (tlen-2) << 2 | L-1)];
+
+ // mac the iv and length
+ mac = w.concat(mac, iv);
+ mac[3] |= ol;
+ mac = prf.encrypt(mac);
+
+ if (adata.length) {
+ // mac the associated data. start with its length...
+ tmp = w.bitLength(adata)/8;
+ if (tmp <= 0xFEFF) {
+ macData = [w.partial(16, tmp)];
+ } else if (tmp <= 0xFFFFFFFF) {
+ macData = w.concat([w.partial(16,0xFFFE)], [tmp]);
+ } // else ...
+
+ // mac the data itself
+ macData = w.concat(macData, adata);
+ for (i=0; i<macData.length; i += 4) {
+ mac = prf.encrypt(xor(mac, macData.slice(i,i+4).concat([0,0,0])));
+ }
+ }
+
+ return mac;
+ },
+
/* Compute the (unencrypted) authentication tag, according to the CCM specification
* @param {Object} prf The pseudorandom function.
* @param {bitArray} plaintext The plaintext data.
@@ -101,7 +152,7 @@ sjcl.mode.ccm = {
*/
_computeTag: function(prf, plaintext, iv, adata, tlen, L) {
// compute B[0]
- var q, mac, field = 0, offset = 24, tmp, i, macData = [], w=sjcl.bitArray, xor = w._xor4;
+ var mac, i, w=sjcl.bitArray, xor = w._xor4;
tlen /= 8;
@@ -115,31 +166,8 @@ sjcl.mode.ccm = {
throw new sjcl.exception.bug("ccm: can't deal with 4GiB or more data");
}
- // mac the flags
- mac = [w.partial(8, (adata.length ? 1<<6 : 0) | (tlen-2) << 2 | L-1)];
+ mac = sjcl.mode.ccm._macAdditionalData(prf, adata, iv, tlen, w.bitLength(plaintext)/8, L);
- // mac the iv and length
- mac = w.concat(mac, iv);
- mac[3] |= w.bitLength(plaintext)/8;
- mac = prf.encrypt(mac);
-
-
- if (adata.length) {
- // mac the associated data. start with its length...
- tmp = w.bitLength(adata)/8;
- if (tmp <= 0xFEFF) {
- macData = [w.partial(16, tmp)];
- } else if (tmp <= 0xFFFFFFFF) {
- macData = w.concat([w.partial(16,0xFFFE)], [tmp]);
- } // else ...
-
- // mac the data itself
- macData = w.concat(macData, adata);
- for (i=0; i<macData.length; i += 4) {
- mac = prf.encrypt(xor(mac, macData.slice(i,i+4).concat([0,0,0])));
- }
- }
-
// mac the plaintext
for (i=0; i<plaintext.length; i+=4) {
mac = prf.encrypt(xor(mac, plaintext.slice(i,i+4).concat([0,0,0])));
@@ -161,7 +189,7 @@ sjcl.mode.ccm = {
* @private
*/
_ctrMode: function(prf, data, iv, tag, tlen, L) {
- var enc, i, w=sjcl.bitArray, xor = w._xor4, ctr, b, l = data.length, bl=w.bitLength(data);
+ var enc, i, w=sjcl.bitArray, xor = w._xor4, ctr, l = data.length, bl=w.bitLength(data), n = l/50, p = n;
// start the ctr
ctr = w.concat([w.partial(8,L-1)],iv).concat([0,0,0]).slice(0,4);
@@ -173,6 +201,10 @@ sjcl.mode.ccm = {
if (!l) { return {tag:tag, data:[]}; }
for (i=0; i<l; i+=4) {
+ if (i > n) {
+ sjcl.mode.ccm._callProgressListener(i/l);
+ n += p;
+ }
ctr[3]++;
enc = prf.encrypt(ctr);
data[i] ^= enc[0];