From e0a6b9629994380c6c38f691efd7b222274edc41 Mon Sep 17 00:00:00 2001 From: xuelei Date: Fri, 10 Apr 2020 11:46:17 +0000 Subject: [PATCH] 8236191: Enhance OID processing Reviewed-by: jnimeh, weijun, ahgross, rhalade --- .../sun/security/util/ObjectIdentifier.java | 63 ++++++++++++++++--- 1 file changed, 54 insertions(+), 9 deletions(-) diff --git a/src/java.base/share/classes/sun/security/util/ObjectIdentifier.java b/src/java.base/share/classes/sun/security/util/ObjectIdentifier.java index 514b993849..00ab476823 100644 --- a/src/java.base/share/classes/sun/security/util/ObjectIdentifier.java +++ b/src/java.base/share/classes/sun/security/util/ObjectIdentifier.java @@ -53,6 +53,26 @@ import java.util.Arrays; public final 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 @@ class ObjectIdentifier implements Serializable 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 @@ class ObjectIdentifier implements Serializable } start = end + 1; count++; + + checkOidSize(pos); } while (end != -1); checkCount(count); @@ -260,11 +288,13 @@ class ObjectIdentifier implements Serializable ); 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 @@ class ObjectIdentifier implements Serializable 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 MAXIMUM_OID_SIZE) { + throw new IOException( + "ObjectIdentifier encoded length exceeds " + + "the restriction in JDK (OId length(>=): " + oidLength + + ", Restriction: " + MAXIMUM_OID_SIZE + ")"); + } + } } -- GitLab