cipherModes.js 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999
  1. /**
  2. * Supported cipher modes.
  3. *
  4. * @author Dave Longley
  5. *
  6. * Copyright (c) 2010-2014 Digital Bazaar, Inc.
  7. */
  8. var forge = require('./forge');
  9. require('./util');
  10. forge.cipher = forge.cipher || {};
  11. // supported cipher modes
  12. var modes = module.exports = forge.cipher.modes = forge.cipher.modes || {};
  13. /** Electronic codebook (ECB) (Don't use this; it's not secure) **/
  14. modes.ecb = function(options) {
  15. options = options || {};
  16. this.name = 'ECB';
  17. this.cipher = options.cipher;
  18. this.blockSize = options.blockSize || 16;
  19. this._ints = this.blockSize / 4;
  20. this._inBlock = new Array(this._ints);
  21. this._outBlock = new Array(this._ints);
  22. };
  23. modes.ecb.prototype.start = function(options) {};
  24. modes.ecb.prototype.encrypt = function(input, output, finish) {
  25. // not enough input to encrypt
  26. if(input.length() < this.blockSize && !(finish && input.length() > 0)) {
  27. return true;
  28. }
  29. // get next block
  30. for(var i = 0; i < this._ints; ++i) {
  31. this._inBlock[i] = input.getInt32();
  32. }
  33. // encrypt block
  34. this.cipher.encrypt(this._inBlock, this._outBlock);
  35. // write output
  36. for(var i = 0; i < this._ints; ++i) {
  37. output.putInt32(this._outBlock[i]);
  38. }
  39. };
  40. modes.ecb.prototype.decrypt = function(input, output, finish) {
  41. // not enough input to decrypt
  42. if(input.length() < this.blockSize && !(finish && input.length() > 0)) {
  43. return true;
  44. }
  45. // get next block
  46. for(var i = 0; i < this._ints; ++i) {
  47. this._inBlock[i] = input.getInt32();
  48. }
  49. // decrypt block
  50. this.cipher.decrypt(this._inBlock, this._outBlock);
  51. // write output
  52. for(var i = 0; i < this._ints; ++i) {
  53. output.putInt32(this._outBlock[i]);
  54. }
  55. };
  56. modes.ecb.prototype.pad = function(input, options) {
  57. // add PKCS#7 padding to block (each pad byte is the
  58. // value of the number of pad bytes)
  59. var padding = (input.length() === this.blockSize ?
  60. this.blockSize : (this.blockSize - input.length()));
  61. input.fillWithByte(padding, padding);
  62. return true;
  63. };
  64. modes.ecb.prototype.unpad = function(output, options) {
  65. // check for error: input data not a multiple of blockSize
  66. if(options.overflow > 0) {
  67. return false;
  68. }
  69. // ensure padding byte count is valid
  70. var len = output.length();
  71. var count = output.at(len - 1);
  72. if(count > (this.blockSize << 2)) {
  73. return false;
  74. }
  75. // trim off padding bytes
  76. output.truncate(count);
  77. return true;
  78. };
  79. /** Cipher-block Chaining (CBC) **/
  80. modes.cbc = function(options) {
  81. options = options || {};
  82. this.name = 'CBC';
  83. this.cipher = options.cipher;
  84. this.blockSize = options.blockSize || 16;
  85. this._ints = this.blockSize / 4;
  86. this._inBlock = new Array(this._ints);
  87. this._outBlock = new Array(this._ints);
  88. };
  89. modes.cbc.prototype.start = function(options) {
  90. // Note: legacy support for using IV residue (has security flaws)
  91. // if IV is null, reuse block from previous processing
  92. if(options.iv === null) {
  93. // must have a previous block
  94. if(!this._prev) {
  95. throw new Error('Invalid IV parameter.');
  96. }
  97. this._iv = this._prev.slice(0);
  98. } else if(!('iv' in options)) {
  99. throw new Error('Invalid IV parameter.');
  100. } else {
  101. // save IV as "previous" block
  102. this._iv = transformIV(options.iv, this.blockSize);
  103. this._prev = this._iv.slice(0);
  104. }
  105. };
  106. modes.cbc.prototype.encrypt = function(input, output, finish) {
  107. // not enough input to encrypt
  108. if(input.length() < this.blockSize && !(finish && input.length() > 0)) {
  109. return true;
  110. }
  111. // get next block
  112. // CBC XOR's IV (or previous block) with plaintext
  113. for(var i = 0; i < this._ints; ++i) {
  114. this._inBlock[i] = this._prev[i] ^ input.getInt32();
  115. }
  116. // encrypt block
  117. this.cipher.encrypt(this._inBlock, this._outBlock);
  118. // write output, save previous block
  119. for(var i = 0; i < this._ints; ++i) {
  120. output.putInt32(this._outBlock[i]);
  121. }
  122. this._prev = this._outBlock;
  123. };
  124. modes.cbc.prototype.decrypt = function(input, output, finish) {
  125. // not enough input to decrypt
  126. if(input.length() < this.blockSize && !(finish && input.length() > 0)) {
  127. return true;
  128. }
  129. // get next block
  130. for(var i = 0; i < this._ints; ++i) {
  131. this._inBlock[i] = input.getInt32();
  132. }
  133. // decrypt block
  134. this.cipher.decrypt(this._inBlock, this._outBlock);
  135. // write output, save previous ciphered block
  136. // CBC XOR's IV (or previous block) with ciphertext
  137. for(var i = 0; i < this._ints; ++i) {
  138. output.putInt32(this._prev[i] ^ this._outBlock[i]);
  139. }
  140. this._prev = this._inBlock.slice(0);
  141. };
  142. modes.cbc.prototype.pad = function(input, options) {
  143. // add PKCS#7 padding to block (each pad byte is the
  144. // value of the number of pad bytes)
  145. var padding = (input.length() === this.blockSize ?
  146. this.blockSize : (this.blockSize - input.length()));
  147. input.fillWithByte(padding, padding);
  148. return true;
  149. };
  150. modes.cbc.prototype.unpad = function(output, options) {
  151. // check for error: input data not a multiple of blockSize
  152. if(options.overflow > 0) {
  153. return false;
  154. }
  155. // ensure padding byte count is valid
  156. var len = output.length();
  157. var count = output.at(len - 1);
  158. if(count > (this.blockSize << 2)) {
  159. return false;
  160. }
  161. // trim off padding bytes
  162. output.truncate(count);
  163. return true;
  164. };
  165. /** Cipher feedback (CFB) **/
  166. modes.cfb = function(options) {
  167. options = options || {};
  168. this.name = 'CFB';
  169. this.cipher = options.cipher;
  170. this.blockSize = options.blockSize || 16;
  171. this._ints = this.blockSize / 4;
  172. this._inBlock = null;
  173. this._outBlock = new Array(this._ints);
  174. this._partialBlock = new Array(this._ints);
  175. this._partialOutput = forge.util.createBuffer();
  176. this._partialBytes = 0;
  177. };
  178. modes.cfb.prototype.start = function(options) {
  179. if(!('iv' in options)) {
  180. throw new Error('Invalid IV parameter.');
  181. }
  182. // use IV as first input
  183. this._iv = transformIV(options.iv, this.blockSize);
  184. this._inBlock = this._iv.slice(0);
  185. this._partialBytes = 0;
  186. };
  187. modes.cfb.prototype.encrypt = function(input, output, finish) {
  188. // not enough input to encrypt
  189. var inputLength = input.length();
  190. if(inputLength === 0) {
  191. return true;
  192. }
  193. // encrypt block
  194. this.cipher.encrypt(this._inBlock, this._outBlock);
  195. // handle full block
  196. if(this._partialBytes === 0 && inputLength >= this.blockSize) {
  197. // XOR input with output, write input as output
  198. for(var i = 0; i < this._ints; ++i) {
  199. this._inBlock[i] = input.getInt32() ^ this._outBlock[i];
  200. output.putInt32(this._inBlock[i]);
  201. }
  202. return;
  203. }
  204. // handle partial block
  205. var partialBytes = (this.blockSize - inputLength) % this.blockSize;
  206. if(partialBytes > 0) {
  207. partialBytes = this.blockSize - partialBytes;
  208. }
  209. // XOR input with output, write input as partial output
  210. this._partialOutput.clear();
  211. for(var i = 0; i < this._ints; ++i) {
  212. this._partialBlock[i] = input.getInt32() ^ this._outBlock[i];
  213. this._partialOutput.putInt32(this._partialBlock[i]);
  214. }
  215. if(partialBytes > 0) {
  216. // block still incomplete, restore input buffer
  217. input.read -= this.blockSize;
  218. } else {
  219. // block complete, update input block
  220. for(var i = 0; i < this._ints; ++i) {
  221. this._inBlock[i] = this._partialBlock[i];
  222. }
  223. }
  224. // skip any previous partial bytes
  225. if(this._partialBytes > 0) {
  226. this._partialOutput.getBytes(this._partialBytes);
  227. }
  228. if(partialBytes > 0 && !finish) {
  229. output.putBytes(this._partialOutput.getBytes(
  230. partialBytes - this._partialBytes));
  231. this._partialBytes = partialBytes;
  232. return true;
  233. }
  234. output.putBytes(this._partialOutput.getBytes(
  235. inputLength - this._partialBytes));
  236. this._partialBytes = 0;
  237. };
  238. modes.cfb.prototype.decrypt = function(input, output, finish) {
  239. // not enough input to decrypt
  240. var inputLength = input.length();
  241. if(inputLength === 0) {
  242. return true;
  243. }
  244. // encrypt block (CFB always uses encryption mode)
  245. this.cipher.encrypt(this._inBlock, this._outBlock);
  246. // handle full block
  247. if(this._partialBytes === 0 && inputLength >= this.blockSize) {
  248. // XOR input with output, write input as output
  249. for(var i = 0; i < this._ints; ++i) {
  250. this._inBlock[i] = input.getInt32();
  251. output.putInt32(this._inBlock[i] ^ this._outBlock[i]);
  252. }
  253. return;
  254. }
  255. // handle partial block
  256. var partialBytes = (this.blockSize - inputLength) % this.blockSize;
  257. if(partialBytes > 0) {
  258. partialBytes = this.blockSize - partialBytes;
  259. }
  260. // XOR input with output, write input as partial output
  261. this._partialOutput.clear();
  262. for(var i = 0; i < this._ints; ++i) {
  263. this._partialBlock[i] = input.getInt32();
  264. this._partialOutput.putInt32(this._partialBlock[i] ^ this._outBlock[i]);
  265. }
  266. if(partialBytes > 0) {
  267. // block still incomplete, restore input buffer
  268. input.read -= this.blockSize;
  269. } else {
  270. // block complete, update input block
  271. for(var i = 0; i < this._ints; ++i) {
  272. this._inBlock[i] = this._partialBlock[i];
  273. }
  274. }
  275. // skip any previous partial bytes
  276. if(this._partialBytes > 0) {
  277. this._partialOutput.getBytes(this._partialBytes);
  278. }
  279. if(partialBytes > 0 && !finish) {
  280. output.putBytes(this._partialOutput.getBytes(
  281. partialBytes - this._partialBytes));
  282. this._partialBytes = partialBytes;
  283. return true;
  284. }
  285. output.putBytes(this._partialOutput.getBytes(
  286. inputLength - this._partialBytes));
  287. this._partialBytes = 0;
  288. };
  289. /** Output feedback (OFB) **/
  290. modes.ofb = function(options) {
  291. options = options || {};
  292. this.name = 'OFB';
  293. this.cipher = options.cipher;
  294. this.blockSize = options.blockSize || 16;
  295. this._ints = this.blockSize / 4;
  296. this._inBlock = null;
  297. this._outBlock = new Array(this._ints);
  298. this._partialOutput = forge.util.createBuffer();
  299. this._partialBytes = 0;
  300. };
  301. modes.ofb.prototype.start = function(options) {
  302. if(!('iv' in options)) {
  303. throw new Error('Invalid IV parameter.');
  304. }
  305. // use IV as first input
  306. this._iv = transformIV(options.iv, this.blockSize);
  307. this._inBlock = this._iv.slice(0);
  308. this._partialBytes = 0;
  309. };
  310. modes.ofb.prototype.encrypt = function(input, output, finish) {
  311. // not enough input to encrypt
  312. var inputLength = input.length();
  313. if(input.length() === 0) {
  314. return true;
  315. }
  316. // encrypt block (OFB always uses encryption mode)
  317. this.cipher.encrypt(this._inBlock, this._outBlock);
  318. // handle full block
  319. if(this._partialBytes === 0 && inputLength >= this.blockSize) {
  320. // XOR input with output and update next input
  321. for(var i = 0; i < this._ints; ++i) {
  322. output.putInt32(input.getInt32() ^ this._outBlock[i]);
  323. this._inBlock[i] = this._outBlock[i];
  324. }
  325. return;
  326. }
  327. // handle partial block
  328. var partialBytes = (this.blockSize - inputLength) % this.blockSize;
  329. if(partialBytes > 0) {
  330. partialBytes = this.blockSize - partialBytes;
  331. }
  332. // XOR input with output
  333. this._partialOutput.clear();
  334. for(var i = 0; i < this._ints; ++i) {
  335. this._partialOutput.putInt32(input.getInt32() ^ this._outBlock[i]);
  336. }
  337. if(partialBytes > 0) {
  338. // block still incomplete, restore input buffer
  339. input.read -= this.blockSize;
  340. } else {
  341. // block complete, update input block
  342. for(var i = 0; i < this._ints; ++i) {
  343. this._inBlock[i] = this._outBlock[i];
  344. }
  345. }
  346. // skip any previous partial bytes
  347. if(this._partialBytes > 0) {
  348. this._partialOutput.getBytes(this._partialBytes);
  349. }
  350. if(partialBytes > 0 && !finish) {
  351. output.putBytes(this._partialOutput.getBytes(
  352. partialBytes - this._partialBytes));
  353. this._partialBytes = partialBytes;
  354. return true;
  355. }
  356. output.putBytes(this._partialOutput.getBytes(
  357. inputLength - this._partialBytes));
  358. this._partialBytes = 0;
  359. };
  360. modes.ofb.prototype.decrypt = modes.ofb.prototype.encrypt;
  361. /** Counter (CTR) **/
  362. modes.ctr = function(options) {
  363. options = options || {};
  364. this.name = 'CTR';
  365. this.cipher = options.cipher;
  366. this.blockSize = options.blockSize || 16;
  367. this._ints = this.blockSize / 4;
  368. this._inBlock = null;
  369. this._outBlock = new Array(this._ints);
  370. this._partialOutput = forge.util.createBuffer();
  371. this._partialBytes = 0;
  372. };
  373. modes.ctr.prototype.start = function(options) {
  374. if(!('iv' in options)) {
  375. throw new Error('Invalid IV parameter.');
  376. }
  377. // use IV as first input
  378. this._iv = transformIV(options.iv, this.blockSize);
  379. this._inBlock = this._iv.slice(0);
  380. this._partialBytes = 0;
  381. };
  382. modes.ctr.prototype.encrypt = function(input, output, finish) {
  383. // not enough input to encrypt
  384. var inputLength = input.length();
  385. if(inputLength === 0) {
  386. return true;
  387. }
  388. // encrypt block (CTR always uses encryption mode)
  389. this.cipher.encrypt(this._inBlock, this._outBlock);
  390. // handle full block
  391. if(this._partialBytes === 0 && inputLength >= this.blockSize) {
  392. // XOR input with output
  393. for(var i = 0; i < this._ints; ++i) {
  394. output.putInt32(input.getInt32() ^ this._outBlock[i]);
  395. }
  396. } else {
  397. // handle partial block
  398. var partialBytes = (this.blockSize - inputLength) % this.blockSize;
  399. if(partialBytes > 0) {
  400. partialBytes = this.blockSize - partialBytes;
  401. }
  402. // XOR input with output
  403. this._partialOutput.clear();
  404. for(var i = 0; i < this._ints; ++i) {
  405. this._partialOutput.putInt32(input.getInt32() ^ this._outBlock[i]);
  406. }
  407. if(partialBytes > 0) {
  408. // block still incomplete, restore input buffer
  409. input.read -= this.blockSize;
  410. }
  411. // skip any previous partial bytes
  412. if(this._partialBytes > 0) {
  413. this._partialOutput.getBytes(this._partialBytes);
  414. }
  415. if(partialBytes > 0 && !finish) {
  416. output.putBytes(this._partialOutput.getBytes(
  417. partialBytes - this._partialBytes));
  418. this._partialBytes = partialBytes;
  419. return true;
  420. }
  421. output.putBytes(this._partialOutput.getBytes(
  422. inputLength - this._partialBytes));
  423. this._partialBytes = 0;
  424. }
  425. // block complete, increment counter (input block)
  426. inc32(this._inBlock);
  427. };
  428. modes.ctr.prototype.decrypt = modes.ctr.prototype.encrypt;
  429. /** Galois/Counter Mode (GCM) **/
  430. modes.gcm = function(options) {
  431. options = options || {};
  432. this.name = 'GCM';
  433. this.cipher = options.cipher;
  434. this.blockSize = options.blockSize || 16;
  435. this._ints = this.blockSize / 4;
  436. this._inBlock = new Array(this._ints);
  437. this._outBlock = new Array(this._ints);
  438. this._partialOutput = forge.util.createBuffer();
  439. this._partialBytes = 0;
  440. // R is actually this value concatenated with 120 more zero bits, but
  441. // we only XOR against R so the other zeros have no effect -- we just
  442. // apply this value to the first integer in a block
  443. this._R = 0xE1000000;
  444. };
  445. modes.gcm.prototype.start = function(options) {
  446. if(!('iv' in options)) {
  447. throw new Error('Invalid IV parameter.');
  448. }
  449. // ensure IV is a byte buffer
  450. var iv = forge.util.createBuffer(options.iv);
  451. // no ciphered data processed yet
  452. this._cipherLength = 0;
  453. // default additional data is none
  454. var additionalData;
  455. if('additionalData' in options) {
  456. additionalData = forge.util.createBuffer(options.additionalData);
  457. } else {
  458. additionalData = forge.util.createBuffer();
  459. }
  460. // default tag length is 128 bits
  461. if('tagLength' in options) {
  462. this._tagLength = options.tagLength;
  463. } else {
  464. this._tagLength = 128;
  465. }
  466. // if tag is given, ensure tag matches tag length
  467. this._tag = null;
  468. if(options.decrypt) {
  469. // save tag to check later
  470. this._tag = forge.util.createBuffer(options.tag).getBytes();
  471. if(this._tag.length !== (this._tagLength / 8)) {
  472. throw new Error('Authentication tag does not match tag length.');
  473. }
  474. }
  475. // create tmp storage for hash calculation
  476. this._hashBlock = new Array(this._ints);
  477. // no tag generated yet
  478. this.tag = null;
  479. // generate hash subkey
  480. // (apply block cipher to "zero" block)
  481. this._hashSubkey = new Array(this._ints);
  482. this.cipher.encrypt([0, 0, 0, 0], this._hashSubkey);
  483. // generate table M
  484. // use 4-bit tables (32 component decomposition of a 16 byte value)
  485. // 8-bit tables take more space and are known to have security
  486. // vulnerabilities (in native implementations)
  487. this.componentBits = 4;
  488. this._m = this.generateHashTable(this._hashSubkey, this.componentBits);
  489. // Note: support IV length different from 96 bits? (only supporting
  490. // 96 bits is recommended by NIST SP-800-38D)
  491. // generate J_0
  492. var ivLength = iv.length();
  493. if(ivLength === 12) {
  494. // 96-bit IV
  495. this._j0 = [iv.getInt32(), iv.getInt32(), iv.getInt32(), 1];
  496. } else {
  497. // IV is NOT 96-bits
  498. this._j0 = [0, 0, 0, 0];
  499. while(iv.length() > 0) {
  500. this._j0 = this.ghash(
  501. this._hashSubkey, this._j0,
  502. [iv.getInt32(), iv.getInt32(), iv.getInt32(), iv.getInt32()]);
  503. }
  504. this._j0 = this.ghash(
  505. this._hashSubkey, this._j0, [0, 0].concat(from64To32(ivLength * 8)));
  506. }
  507. // generate ICB (initial counter block)
  508. this._inBlock = this._j0.slice(0);
  509. inc32(this._inBlock);
  510. this._partialBytes = 0;
  511. // consume authentication data
  512. additionalData = forge.util.createBuffer(additionalData);
  513. // save additional data length as a BE 64-bit number
  514. this._aDataLength = from64To32(additionalData.length() * 8);
  515. // pad additional data to 128 bit (16 byte) block size
  516. var overflow = additionalData.length() % this.blockSize;
  517. if(overflow) {
  518. additionalData.fillWithByte(0, this.blockSize - overflow);
  519. }
  520. this._s = [0, 0, 0, 0];
  521. while(additionalData.length() > 0) {
  522. this._s = this.ghash(this._hashSubkey, this._s, [
  523. additionalData.getInt32(),
  524. additionalData.getInt32(),
  525. additionalData.getInt32(),
  526. additionalData.getInt32()
  527. ]);
  528. }
  529. };
  530. modes.gcm.prototype.encrypt = function(input, output, finish) {
  531. // not enough input to encrypt
  532. var inputLength = input.length();
  533. if(inputLength === 0) {
  534. return true;
  535. }
  536. // encrypt block
  537. this.cipher.encrypt(this._inBlock, this._outBlock);
  538. // handle full block
  539. if(this._partialBytes === 0 && inputLength >= this.blockSize) {
  540. // XOR input with output
  541. for(var i = 0; i < this._ints; ++i) {
  542. output.putInt32(this._outBlock[i] ^= input.getInt32());
  543. }
  544. this._cipherLength += this.blockSize;
  545. } else {
  546. // handle partial block
  547. var partialBytes = (this.blockSize - inputLength) % this.blockSize;
  548. if(partialBytes > 0) {
  549. partialBytes = this.blockSize - partialBytes;
  550. }
  551. // XOR input with output
  552. this._partialOutput.clear();
  553. for(var i = 0; i < this._ints; ++i) {
  554. this._partialOutput.putInt32(input.getInt32() ^ this._outBlock[i]);
  555. }
  556. if(partialBytes <= 0 || finish) {
  557. // handle overflow prior to hashing
  558. if(finish) {
  559. // get block overflow
  560. var overflow = inputLength % this.blockSize;
  561. this._cipherLength += overflow;
  562. // truncate for hash function
  563. this._partialOutput.truncate(this.blockSize - overflow);
  564. } else {
  565. this._cipherLength += this.blockSize;
  566. }
  567. // get output block for hashing
  568. for(var i = 0; i < this._ints; ++i) {
  569. this._outBlock[i] = this._partialOutput.getInt32();
  570. }
  571. this._partialOutput.read -= this.blockSize;
  572. }
  573. // skip any previous partial bytes
  574. if(this._partialBytes > 0) {
  575. this._partialOutput.getBytes(this._partialBytes);
  576. }
  577. if(partialBytes > 0 && !finish) {
  578. // block still incomplete, restore input buffer, get partial output,
  579. // and return early
  580. input.read -= this.blockSize;
  581. output.putBytes(this._partialOutput.getBytes(
  582. partialBytes - this._partialBytes));
  583. this._partialBytes = partialBytes;
  584. return true;
  585. }
  586. output.putBytes(this._partialOutput.getBytes(
  587. inputLength - this._partialBytes));
  588. this._partialBytes = 0;
  589. }
  590. // update hash block S
  591. this._s = this.ghash(this._hashSubkey, this._s, this._outBlock);
  592. // increment counter (input block)
  593. inc32(this._inBlock);
  594. };
  595. modes.gcm.prototype.decrypt = function(input, output, finish) {
  596. // not enough input to decrypt
  597. var inputLength = input.length();
  598. if(inputLength < this.blockSize && !(finish && inputLength > 0)) {
  599. return true;
  600. }
  601. // encrypt block (GCM always uses encryption mode)
  602. this.cipher.encrypt(this._inBlock, this._outBlock);
  603. // increment counter (input block)
  604. inc32(this._inBlock);
  605. // update hash block S
  606. this._hashBlock[0] = input.getInt32();
  607. this._hashBlock[1] = input.getInt32();
  608. this._hashBlock[2] = input.getInt32();
  609. this._hashBlock[3] = input.getInt32();
  610. this._s = this.ghash(this._hashSubkey, this._s, this._hashBlock);
  611. // XOR hash input with output
  612. for(var i = 0; i < this._ints; ++i) {
  613. output.putInt32(this._outBlock[i] ^ this._hashBlock[i]);
  614. }
  615. // increment cipher data length
  616. if(inputLength < this.blockSize) {
  617. this._cipherLength += inputLength % this.blockSize;
  618. } else {
  619. this._cipherLength += this.blockSize;
  620. }
  621. };
  622. modes.gcm.prototype.afterFinish = function(output, options) {
  623. var rval = true;
  624. // handle overflow
  625. if(options.decrypt && options.overflow) {
  626. output.truncate(this.blockSize - options.overflow);
  627. }
  628. // handle authentication tag
  629. this.tag = forge.util.createBuffer();
  630. // concatenate additional data length with cipher length
  631. var lengths = this._aDataLength.concat(from64To32(this._cipherLength * 8));
  632. // include lengths in hash
  633. this._s = this.ghash(this._hashSubkey, this._s, lengths);
  634. // do GCTR(J_0, S)
  635. var tag = [];
  636. this.cipher.encrypt(this._j0, tag);
  637. for(var i = 0; i < this._ints; ++i) {
  638. this.tag.putInt32(this._s[i] ^ tag[i]);
  639. }
  640. // trim tag to length
  641. this.tag.truncate(this.tag.length() % (this._tagLength / 8));
  642. // check authentication tag
  643. if(options.decrypt && this.tag.bytes() !== this._tag) {
  644. rval = false;
  645. }
  646. return rval;
  647. };
  648. /**
  649. * See NIST SP-800-38D 6.3 (Algorithm 1). This function performs Galois
  650. * field multiplication. The field, GF(2^128), is defined by the polynomial:
  651. *
  652. * x^128 + x^7 + x^2 + x + 1
  653. *
  654. * Which is represented in little-endian binary form as: 11100001 (0xe1). When
  655. * the value of a coefficient is 1, a bit is set. The value R, is the
  656. * concatenation of this value and 120 zero bits, yielding a 128-bit value
  657. * which matches the block size.
  658. *
  659. * This function will multiply two elements (vectors of bytes), X and Y, in
  660. * the field GF(2^128). The result is initialized to zero. For each bit of
  661. * X (out of 128), x_i, if x_i is set, then the result is multiplied (XOR'd)
  662. * by the current value of Y. For each bit, the value of Y will be raised by
  663. * a power of x (multiplied by the polynomial x). This can be achieved by
  664. * shifting Y once to the right. If the current value of Y, prior to being
  665. * multiplied by x, has 0 as its LSB, then it is a 127th degree polynomial.
  666. * Otherwise, we must divide by R after shifting to find the remainder.
  667. *
  668. * @param x the first block to multiply by the second.
  669. * @param y the second block to multiply by the first.
  670. *
  671. * @return the block result of the multiplication.
  672. */
  673. modes.gcm.prototype.multiply = function(x, y) {
  674. var z_i = [0, 0, 0, 0];
  675. var v_i = y.slice(0);
  676. // calculate Z_128 (block has 128 bits)
  677. for(var i = 0; i < 128; ++i) {
  678. // if x_i is 0, Z_{i+1} = Z_i (unchanged)
  679. // else Z_{i+1} = Z_i ^ V_i
  680. // get x_i by finding 32-bit int position, then left shift 1 by remainder
  681. var x_i = x[(i / 32) | 0] & (1 << (31 - i % 32));
  682. if(x_i) {
  683. z_i[0] ^= v_i[0];
  684. z_i[1] ^= v_i[1];
  685. z_i[2] ^= v_i[2];
  686. z_i[3] ^= v_i[3];
  687. }
  688. // if LSB(V_i) is 1, V_i = V_i >> 1
  689. // else V_i = (V_i >> 1) ^ R
  690. this.pow(v_i, v_i);
  691. }
  692. return z_i;
  693. };
  694. modes.gcm.prototype.pow = function(x, out) {
  695. // if LSB(x) is 1, x = x >>> 1
  696. // else x = (x >>> 1) ^ R
  697. var lsb = x[3] & 1;
  698. // always do x >>> 1:
  699. // starting with the rightmost integer, shift each integer to the right
  700. // one bit, pulling in the bit from the integer to the left as its top
  701. // most bit (do this for the last 3 integers)
  702. for(var i = 3; i > 0; --i) {
  703. out[i] = (x[i] >>> 1) | ((x[i - 1] & 1) << 31);
  704. }
  705. // shift the first integer normally
  706. out[0] = x[0] >>> 1;
  707. // if lsb was not set, then polynomial had a degree of 127 and doesn't
  708. // need to divided; otherwise, XOR with R to find the remainder; we only
  709. // need to XOR the first integer since R technically ends w/120 zero bits
  710. if(lsb) {
  711. out[0] ^= this._R;
  712. }
  713. };
  714. modes.gcm.prototype.tableMultiply = function(x) {
  715. // assumes 4-bit tables are used
  716. var z = [0, 0, 0, 0];
  717. for(var i = 0; i < 32; ++i) {
  718. var idx = (i / 8) | 0;
  719. var x_i = (x[idx] >>> ((7 - (i % 8)) * 4)) & 0xF;
  720. var ah = this._m[i][x_i];
  721. z[0] ^= ah[0];
  722. z[1] ^= ah[1];
  723. z[2] ^= ah[2];
  724. z[3] ^= ah[3];
  725. }
  726. return z;
  727. };
  728. /**
  729. * A continuing version of the GHASH algorithm that operates on a single
  730. * block. The hash block, last hash value (Ym) and the new block to hash
  731. * are given.
  732. *
  733. * @param h the hash block.
  734. * @param y the previous value for Ym, use [0, 0, 0, 0] for a new hash.
  735. * @param x the block to hash.
  736. *
  737. * @return the hashed value (Ym).
  738. */
  739. modes.gcm.prototype.ghash = function(h, y, x) {
  740. y[0] ^= x[0];
  741. y[1] ^= x[1];
  742. y[2] ^= x[2];
  743. y[3] ^= x[3];
  744. return this.tableMultiply(y);
  745. //return this.multiply(y, h);
  746. };
  747. /**
  748. * Precomputes a table for multiplying against the hash subkey. This
  749. * mechanism provides a substantial speed increase over multiplication
  750. * performed without a table. The table-based multiplication this table is
  751. * for solves X * H by multiplying each component of X by H and then
  752. * composing the results together using XOR.
  753. *
  754. * This function can be used to generate tables with different bit sizes
  755. * for the components, however, this implementation assumes there are
  756. * 32 components of X (which is a 16 byte vector), therefore each component
  757. * takes 4-bits (so the table is constructed with bits=4).
  758. *
  759. * @param h the hash subkey.
  760. * @param bits the bit size for a component.
  761. */
  762. modes.gcm.prototype.generateHashTable = function(h, bits) {
  763. // TODO: There are further optimizations that would use only the
  764. // first table M_0 (or some variant) along with a remainder table;
  765. // this can be explored in the future
  766. var multiplier = 8 / bits;
  767. var perInt = 4 * multiplier;
  768. var size = 16 * multiplier;
  769. var m = new Array(size);
  770. for(var i = 0; i < size; ++i) {
  771. var tmp = [0, 0, 0, 0];
  772. var idx = (i / perInt) | 0;
  773. var shft = ((perInt - 1 - (i % perInt)) * bits);
  774. tmp[idx] = (1 << (bits - 1)) << shft;
  775. m[i] = this.generateSubHashTable(this.multiply(tmp, h), bits);
  776. }
  777. return m;
  778. };
  779. /**
  780. * Generates a table for multiplying against the hash subkey for one
  781. * particular component (out of all possible component values).
  782. *
  783. * @param mid the pre-multiplied value for the middle key of the table.
  784. * @param bits the bit size for a component.
  785. */
  786. modes.gcm.prototype.generateSubHashTable = function(mid, bits) {
  787. // compute the table quickly by minimizing the number of
  788. // POW operations -- they only need to be performed for powers of 2,
  789. // all other entries can be composed from those powers using XOR
  790. var size = 1 << bits;
  791. var half = size >>> 1;
  792. var m = new Array(size);
  793. m[half] = mid.slice(0);
  794. var i = half >>> 1;
  795. while(i > 0) {
  796. // raise m0[2 * i] and store in m0[i]
  797. this.pow(m[2 * i], m[i] = []);
  798. i >>= 1;
  799. }
  800. i = 2;
  801. while(i < half) {
  802. for(var j = 1; j < i; ++j) {
  803. var m_i = m[i];
  804. var m_j = m[j];
  805. m[i + j] = [
  806. m_i[0] ^ m_j[0],
  807. m_i[1] ^ m_j[1],
  808. m_i[2] ^ m_j[2],
  809. m_i[3] ^ m_j[3]
  810. ];
  811. }
  812. i *= 2;
  813. }
  814. m[0] = [0, 0, 0, 0];
  815. /* Note: We could avoid storing these by doing composition during multiply
  816. calculate top half using composition by speed is preferred. */
  817. for(i = half + 1; i < size; ++i) {
  818. var c = m[i ^ half];
  819. m[i] = [mid[0] ^ c[0], mid[1] ^ c[1], mid[2] ^ c[2], mid[3] ^ c[3]];
  820. }
  821. return m;
  822. };
  823. /** Utility functions */
  824. function transformIV(iv, blockSize) {
  825. if(typeof iv === 'string') {
  826. // convert iv string into byte buffer
  827. iv = forge.util.createBuffer(iv);
  828. }
  829. if(forge.util.isArray(iv) && iv.length > 4) {
  830. // convert iv byte array into byte buffer
  831. var tmp = iv;
  832. iv = forge.util.createBuffer();
  833. for(var i = 0; i < tmp.length; ++i) {
  834. iv.putByte(tmp[i]);
  835. }
  836. }
  837. if(iv.length() < blockSize) {
  838. throw new Error(
  839. 'Invalid IV length; got ' + iv.length() +
  840. ' bytes and expected ' + blockSize + ' bytes.');
  841. }
  842. if(!forge.util.isArray(iv)) {
  843. // convert iv byte buffer into 32-bit integer array
  844. var ints = [];
  845. var blocks = blockSize / 4;
  846. for(var i = 0; i < blocks; ++i) {
  847. ints.push(iv.getInt32());
  848. }
  849. iv = ints;
  850. }
  851. return iv;
  852. }
  853. function inc32(block) {
  854. // increment last 32 bits of block only
  855. block[block.length - 1] = (block[block.length - 1] + 1) & 0xFFFFFFFF;
  856. }
  857. function from64To32(num) {
  858. // convert 64-bit number to two BE Int32s
  859. return [(num / 0x100000000) | 0, num & 0xFFFFFFFF];
  860. }