From 58cd3349db447a392c8b5c34352460fe217fad19 Mon Sep 17 00:00:00 2001
From: Rob Wu <rob@robwu.nl>
Date: Fri, 8 Aug 2014 12:36:29 +0200
Subject: [PATCH] AES cipher: make padding optional

Fixes #5152
---
 src/core/crypto.js | 30 +++++++++++++++++++++++++-----
 1 file changed, 25 insertions(+), 5 deletions(-)

diff --git a/src/core/crypto.js b/src/core/crypto.js
index 92cb1b908..1f13239fa 100644
--- a/src/core/crypto.js
+++ b/src/core/crypto.js
@@ -978,8 +978,18 @@ var AES128Cipher = (function AES128CipherClosure() {
     if (finalize) {
       // undo a padding that is described in RFC 2898
       var lastBlock = result[result.length - 1];
-      outputLength -= lastBlock[15];
-      result[result.length - 1] = lastBlock.subarray(0, 16 - lastBlock[15]);
+      var psLen = lastBlock[15];
+      if (psLen <= 16) {
+        for (i = 15, ii = 16 - psLen; i >= ii; --i) {
+          if (lastBlock[i] !== psLen) {
+            // Invalid padding, assume that the block has no padding.
+            psLen = 0;
+            break;
+          }
+        }
+        outputLength -= psLen;
+        result[result.length - 1] = lastBlock.subarray(0, 16 - psLen);
+      }
     }
     var output = new Uint8Array(outputLength);
     for (i = 0, j = 0, ii = result.length; i < ii; ++i, j += 16) {
@@ -1394,7 +1404,7 @@ var AES256Cipher = (function AES256CipherClosure() {
       if (bufferLength < 16) {
         continue;
       }
-      // buffer is full, encrypting
+      // buffer is full, decrypting
       var plain = decrypt256(buffer, this.key);
       // xor-ing the IV vector to get plain text
       for (j = 0; j < 16; ++j) {
@@ -1417,8 +1427,18 @@ var AES256Cipher = (function AES256CipherClosure() {
     if (finalize) {
       // undo a padding that is described in RFC 2898
       var lastBlock = result[result.length - 1];
-      outputLength -= lastBlock[15];
-      result[result.length - 1] = lastBlock.subarray(0, 16 - lastBlock[15]);
+      var psLen = lastBlock[15];
+      if (psLen <= 16) {
+        for (i = 15, ii = 16 - psLen; i >= ii; --i) {
+          if (lastBlock[i] !== psLen) {
+            // Invalid padding, assume that the block has no padding.
+            psLen = 0;
+            break;
+          }
+        }
+        outputLength -= psLen;
+        result[result.length - 1] = lastBlock.subarray(0, 16 - psLen);
+      }
     }
     var output = new Uint8Array(outputLength);
     for (i = 0, j = 0, ii = result.length; i < ii; ++i, j += 16) {