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