sun.security.util: check lengths in DER encoding are non-negative
Port of:
http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/rev/4581ed6af636
This completes the upgrade to jdk8u60 of the classes
DerIndefLenConverter and DerInputStream.
(cherry picked from commit e27611b2c8a2c8cb413ff2f5f0c9cbae288aa835)
Bug: 30703445
Bug: 29631070
Change-Id: I052a1ea9959f9623973bf949a96923b603e17774
(cherry picked from commit 4c3078609421ce333468dd415d62980e68d35c9e)
diff --git a/luni/src/test/java/libcore/javax/security/auth/x500/X500PrincipalTest.java b/luni/src/test/java/libcore/javax/security/auth/x500/X500PrincipalTest.java
index 4f5d658..5471b1f 100644
--- a/luni/src/test/java/libcore/javax/security/auth/x500/X500PrincipalTest.java
+++ b/luni/src/test/java/libcore/javax/security/auth/x500/X500PrincipalTest.java
@@ -120,6 +120,30 @@
expectExceptionInDNConstructor("l=\\g0");
}
+ public void testNegativeLen() {
+ try {
+ X500Principal p = new X500Principal(new byte[]{
+ 0x30, // DerValue.tag_Sequence read in DerValue#getSequence
+ 9, // Length of the vector. read in readVector.
+ // DerInputStream.getLength will just return this as 10 & 0x80 == 0
+ -1, // Tag of the first value in the sequencevalue. Convenient so that it
+ // doesn't hold DerIndefLenConverter.isEOC()
+ (byte) 0x80, // Encoding in indefinite form
+ -1, // Second tag to be read by DerIndefLenConverter
+ (byte) 0x84, // Second length byte to be read, 0x80 means long form, 4 bytes
+ (byte) 0xff, // Length to be read by DerIndefLenConverter, -6, will move the
+ // buffer position to the second tag
+ (byte) 0xff,
+ (byte) 0xff,
+ (byte) -6,
+ 0, // Needed as otherwise it's detected that there's nothing after
+ // the length
+ });
+ fail("expected IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
private void expectExceptionInDNConstructor(String dn) {
try {
X500Principal principal = new X500Principal(dn);
diff --git a/ojluni/src/main/java/sun/security/util/DerIndefLenConverter.java b/ojluni/src/main/java/sun/security/util/DerIndefLenConverter.java
index 78d9e30..cbd5ecc 100755
--- a/ojluni/src/main/java/sun/security/util/DerIndefLenConverter.java
+++ b/ojluni/src/main/java/sun/security/util/DerIndefLenConverter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -156,12 +156,18 @@
}
if (isLongForm(lenByte)) {
lenByte &= LEN_MASK;
- if (lenByte > 4)
+ if (lenByte > 4) {
throw new IOException("Too much data");
- if ((dataSize - dataPos) < (lenByte + 1))
+ }
+ if ((dataSize - dataPos) < (lenByte + 1)) {
throw new IOException("Too little data");
- for (int i = 0; i < lenByte; i++)
+ }
+ for (int i = 0; i < lenByte; i++) {
curLen = (curLen << 8) + (data[dataPos++] & 0xff);
+ }
+ if (curLen < 0) {
+ throw new IOException("Invalid length bytes");
+ }
} else {
curLen = (lenByte & LEN_MASK);
}
@@ -188,10 +194,15 @@
}
if (isLongForm(lenByte)) {
lenByte &= LEN_MASK;
- for (int i = 0; i < lenByte; i++)
+ for (int i = 0; i < lenByte; i++) {
curLen = (curLen << 8) + (data[dataPos++] & 0xff);
- } else
+ }
+ if (curLen < 0) {
+ throw new IOException("Invalid length bytes");
+ }
+ } else {
curLen = (lenByte & LEN_MASK);
+ }
writeLength(curLen);
writeValue(curLen);
}
diff --git a/ojluni/src/main/java/sun/security/util/DerInputStream.java b/ojluni/src/main/java/sun/security/util/DerInputStream.java
index 8f51439..dae8afd 100755
--- a/ojluni/src/main/java/sun/security/util/DerInputStream.java
+++ b/ojluni/src/main/java/sun/security/util/DerInputStream.java
@@ -604,6 +604,10 @@
value <<= 8;
value += 0x0ff & in.read();
}
+ if (value < 0) {
+ throw new IOException("DerInputStream.getLength(): "
+ + "Invalid length bytes");
+ }
}
return value;
}