summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKenny Root <kroot@google.com>2012-05-10 10:21:06 -0700
committerKenny Root <kroot@google.com>2012-05-10 11:48:21 -0700
commit103d53005e7a3c2735f4ac76fa9b795a7e7e39d7 (patch)
treeda5b4a423467f932654ca2db1494bd9e34210f58
parenta25079e6bafcfd77135a852f0e838738d80606ef (diff)
downloadframeworks_base-103d53005e7a3c2735f4ac76fa9b795a7e7e39d7.zip
frameworks_base-103d53005e7a3c2735f4ac76fa9b795a7e7e39d7.tar.gz
frameworks_base-103d53005e7a3c2735f4ac76fa9b795a7e7e39d7.tar.bz2
Use long instead of int for file offsets
Use long instead of int so we don't run into a 2GB file limit. Fix possible overflows in offset and length. Change-Id: Idb3a34f5600f9c2372b9c89256f21757049fa43b
-rw-r--r--core/java/android/content/pm/ContainerEncryptionParams.java28
-rw-r--r--core/java/android/content/pm/LimitedLengthInputStream.java26
-rw-r--r--core/tests/coretests/src/android/content/pm/LimitedLengthInputStreamTest.java12
-rw-r--r--packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java25
4 files changed, 63 insertions, 28 deletions
diff --git a/core/java/android/content/pm/ContainerEncryptionParams.java b/core/java/android/content/pm/ContainerEncryptionParams.java
index 5b1440d..88112a7 100644
--- a/core/java/android/content/pm/ContainerEncryptionParams.java
+++ b/core/java/android/content/pm/ContainerEncryptionParams.java
@@ -70,16 +70,16 @@ public class ContainerEncryptionParams implements Parcelable {
private final byte[] mMacTag;
/** Offset into file where authenticated (e.g., MAC protected) data begins. */
- private final int mAuthenticatedDataStart;
+ private final long mAuthenticatedDataStart;
/** Offset into file where encrypted data begins. */
- private final int mEncryptedDataStart;
+ private final long mEncryptedDataStart;
/**
* Offset into file for the end of encrypted data (and, by extension,
* authenticated data) in file.
*/
- private final int mDataEnd;
+ private final long mDataEnd;
public ContainerEncryptionParams(String encryptionAlgorithm,
AlgorithmParameterSpec encryptionSpec, SecretKey encryptionKey)
@@ -99,6 +99,8 @@ public class ContainerEncryptionParams implements Parcelable {
* @param macAlgorithm MAC algorithm to use; format matches JCE
* @param macSpec algorithm parameters specification, may be {@code null}
* @param macKey key used for authentication (i.e., for the MAC tag)
+ * @param macTag message authentication code (MAC) tag for the authenticated
+ * data
* @param authenticatedDataStart offset of start of authenticated data in
* stream
* @param encryptedDataStart offset of start of encrypted data in stream
@@ -109,7 +111,7 @@ public class ContainerEncryptionParams implements Parcelable {
public ContainerEncryptionParams(String encryptionAlgorithm,
AlgorithmParameterSpec encryptionSpec, SecretKey encryptionKey, String macAlgorithm,
AlgorithmParameterSpec macSpec, SecretKey macKey, byte[] macTag,
- int authenticatedDataStart, int encryptedDataStart, int dataEnd)
+ long authenticatedDataStart, long encryptedDataStart, long dataEnd)
throws InvalidAlgorithmParameterException {
if (TextUtils.isEmpty(encryptionAlgorithm)) {
throw new NullPointerException("algorithm == null");
@@ -172,15 +174,15 @@ public class ContainerEncryptionParams implements Parcelable {
return mMacTag;
}
- public int getAuthenticatedDataStart() {
+ public long getAuthenticatedDataStart() {
return mAuthenticatedDataStart;
}
- public int getEncryptedDataStart() {
+ public long getEncryptedDataStart() {
return mEncryptedDataStart;
}
- public int getDataEnd() {
+ public long getDataEnd() {
return mDataEnd;
}
@@ -315,9 +317,9 @@ public class ContainerEncryptionParams implements Parcelable {
dest.writeByteArray(mMacTag);
- dest.writeInt(mAuthenticatedDataStart);
- dest.writeInt(mEncryptedDataStart);
- dest.writeInt(mDataEnd);
+ dest.writeLong(mAuthenticatedDataStart);
+ dest.writeLong(mEncryptedDataStart);
+ dest.writeLong(mDataEnd);
}
private ContainerEncryptionParams(Parcel source) throws InvalidAlgorithmParameterException {
@@ -333,9 +335,9 @@ public class ContainerEncryptionParams implements Parcelable {
mMacTag = source.createByteArray();
- mAuthenticatedDataStart = source.readInt();
- mEncryptedDataStart = source.readInt();
- mDataEnd = source.readInt();
+ mAuthenticatedDataStart = source.readLong();
+ mEncryptedDataStart = source.readLong();
+ mDataEnd = source.readLong();
switch (encParamType) {
case ENC_PARAMS_IV_PARAMETERS:
diff --git a/core/java/android/content/pm/LimitedLengthInputStream.java b/core/java/android/content/pm/LimitedLengthInputStream.java
index 25a490f..e787277 100644
--- a/core/java/android/content/pm/LimitedLengthInputStream.java
+++ b/core/java/android/content/pm/LimitedLengthInputStream.java
@@ -3,6 +3,7 @@ package android.content.pm;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.util.Arrays;
/**
* A class that limits the amount of data that is read from an InputStream. When
@@ -15,20 +16,20 @@ public class LimitedLengthInputStream extends FilterInputStream {
/**
* The end of the stream where we don't want to allow more data to be read.
*/
- private final int mEnd;
+ private final long mEnd;
/**
* Current offset in the stream.
*/
- private int mOffset;
+ private long mOffset;
/**
* @param in underlying stream to wrap
* @param offset offset into stream where data starts
* @param length length of data at offset
- * @throws IOException if an error occured with the underlying stream
+ * @throws IOException if an error occurred with the underlying stream
*/
- public LimitedLengthInputStream(InputStream in, int offset, int length) throws IOException {
+ public LimitedLengthInputStream(InputStream in, long offset, long length) throws IOException {
super(in);
if (in == null) {
@@ -36,11 +37,15 @@ public class LimitedLengthInputStream extends FilterInputStream {
}
if (offset < 0) {
- throw new IOException("offset == " + offset);
+ throw new IOException("offset < 0");
}
if (length < 0) {
- throw new IOException("length must be non-negative; is " + length);
+ throw new IOException("length < 0");
+ }
+
+ if (length > Long.MAX_VALUE - offset) {
+ throw new IOException("offset + length > Long.MAX_VALUE");
}
mEnd = offset + length;
@@ -65,8 +70,15 @@ public class LimitedLengthInputStream extends FilterInputStream {
return -1;
}
+ final int arrayLength = buffer.length;
+ Arrays.checkOffsetAndCount(arrayLength, offset, byteCount);
+
+ if (mOffset > Long.MAX_VALUE - byteCount) {
+ throw new IOException("offset out of bounds: " + mOffset + " + " + byteCount);
+ }
+
if (mOffset + byteCount > mEnd) {
- byteCount = mEnd - mOffset;
+ byteCount = (int) (mEnd - mOffset);
}
final int numRead = super.read(buffer, offset, byteCount);
diff --git a/core/tests/coretests/src/android/content/pm/LimitedLengthInputStreamTest.java b/core/tests/coretests/src/android/content/pm/LimitedLengthInputStreamTest.java
index 0a0152b..1f762fd 100644
--- a/core/tests/coretests/src/android/content/pm/LimitedLengthInputStreamTest.java
+++ b/core/tests/coretests/src/android/content/pm/LimitedLengthInputStreamTest.java
@@ -66,6 +66,17 @@ public class LimitedLengthInputStreamTest extends AndroidTestCase {
}
}
+ @MediumTest
+ public void testConstructor_OffsetLengthOverflow_Fail() throws Exception {
+ try {
+ InputStream is = new LimitedLengthInputStream(mTestStream1, Long.MAX_VALUE - 1,
+ Long.MAX_VALUE - 1);
+ fail("Should fail when offset + length is > Long.MAX_VALUE");
+ } catch (IOException e) {
+ // success
+ }
+ }
+
private void checkReadBytesWithOffsetAndLength_WithString1(int offset, int length)
throws Exception {
byte[] temp = new byte[TEST_STRING1.length];
@@ -182,5 +193,4 @@ public class LimitedLengthInputStreamTest extends AndroidTestCase {
public void testSingleByteRead_NonZeroOffset_FullLength_Success() throws Exception {
checkSingleByteRead_WithString1(3, TEST_STRING1.length - 3);
}
-
}
diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
index 17e5f4e..3b87b96 100644
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
@@ -473,6 +473,8 @@ public class DefaultContainerService extends IntentService {
}
private static class ApkContainer {
+ private static final int MAX_AUTHENTICATED_DATA_SIZE = 16384;
+
private final InputStream mInStream;
private MacAuthenticatedInputStream mAuthenticatedStream;
@@ -540,26 +542,35 @@ public class DefaultContainerService extends IntentService {
throw new IOException(e);
}
- final int encStart = encryptionParams.getEncryptedDataStart();
- final int end = encryptionParams.getDataEnd();
+ final long encStart = encryptionParams.getEncryptedDataStart();
+ final long end = encryptionParams.getDataEnd();
if (end < encStart) {
throw new IOException("end <= encStart");
}
final Mac mac = getMacInstance(encryptionParams);
if (mac != null) {
- final int macStart = encryptionParams.getAuthenticatedDataStart();
+ final long macStart = encryptionParams.getAuthenticatedDataStart();
+ if (macStart >= Integer.MAX_VALUE) {
+ throw new IOException("macStart >= Integer.MAX_VALUE");
+ }
- final int furtherOffset;
+ final long furtherOffset;
if (macStart >= 0 && encStart >= 0 && macStart < encStart) {
/*
* If there is authenticated data at the beginning, read
* that into our MAC first.
*/
- final int authenticatedLength = encStart - macStart;
- final byte[] authenticatedData = new byte[authenticatedLength];
+ final long authenticatedLengthLong = encStart - macStart;
+ if (authenticatedLengthLong > MAX_AUTHENTICATED_DATA_SIZE) {
+ throw new IOException("authenticated data is too long");
+ }
+ final int authenticatedLength = (int) authenticatedLengthLong;
+
+ final byte[] authenticatedData = new byte[(int) authenticatedLength];
- Streams.readFully(inStream, authenticatedData, macStart, authenticatedLength);
+ Streams.readFully(inStream, authenticatedData, (int) macStart,
+ authenticatedLength);
mac.update(authenticatedData, 0, authenticatedLength);
furtherOffset = 0;