changeset 9956:0dfd910e9753

8236191: Enhance OID processing Reviewed-by: jnimeh, weijun, ahgross, rhalade
author xuelei
date Fri, 10 Apr 2020 11:46:17 +0000
parents 9d38e2747017
children cf4f065c885d
files src/share/classes/sun/security/util/ObjectIdentifier.java
diffstat 1 files changed, 54 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/sun/security/util/ObjectIdentifier.java	Thu Apr 16 10:57:51 2020 -0400
+++ b/src/share/classes/sun/security/util/ObjectIdentifier.java	Fri Apr 10 11:46:17 2020 +0000
@@ -53,6 +53,26 @@
 final public
 class ObjectIdentifier implements Serializable
 {
+    /*
+     * The maximum encoded OID length, excluding the ASN.1 encoding tag and
+     * length.
+     *
+     * In theory, there is no maximum size for OIDs.  However, there are some
+     * limitation in practice.
+     *
+     * RFC 5280 mandates support for OIDs that have arc elements with values
+     * that are less than 2^28 (that is, they MUST be between 0 and
+     * 268,435,455, inclusive), and implementations MUST be able to handle
+     * OIDs with up to 20 elements (inclusive).  Per RFC 5280, an encoded
+     * OID should be less than 80 bytes for safe interoperability.
+     *
+     * This class could be used for protocols other than X.509 certificates.
+     * To be safe, a relatively large but still reasonable value is chosen
+     * as the restriction in JDK.
+     */
+    private static final int MAXIMUM_OID_SIZE = 4096;    // 2^12
+
+
     /**
      * We use the DER value (no tag, no length) as the internal format
      * @serial
@@ -115,7 +135,13 @@
             if (componentLen > comp.length) {
                 componentLen = comp.length;
             }
+
+            // Check the estimated size before it is too later.
+            checkOidSize(componentLen);
+
             init(comp, componentLen);
+        } else {
+            checkOidSize(encoding.length);
         }
     }
 
@@ -198,6 +224,8 @@
                 }
                 start = end + 1;
                 count++;
+
+                checkOidSize(pos);
             } while (end != -1);
 
             checkCount(count);
@@ -260,11 +288,13 @@
                 );
 
         int len = in.getDefiniteLength();
+        checkOidSize(len);
         if (len > in.available()) {
-            throw new IOException("ObjectIdentifier() -- length exceeds" +
+            throw new IOException("ObjectIdentifier length exceeds " +
                     "data available.  Length: " + len + ", Available: " +
                     in.available());
         }
+
         encoding = new byte[len];
         in.getBytes(encoding);
         check(encoding);
@@ -278,26 +308,32 @@
     ObjectIdentifier (DerInputBuffer buf) throws IOException
     {
         DerInputStream in = new DerInputStream(buf);
-        encoding = new byte[in.available()];
+        int len = in.available();
+        checkOidSize(len);
+
+        encoding = new byte[len];
         in.getBytes(encoding);
         check(encoding);
     }
 
-    private void init(int[] components, int length) {
+    private void init(int[] components, int length) throws IOException {
         int pos = 0;
-        byte[] tmp = new byte[length*5+1];  // +1 for empty input
+        byte[] tmp = new byte[length * 5 + 1];  // +1 for empty input
 
-        if (components[1] < Integer.MAX_VALUE - components[0]*40)
-            pos += pack7Oid(components[0]*40+components[1], tmp, pos);
-        else {
+        if (components[1] < Integer.MAX_VALUE - components[0] * 40) {
+            pos += pack7Oid(components[0] * 40 + components[1], tmp, pos);
+        } else {
             BigInteger big = BigInteger.valueOf(components[1]);
-            big = big.add(BigInteger.valueOf(components[0]*40));
+            big = big.add(BigInteger.valueOf(components[0] * 40));
             pos += pack7Oid(big, tmp, pos);
         }
 
-        for (int i=2; i<length; i++) {
+        for (int i = 2; i < length; i++) {
             pos += pack7Oid(components[i], tmp, pos);
+
+            checkOidSize(pos);
         }
+
         encoding = new byte[pos];
         System.arraycopy(tmp, 0, encoding, 0, pos);
     }
@@ -669,4 +705,13 @@
                     "oid component #" + (i+1) + " must be non-negative ");
         }
     }
+
+    private static void checkOidSize(int oidLength) throws IOException {
+        if (oidLength > MAXIMUM_OID_SIZE) {
+            throw new IOException(
+                    "ObjectIdentifier encoded length exceeds " +
+                    "the restriction in JDK (OId length(>=): " + oidLength +
+                    ", Restriction: " + MAXIMUM_OID_SIZE + ")");
+        }
+    }
 }