You are viewing a plain text version of this content. The canonical link for it is here.
Posted to common-commits@hadoop.apache.org by aa...@apache.org on 2015/08/14 18:13:50 UTC
[02/18] hadoop git commit: HADOOP-11343. Overflow is not properly
handled in caclulating final iv for AES CTR. Contributed by Jerry Chen.
HADOOP-11343. Overflow is not properly handled in caclulating final iv for AES CTR. Contributed by Jerry Chen.
(cherry picked from commit 0707e4eca906552c960e3b8c4e20d9913145eca6)
(cherry picked from commit dabdd2d746d1e1194c124c5c7fe73fcc025e78d2)
Project: http://git-wip-us.apache.org/repos/asf/hadoop/repo
Commit: http://git-wip-us.apache.org/repos/asf/hadoop/commit/6245beaa
Tree: http://git-wip-us.apache.org/repos/asf/hadoop/tree/6245beaa
Diff: http://git-wip-us.apache.org/repos/asf/hadoop/diff/6245beaa
Branch: refs/heads/ajisakaa/common-merge
Commit: 6245beaa6afef550595c00415404e6254a55e18e
Parents: ee8a6da
Author: Andrew Wang <wa...@apache.org>
Authored: Fri Dec 5 18:20:19 2014 -0800
Committer: Akira Ajisaka <aa...@apache.org>
Committed: Fri Aug 14 00:27:55 2015 +0900
----------------------------------------------------------------------
hadoop-common-project/hadoop-common/CHANGES.txt | 3 +
.../apache/hadoop/crypto/AesCtrCryptoCodec.java | 27 ++++-----
.../apache/hadoop/crypto/TestCryptoCodec.java | 64 ++++++++++++++++++++
3 files changed, 79 insertions(+), 15 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/hadoop/blob/6245beaa/hadoop-common-project/hadoop-common/CHANGES.txt
----------------------------------------------------------------------
diff --git a/hadoop-common-project/hadoop-common/CHANGES.txt b/hadoop-common-project/hadoop-common/CHANGES.txt
index 104aee2..af406b6 100644
--- a/hadoop-common-project/hadoop-common/CHANGES.txt
+++ b/hadoop-common-project/hadoop-common/CHANGES.txt
@@ -19,6 +19,9 @@ Release 2.6.1 - UNRELEASED
HADOOP-11333. Fix deadlock in DomainSocketWatcher when the notification
pipe is full (zhaoyunjiong via cmccabe)
+ HADOOP-11343. Overflow is not properly handled in caclulating final iv for
+ AES CTR. (Jerry Chen via wang)
+
Release 2.6.0 - 2014-11-18
INCOMPATIBLE CHANGES
http://git-wip-us.apache.org/repos/asf/hadoop/blob/6245beaa/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/AesCtrCryptoCodec.java
----------------------------------------------------------------------
diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/AesCtrCryptoCodec.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/AesCtrCryptoCodec.java
index 8f8bc66..5e286b9 100644
--- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/AesCtrCryptoCodec.java
+++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/AesCtrCryptoCodec.java
@@ -33,7 +33,6 @@ public abstract class AesCtrCryptoCodec extends CryptoCodec {
* @see http://en.wikipedia.org/wiki/Advanced_Encryption_Standard
*/
private static final int AES_BLOCK_SIZE = SUITE.getAlgorithmBlockSize();
- private static final int CTR_OFFSET = 8;
@Override
public CipherSuite getCipherSuite() {
@@ -48,20 +47,18 @@ public abstract class AesCtrCryptoCodec extends CryptoCodec {
public void calculateIV(byte[] initIV, long counter, byte[] IV) {
Preconditions.checkArgument(initIV.length == AES_BLOCK_SIZE);
Preconditions.checkArgument(IV.length == AES_BLOCK_SIZE);
-
- System.arraycopy(initIV, 0, IV, 0, CTR_OFFSET);
- long l = 0;
- for (int i = 0; i < 8; i++) {
- l = ((l << 8) | (initIV[CTR_OFFSET + i] & 0xff));
+
+ int i = IV.length; // IV length
+ int j = 0; // counter bytes index
+ int sum = 0;
+ while (i-- > 0) {
+ // (sum >>> Byte.SIZE) is the carry for addition
+ sum = (initIV[i] & 0xff) + (sum >>> Byte.SIZE);
+ if (j++ < 8) { // Big-endian, and long is 8 bytes length
+ sum += (byte) counter & 0xff;
+ counter >>>= 8;
+ }
+ IV[i] = (byte) sum;
}
- l += counter;
- IV[CTR_OFFSET + 0] = (byte) (l >>> 56);
- IV[CTR_OFFSET + 1] = (byte) (l >>> 48);
- IV[CTR_OFFSET + 2] = (byte) (l >>> 40);
- IV[CTR_OFFSET + 3] = (byte) (l >>> 32);
- IV[CTR_OFFSET + 4] = (byte) (l >>> 24);
- IV[CTR_OFFSET + 5] = (byte) (l >>> 16);
- IV[CTR_OFFSET + 6] = (byte) (l >>> 8);
- IV[CTR_OFFSET + 7] = (byte) (l);
}
}
http://git-wip-us.apache.org/repos/asf/hadoop/blob/6245beaa/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/crypto/TestCryptoCodec.java
----------------------------------------------------------------------
diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/crypto/TestCryptoCodec.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/crypto/TestCryptoCodec.java
index 79987ce..08231f9 100644
--- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/crypto/TestCryptoCodec.java
+++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/crypto/TestCryptoCodec.java
@@ -23,7 +23,9 @@ import static org.junit.Assert.assertTrue;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.IOException;
+import java.math.BigInteger;
import java.security.GeneralSecurityException;
+import java.security.SecureRandom;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@@ -41,6 +43,8 @@ import org.junit.Assert;
import org.junit.Assume;
import org.junit.Test;
+import com.google.common.primitives.Longs;
+
public class TestCryptoCodec {
private static final Log LOG= LogFactory.getLog(TestCryptoCodec.class);
private static final byte[] key = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
@@ -230,4 +234,64 @@ public class TestCryptoCodec {
Assert.assertEquals(len, rand1.length);
Assert.assertFalse(Arrays.equals(rand, rand1));
}
+
+ /**
+ * Regression test for IV calculation, see HADOOP-11343
+ */
+ @Test(timeout=120000)
+ public void testCalculateIV() throws Exception {
+ JceAesCtrCryptoCodec codec = new JceAesCtrCryptoCodec();
+ codec.setConf(conf);
+
+ SecureRandom sr = new SecureRandom();
+ byte[] initIV = new byte[16];
+ byte[] IV = new byte[16];
+
+ long iterations = 1000;
+ long counter = 10000;
+
+ // Overflow test, IV: 00 00 00 00 00 00 00 00 ff ff ff ff ff ff ff ff
+ for(int i = 0; i < 8; i++) {
+ initIV[8 + i] = (byte)0xff;
+ }
+
+ for(long j = 0; j < counter; j++) {
+ assertIVCalculation(codec, initIV, j, IV);
+ }
+
+ // Random IV and counter sequence test
+ for(long i = 0; i < iterations; i++) {
+ sr.nextBytes(initIV);
+
+ for(long j = 0; j < counter; j++) {
+ assertIVCalculation(codec, initIV, j, IV);
+ }
+ }
+
+ // Random IV and random counter test
+ for(long i = 0; i < iterations; i++) {
+ sr.nextBytes(initIV);
+
+ for(long j = 0; j < counter; j++) {
+ long c = sr.nextLong();
+ assertIVCalculation(codec, initIV, c, IV);
+ }
+ }
+ }
+
+ private void assertIVCalculation(CryptoCodec codec, byte[] initIV,
+ long counter, byte[] IV) {
+ codec.calculateIV(initIV, counter, IV);
+
+ BigInteger iv = new BigInteger(1, IV);
+ BigInteger ref = calculateRef(initIV, counter);
+
+ assertTrue("Calculated IV don't match with the reference", iv.equals(ref));
+ }
+
+ private static BigInteger calculateRef(byte[] initIV, long counter) {
+ byte[] cb = Longs.toByteArray(counter);
+ BigInteger bi = new BigInteger(1, initIV);
+ return bi.add(new BigInteger(1, cb));
+ }
}