1 /**
  2  * @namespace AES-256 encryption and associated modes
  3  * @author Anonymized
  4  * @description
  5  * <p>Implementation of AES on 256 bit keys.</p>
  6  * @requires encoding
  7  */
  8  var aes =
  9  {
 10   Stables: (function()
 11   {
 12    var a256 = function()
 13    {
 14     return [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 15             0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 16             0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 17             0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 18             0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 19             0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 20             0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 21             0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
 22    },
 23 
 24    t5 = function(){return [a256(), a256(), a256(), a256(), a256()]},
 25    encTable = t5(), decTable = t5(),
 26    sbox = encTable[4], sboxInv = decTable[4],
 27    i = 0, x = 0, xInv = 0, x2 = 0, x4 = 0, x8 = 0,
 28    tEnc = 0, tDec = 0, s = 0, d = a256(), th = a256();
 29 
 30    for(i=0; i < 256; i++)
 31     th[((d[i & 255] = i<<1 ^ (i>>7)*283)^i) & 255] = i;
 32 
 33    for(x=xInv=0; !sbox[x&255]; x^=(!x2?1:x2), xInv=th[xInv&255], xInv=(!xInv?1:xInv))
 34    {
 35     s = xInv ^ xInv<<1 ^ xInv<<2 ^ xInv<<3 ^ xInv<<4;
 36     s = s>>8 ^ s&255 ^ 99;
 37     sbox[x&255] = s; sboxInv[s&255] = x;
 38 
 39     x8 = d[(x4 = d[(x2 = d[x&255])&255])&255];
 40     tDec = x8*0x1010101 ^ x4*0x10001 ^ x2*0x101 ^ x*0x1010100;
 41     tEnc = d[s&255]*0x101 ^ s*0x1010100;
 42 
 43     for (i=0; i<4; i++)
 44     {
 45      encTable[i&3][x&255] = tEnc = tEnc<<24 ^ tEnc>>>8;
 46      decTable[i&3][s&255] = tDec = tDec<<24 ^ tDec>>>8;
 47     }
 48    }
 49 
 50    return [encTable, decTable];
 51   })(),
 52 
 53   key: (function()
 54   {
 55    var a = function(){ return [
 56     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 57     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 58     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
 59    ]};
 60    return [a(),a()];
 61   })(),
 62 
 63 /** Set the key to use for encryption and decryption.
 64   * @param {string} key ASCII key (32 bytes long)
 65   */
 66   setKey: function(key)
 67   {
 68    var pad = function(s){var s=s+'';while(s.length<64) s+="0"; return s},
 69        key = this._blockGen(pad(key),true), i = 0, j = 0,
 70        k = [0,0,0,0,0,0,0,0], block = [0,0,0,0];
 71 
 72    for(i=0; i<2; i++)
 73    {
 74     block = key.gen();
 75     for(j=0; j<4; j++) k[(4*i+j)&7] = block[j&3];
 76    }
 77 
 78    this._setKey(k);
 79   },
 80 
 81   _setKey: function(key)
 82   {
 83    var i = 0, j = 0, rcon = 1, tmp = 0,
 84       encKey = this.key[0],
 85       decKey = this.key[1],
 86     decTable = this.Stables[1],
 87         sbox = this.Stables[0][4];
 88 
 89    for(i = 0; i < 60; i++)
 90    {
 91     if(i < 8)
 92     {
 93      encKey[i & 63] = key[i & 7];
 94      continue;
 95     }
 96 
 97     tmp = encKey[(i-1) & 63];
 98     if(!(i%4))
 99     {
100      tmp = sbox[tmp>>>24 & 255]<<24
101          ^ sbox[tmp>>16  & 255]<<16
102          ^ sbox[tmp>>8   & 255]<<8
103          ^ sbox[tmp & 255];
104 
105      if(!(i%8))
106      {
107       tmp = tmp<<8 ^ tmp>>>24 ^ rcon<<24;
108       rcon = rcon<<1 ^ (rcon>>7)*283;
109      }
110     }
111 
112     encKey[i & 63] = encKey[(i-8) & 63] ^ tmp;
113    }
114   
115    for(j = 0; i>0; j++, i--)
116    {
117     tmp = encKey[(!(j&3) ? i-4 : i)&63];
118 
119     decKey[j & 63] =
120      (i<=4 || j<4) ? tmp :
121      decTable[0][sbox[tmp>>>24 & 255] & 255] ^
122      decTable[1][sbox[tmp>>16  & 255] & 255] ^
123      decTable[2][sbox[tmp>>8   & 255] & 255] ^
124      decTable[3][sbox[tmp      & 255] & 255];
125    }
126   },
127 
128 /** Internal AES block function.
129   * @param {number array[4]} input array of four 32-bit words to process
130   * @param {boolean} dir false for encryption, true for decryption
131   * @returns {number array[8]} result of the encryption
132   */
133   _aes: function(input, dir)
134   {
135    var key = this.key[(!dir ? 0 : 1) & 1],
136          a = input[0] ^ key[0],
137          b = input[(!dir ? 1 : 3) & 3] ^ key[1],
138          c = input[2] ^ key[2],
139          d = input[(!dir ? 3 : 1) & 3] ^ key[3],
140         a2 = 0, b2 = 0, c2 = 0, i = 0, kIndex = 4,
141        out = [0, 0, 0, 0],
142      table = this.Stables[(!dir ? 0 : 1 ) & 1],
143         t0 = table[0], t1 = table[1], t2 = table[2],
144         t3 = table[3], sbox = table[4];
145 
146    for(i = 0; i < 13; i++)
147    {
148     a2 = t0[a>>>24 & 255] ^ t1[b>>16 & 255] ^ t2[c>>8 & 255] ^ t3[d & 255] ^ key[kIndex & 63];
149     b2 = t0[b>>>24 & 255] ^ t1[c>>16 & 255] ^ t2[d>>8 & 255] ^ t3[a & 255] ^ key[(kIndex + 1) & 63];
150     c2 = t0[c>>>24 & 255] ^ t1[d>>16 & 255] ^ t2[a>>8 & 255] ^ t3[b & 255] ^ key[(kIndex + 2) & 63];
151     d  = t0[d>>>24 & 255] ^ t1[a>>16 & 255] ^ t2[b>>8 & 255] ^ t3[c & 255] ^ key[(kIndex + 3) & 63];
152     kIndex += 4; a = a2; b = b2; c = c2;
153    }
154         
155    for(i = 0; i < 4; i++)
156    {
157     out[(!dir ? i : (3&-i)) & 3] =
158     sbox[a>>>24 & 255]<<24 ^ 
159     sbox[b>>16  & 255]<<16 ^
160     sbox[c>>8   & 255]<<8  ^
161     sbox[d      & 255]     ^
162     key[kIndex++ & 63];
163     a2=a; a=b; b=c; c=d; d=a2;
164    }
165 
166    return out;
167   },
168 
169 /** Block generator function, with PKCS#5 support for padding.
170   * @private
171   * @param {string} s input string to process in blocks
172   * @param {boolean} dir false for encryption, true for decryption (no padding)
173   * @returns {blocks:number,gen:()->number array[4]} A record containing the number of blocks and the block generating function
174   */
175   _blockGen: function(s, dir)
176   {
177    var s = s+'', len = s.length, block = 0, i = 0, e = len&15,
178        blocks = (dir?0:1)+(!e?0:1)+(len>>4), pad = (blocks<<4)-len,
179 
180    gen = function()
181    {
182     var res = [0,0,0,0], i = 0, j = 0,
183         m = 0, base = block++ << 4, tmp = 0;
184 
185     for(i = 0; i < 4; i++)
186     {
187      for(tmp = 0, j = base+4*i, m = j+4; j < m; j++)
188       tmp = (tmp<<8)+encoding.a2b(s[(j>>>0)%s.length]);
189      res[i&3] = tmp;
190     }
191     return res;
192    };
193 
194    if(!dir) for(i=0; i<pad; i++) s += encoding.b2a(pad);
195    else while(!!(e++%16)) s += "\x00";
196 
197    return {blocks: blocks, gen: gen};
198   },
199 
200 /** Output processing. By default, returns an ASCII string.
201   * @private
202   * @param {number array[4]} block internal block to output
203   * @param {boolean} last true if this is the last block, false otherwise
204   * @returns {string} ASCII string representing the input block. Will unpad if this is the last block.
205   */
206   _output: function(block, last)
207   {
208    var res = "", i = 0, j = 0, c = 0, pad = 16; 
209 
210    if(last) pad -= 1+block[3]&255;
211 
212    for(i=0; i < 4; i++)
213     for(c = block[i&3], j=0; j<4 && res.length <= pad; j++)
214      res += encoding.b2a(c >> (24-8*j));
215 
216    return res;
217   },
218 
219   _xor4: function(x,y)
220   {
221    return [x[0]^y[0], x[1]^y[1], x[2]^y[2], x[3]^y[3]];
222   },
223 
224 /** CBC mode encryption and decryption using AES.
225   * @param {string} s input plaintext or ciphertext (ASCII string)
226   * @param {string} iv initial vector of the encryption, a 16 bytes ASCII string
227   * @param {boolean} dir false for encryption, true for encryption
228   * @returns {string} result as an ASCII string
229   */
230   CBC: function(s, iv, dir)
231   {
232    var  i = 0, res = "", last = false,
233     input = this._blockGen(s, dir),
234        iv = this._blockGen(iv, true).gen(),
235     block = [0,0,0,0],
236       xor = this._xor4;
237 
238    for(i=0; i<input.blocks; i++)
239    {
240     block = input.gen();
241 
242     if(!dir)
243     {
244      iv = this._aes(xor(iv,block), false);
245      res += this._output(iv, false);
246     }
247     else
248     {
249      res += this._output(xor(iv, this._aes(block,true)), i+1 == input.blocks);
250      iv = block;
251     }
252    }
253 
254    return res;
255   },
256 
257   /** Authenticated encryption in CCM mode (provides ciphertext integrity).
258    * @param {string} s input plaintext (ASCII string)
259    * @param {string} iv Random initialization vector, 16 byte ASCII string
260    * @param {string} adata Optional authentication data (not secret but integrity protected)
261    * @param {number} tlen tag length in bytes (2 to 16) - high values make it harder to tamper with the ciphertext
262    * @return {string} the encrypted data, an ASCII string
263    */
264   CCM_encrypt: function(s, iv2, adata, tlen)
265   {
266    var tlen = (tlen<4 || tlen>16 || !!(tlen&1)) ? 8 : tlen,
267        s=s+'', sl=s.length, ol=sl>>3, L=0, i=0, iv = '',
268        tag = '', res = {data:'', tag:''};
269 
270    for(L=2; L<4 && !!(ol>>>8*L); L++);
271    for(iv2+='';iv2.length < 16; iv2+="\x00");
272    for(i=0; i<iv2.length; i++){ iv += iv2[i]; if(i>13-L) break }
273  
274    tag = this._ccmTag(s, iv, adata, tlen, L);
275    res = this._ctrMode(s, iv, tag, tlen, L);
276 
277    return res.data + res.tag;
278   },
279   
280   /** Decryption in CCM mode.
281    * @param {string} s input ciphertext
282    * @param {string} iv random initialization vector (ASCII string)
283    * @param {string} adata Optional authenticated data (ASCII)
284    * @param {number} tlen tag length in bytes
285    * @return {valid:bolean,data:string} Object containing the decrypted data and authentication status
286    */
287   CCM_decrypt: function(s, iv2, adata, tlen)
288   {
289    var tlen = (tlen<4 || tlen>16 || !!(tlen&1)) ? 8 : tlen,
290        s=s+'', sl=s.length, c = '', ol=(sl-tlen)>>3, L=0,
291        i=0, res = {data:'',tag:''}, tag = '', iv = '';
292 
293    for(i=0; i<s.length; i++)
294    {
295     if(i < sl-tlen) c += s[i];
296     else tag += s[i];
297    }
298 
299    for(L=2; L<4 && !!(ol>>>8*L); L++);
300    for(iv2+='';iv2.length < 16; iv2+="\x00");
301    for(i=0; i<iv2.length; i++){ iv += iv2[i]; if(i>13-L) break }
302 
303    res = this._ctrMode(c, iv, tag, tlen, L);
304    s = this._ccmTag(res.data, iv, adata, tlen, L);
305 
306    return {valid: s==res.tag, data: res.data};
307   },
308 
309   _ccmTag: function(s, iv, adata, tlen, L)
310   {
311    var i=0, s=s+'', sl=s.length, xor = this._xor4, c = [0,0,0,0],
312        ad = (function(x){var x=x+'', n=x.length, c=function(n){
313        return encoding.b2a(n)}; if(!n) return x; if(n<=0xFEFF)
314        return c(n>>16)+c(n&255)+x; return "\xff\xfe"+c(n>>>24)+
315        c(n>>16&255)+c(n>>8&255)+c(n&255)+x})(adata), res = '', T = '',
316        p = this._blockGen(s, true), q = this._blockGen(ad, true);
317 
318    mac = encoding.b2a(((adata==''?0:1)<<6) | (((tlen-2)>>1)<<3) | (L-1))+iv;
319    for(i=15-mac.length; i>=0; i--) mac += encoding.b2a(i>3?0:sl>>>8*i);
320    c = this._aes(this._blockGen(mac,true).gen(), false);
321 
322    if(!!ad) // Additional data
323     for(i=0; i<q.blocks; i++) c = this._aes(xor(c, q.gen()), false);
324    for(i=0; i<p.blocks; i++) c = this._aes(xor(c, p.gen()), false);
325 
326    T = this._output(c, false);
327    for(i=0; i<T.length; i++)
328    {
329     res += T[i];
330     if(i+1 == tlen) break;
331    }
332 
333    return res;
334   },
335 
336   _ctrMode: function(s, iv, tag, tlen, L)
337   {
338    var ctr = this._blockGen(encoding.b2a(L-1)+iv, true).gen(), tag0=tag,
339        xor = this._xor4, res = "", D = this._blockGen(s, true), sl=s.length,
340        tag = xor(this._blockGen(tag, true).gen(), this._aes(ctr, false)),
341        ts = '', i = 0, c = "", j = 0;
342 
343    c = this._output(tag, false);
344    for(i=0; i<c.length; i++){ ts+=c[i]; if(i+1==tlen) break; }
345 
346    for (i=0; i<D.blocks; i++)
347    {
348     ctr[3]++;
349     c = this._output(xor(D.gen(), this._aes(ctr, false)), false);
350     for(j=0; j<c.length; j++)
351     {
352      res += c[j];
353      if(res.length == sl) break;
354     }
355    }
356 
357    return {tag:ts, data:res};
358   }
359  };
360 
361