ocb2.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. /** @fileOverview OCB 2.0 implementation
  2. *
  3. * @author Emily Stark
  4. * @author Mike Hamburg
  5. * @author Dan Boneh
  6. */
  7. /** @namespace
  8. * Phil Rogaway's Offset CodeBook mode, version 2.0.
  9. * May be covered by US and international patents.
  10. *
  11. * @author Emily Stark
  12. * @author Mike Hamburg
  13. * @author Dan Boneh
  14. */
  15. sjcl.mode.ocb2 = {
  16. /** The name of the mode.
  17. * @constant
  18. */
  19. name: "ocb2",
  20. /** Encrypt in OCB mode, version 2.0.
  21. * @param {Object} prp The block cipher. It must have a block size of 16 bytes.
  22. * @param {bitArray} plaintext The plaintext data.
  23. * @param {bitArray} iv The initialization value.
  24. * @param {bitArray} [adata=[]] The authenticated data.
  25. * @param {Number} [tlen=64] the desired tag length, in bits.
  26. * @param [false] premac 1 if the authentication data is pre-macced with PMAC.
  27. * @return The encrypted data, an array of bytes.
  28. * @throws {sjcl.exception.invalid} if the IV isn't exactly 128 bits.
  29. */
  30. encrypt: function(prp, plaintext, iv, adata, tlen, premac) {
  31. if (sjcl.bitArray.bitLength(iv) !== 128) {
  32. throw new sjcl.exception.invalid("ocb iv must be 128 bits");
  33. }
  34. var i,
  35. times2 = sjcl.mode.ocb2._times2,
  36. w = sjcl.bitArray,
  37. xor = w._xor4,
  38. checksum = [0,0,0,0],
  39. delta = times2(prp.encrypt(iv)),
  40. bi, bl,
  41. output = [],
  42. pad;
  43. adata = adata || [];
  44. tlen = tlen || 64;
  45. for (i=0; i+4 < plaintext.length; i+=4) {
  46. /* Encrypt a non-final block */
  47. bi = plaintext.slice(i,i+4);
  48. checksum = xor(checksum, bi);
  49. bi = xor(delta,prp.encrypt(xor(delta, bi)));
  50. output.splice(i,0,bi[0],bi[1],bi[2],bi[3]);
  51. delta = times2(delta);
  52. }
  53. /* Chop out the final block */
  54. bi = plaintext.slice(i);
  55. bl = w.bitLength(bi);
  56. pad = prp.encrypt(xor(delta,[0,0,0,bl]));
  57. bi = w.clamp(xor(bi,pad), bl);
  58. /* Checksum the final block, and finalize the checksum */
  59. checksum = xor(checksum,xor(bi,pad));
  60. checksum = prp.encrypt(xor(checksum,xor(delta,times2(delta))));
  61. /* MAC the header */
  62. if (adata.length) {
  63. checksum = xor(checksum, premac ? adata : sjcl.mode.ocb2.pmac(prp, adata));
  64. }
  65. return output.concat(w.concat(bi, w.clamp(checksum, tlen)));
  66. },
  67. /** Decrypt in OCB mode.
  68. * @param {Object} prp The block cipher. It must have a block size of 16 bytes.
  69. * @param {bitArray} ciphertext The ciphertext data.
  70. * @param {bitArray} iv The initialization value.
  71. * @param {bitArray} [adata=[]] The authenticated data.
  72. * @param {Number} [tlen=64] the desired tag length, in bits.
  73. * @param {boolean} [premac=false] true if the authentication data is pre-macced with PMAC.
  74. * @return The decrypted data, an array of bytes.
  75. * @throws {sjcl.exception.invalid} if the IV isn't exactly 128 bits.
  76. * @throws {sjcl.exception.corrupt} if if the message is corrupt.
  77. */
  78. decrypt: function(prp, ciphertext, iv, adata, tlen, premac) {
  79. if (sjcl.bitArray.bitLength(iv) !== 128) {
  80. throw new sjcl.exception.invalid("ocb iv must be 128 bits");
  81. }
  82. tlen = tlen || 64;
  83. var i,
  84. times2 = sjcl.mode.ocb2._times2,
  85. w = sjcl.bitArray,
  86. xor = w._xor4,
  87. checksum = [0,0,0,0],
  88. delta = times2(prp.encrypt(iv)),
  89. bi, bl,
  90. len = sjcl.bitArray.bitLength(ciphertext) - tlen,
  91. output = [],
  92. pad;
  93. adata = adata || [];
  94. for (i=0; i+4 < len/32; i+=4) {
  95. /* Decrypt a non-final block */
  96. bi = xor(delta, prp.decrypt(xor(delta, ciphertext.slice(i,i+4))));
  97. checksum = xor(checksum, bi);
  98. output.splice(i,0,bi[0],bi[1],bi[2],bi[3]);
  99. delta = times2(delta);
  100. }
  101. /* Chop out and decrypt the final block */
  102. bl = len-i*32;
  103. pad = prp.encrypt(xor(delta,[0,0,0,bl]));
  104. bi = xor(pad, w.clamp(ciphertext.slice(i),bl));
  105. /* Checksum the final block, and finalize the checksum */
  106. checksum = xor(checksum, bi);
  107. checksum = prp.encrypt(xor(checksum, xor(delta, times2(delta))));
  108. /* MAC the header */
  109. if (adata.length) {
  110. checksum = xor(checksum, premac ? adata : sjcl.mode.ocb2.pmac(prp, adata));
  111. }
  112. if (!w.equal(w.clamp(checksum, tlen), w.bitSlice(ciphertext, len))) {
  113. throw new sjcl.exception.corrupt("ocb: tag doesn't match");
  114. }
  115. return output.concat(w.clamp(bi,bl));
  116. },
  117. /** PMAC authentication for OCB associated data.
  118. * @param {Object} prp The block cipher. It must have a block size of 16 bytes.
  119. * @param {bitArray} adata The authenticated data.
  120. */
  121. pmac: function(prp, adata) {
  122. var i,
  123. times2 = sjcl.mode.ocb2._times2,
  124. w = sjcl.bitArray,
  125. xor = w._xor4,
  126. checksum = [0,0,0,0],
  127. delta = prp.encrypt([0,0,0,0]),
  128. bi;
  129. delta = xor(delta,times2(times2(delta)));
  130. for (i=0; i+4<adata.length; i+=4) {
  131. delta = times2(delta);
  132. checksum = xor(checksum, prp.encrypt(xor(delta, adata.slice(i,i+4))));
  133. }
  134. bi = adata.slice(i);
  135. if (w.bitLength(bi) < 128) {
  136. delta = xor(delta,times2(delta));
  137. bi = w.concat(bi,[0x80000000|0]);
  138. }
  139. checksum = xor(checksum, bi);
  140. return prp.encrypt(xor(times2(xor(delta,times2(delta))), checksum));
  141. },
  142. /** Double a block of words, OCB style.
  143. * @private
  144. */
  145. _times2: function(x) {
  146. return [x[0]<<1 ^ x[1]>>>31,
  147. x[1]<<1 ^ x[2]>>>31,
  148. x[2]<<1 ^ x[3]>>>31,
  149. x[3]<<1 ^ (x[0]>>>31)*0x87];
  150. }
  151. };