8157404: Unable to read certain PKCS12 keystores from SequenceInputStream
Reviewed-by: xuelei
This commit is contained in:
parent
460c22f03d
commit
e0f37c15e4
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2019, 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
|
||||
@ -26,7 +26,9 @@
|
||||
package sun.security.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* A package private utility class to convert indefinite length DER
|
||||
@ -143,6 +145,10 @@ class DerIndefLenConverter {
|
||||
/**
|
||||
* Parse the length and if it is an indefinite length then add
|
||||
* the current position to the <code>ndefsList</code> vector.
|
||||
*
|
||||
* @return the length of definite length data next, or -1 if there is
|
||||
* not enough bytes to determine it
|
||||
* @throws IOException if invalid data is read
|
||||
*/
|
||||
private int parseLength() throws IOException {
|
||||
int curLen = 0;
|
||||
@ -160,7 +166,7 @@ class DerIndefLenConverter {
|
||||
throw new IOException("Too much data");
|
||||
}
|
||||
if ((dataSize - dataPos) < (lenByte + 1)) {
|
||||
throw new IOException("Too little data");
|
||||
return -1;
|
||||
}
|
||||
for (int i = 0; i < lenByte; i++) {
|
||||
curLen = (curLen << 8) + (data[dataPos++] & 0xff);
|
||||
@ -314,10 +320,10 @@ class DerIndefLenConverter {
|
||||
* @param indefData the byte array holding the indefinite
|
||||
* length encoding.
|
||||
* @return the byte array containing the definite length
|
||||
* DER encoding.
|
||||
* DER encoding, or null if there is not enough data.
|
||||
* @exception IOException on parsing or re-writing errors.
|
||||
*/
|
||||
byte[] convert(byte[] indefData) throws IOException {
|
||||
byte[] convertBytes(byte[] indefData) throws IOException {
|
||||
data = indefData;
|
||||
dataPos=0; index=0;
|
||||
dataSize = data.length;
|
||||
@ -328,6 +334,9 @@ class DerIndefLenConverter {
|
||||
while (dataPos < dataSize) {
|
||||
parseTag();
|
||||
len = parseLength();
|
||||
if (len < 0) {
|
||||
return null;
|
||||
}
|
||||
parseValue(len);
|
||||
if (unresolved == 0) {
|
||||
unused = dataSize - dataPos;
|
||||
@ -337,7 +346,7 @@ class DerIndefLenConverter {
|
||||
}
|
||||
|
||||
if (unresolved != 0) {
|
||||
throw new IOException("not all indef len BER resolved");
|
||||
return null;
|
||||
}
|
||||
|
||||
newData = new byte[dataSize + numOfTotalLenBytes + unused];
|
||||
@ -354,4 +363,48 @@ class DerIndefLenConverter {
|
||||
|
||||
return newData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the input stream into a DER byte array. If an indef len BER is
|
||||
* not resolved this method will try to read more data until EOF is reached.
|
||||
* This may block.
|
||||
*
|
||||
* @param in the input stream with tag and lenByte already read
|
||||
* @param lenByte the length of the length field to remember
|
||||
* @param tag the tag to remember
|
||||
* @return a DER byte array
|
||||
* @throws IOException if not all indef len BER
|
||||
* can be resolved or another I/O error happens
|
||||
*/
|
||||
public static byte[] convertStream(InputStream in, byte lenByte, byte tag)
|
||||
throws IOException {
|
||||
int offset = 2; // for tag and length bytes
|
||||
int readLen = in.available();
|
||||
byte[] indefData = new byte[readLen + offset];
|
||||
indefData[0] = tag;
|
||||
indefData[1] = lenByte;
|
||||
while (true) {
|
||||
int bytesRead = in.readNBytes(indefData, offset, readLen);
|
||||
if (bytesRead != readLen) {
|
||||
readLen = bytesRead;
|
||||
indefData = Arrays.copyOf(indefData, offset + bytesRead);
|
||||
}
|
||||
DerIndefLenConverter derIn = new DerIndefLenConverter();
|
||||
byte[] result = derIn.convertBytes(indefData);
|
||||
if (result == null) {
|
||||
int next = in.read(); // This could block, but we need more
|
||||
if (next == -1) {
|
||||
throw new IOException("not all indef len BER resolved");
|
||||
}
|
||||
int more = in.available();
|
||||
// expand array to include next and more
|
||||
indefData = Arrays.copyOf(indefData, offset + readLen + 1 + more);
|
||||
indefData[offset + readLen] = (byte)next;
|
||||
offset = offset + readLen + 1;
|
||||
readLen = more;
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 2019, 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
|
||||
@ -27,11 +27,9 @@ package sun.security.util;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.EOFException;
|
||||
import java.util.Date;
|
||||
import java.util.Vector;
|
||||
import java.math.BigInteger;
|
||||
import java.io.DataInputStream;
|
||||
|
||||
/**
|
||||
* A DER input stream, used for parsing ASN.1 DER-encoded data such as
|
||||
@ -130,7 +128,12 @@ public class DerInputStream {
|
||||
System.arraycopy(data, offset, inData, 0, len);
|
||||
|
||||
DerIndefLenConverter derIn = new DerIndefLenConverter();
|
||||
buffer = new DerInputBuffer(derIn.convert(inData), allowBER);
|
||||
byte[] result = derIn.convertBytes(inData);
|
||||
if (result == null) {
|
||||
throw new IOException("not all indef len BER resolved");
|
||||
} else {
|
||||
buffer = new DerInputBuffer(result, allowBER);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
buffer = new DerInputBuffer(data, offset, len, allowBER);
|
||||
@ -389,16 +392,9 @@ public class DerInputStream {
|
||||
|
||||
if (len == -1) {
|
||||
// indefinite length encoding found
|
||||
int readLen = buffer.available();
|
||||
int offset = 2; // for tag and length bytes
|
||||
byte[] indefData = new byte[readLen + offset];
|
||||
indefData[0] = tag;
|
||||
indefData[1] = lenByte;
|
||||
DataInputStream dis = new DataInputStream(buffer);
|
||||
dis.readFully(indefData, offset, readLen);
|
||||
dis.close();
|
||||
DerIndefLenConverter derIn = new DerIndefLenConverter();
|
||||
buffer = new DerInputBuffer(derIn.convert(indefData), buffer.allowBER);
|
||||
buffer = new DerInputBuffer(
|
||||
DerIndefLenConverter.convertStream(buffer, lenByte, tag),
|
||||
buffer.allowBER);
|
||||
|
||||
if (tag != buffer.read())
|
||||
throw new IOException("Indefinite length encoding" +
|
||||
|
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 2019, 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
|
||||
@ -257,16 +257,9 @@ public class DerValue {
|
||||
length = DerInputStream.getLength(lenByte, in);
|
||||
if (length == -1) { // indefinite length encoding found
|
||||
DerInputBuffer inbuf = in.dup();
|
||||
int readLen = inbuf.available();
|
||||
int offset = 2; // for tag and length bytes
|
||||
byte[] indefData = new byte[readLen + offset];
|
||||
indefData[0] = tag;
|
||||
indefData[1] = lenByte;
|
||||
DataInputStream dis = new DataInputStream(inbuf);
|
||||
dis.readFully(indefData, offset, readLen);
|
||||
dis.close();
|
||||
DerIndefLenConverter derIn = new DerIndefLenConverter();
|
||||
inbuf = new DerInputBuffer(derIn.convert(indefData), in.allowBER);
|
||||
inbuf = new DerInputBuffer(
|
||||
DerIndefLenConverter.convertStream(inbuf, lenByte, tag),
|
||||
in.allowBER);
|
||||
if (tag != inbuf.read())
|
||||
throw new IOException
|
||||
("Indefinite length encoding not supported");
|
||||
@ -277,7 +270,7 @@ public class DerValue {
|
||||
// indefinite form is encoded by sending a length field with a
|
||||
// length of 0. - i.e. [1000|0000].
|
||||
// the object is ended by sending two zero bytes.
|
||||
in.skip(length + offset);
|
||||
in.skip(length + 2);
|
||||
} else {
|
||||
|
||||
buffer = in.dup();
|
||||
@ -389,16 +382,8 @@ public class DerValue {
|
||||
byte lenByte = (byte)in.read();
|
||||
length = DerInputStream.getLength(lenByte, in);
|
||||
if (length == -1) { // indefinite length encoding found
|
||||
int readLen = in.available();
|
||||
int offset = 2; // for tag and length bytes
|
||||
byte[] indefData = new byte[readLen + offset];
|
||||
indefData[0] = tag;
|
||||
indefData[1] = lenByte;
|
||||
DataInputStream dis = new DataInputStream(in);
|
||||
dis.readFully(indefData, offset, readLen);
|
||||
dis.close();
|
||||
DerIndefLenConverter derIn = new DerIndefLenConverter();
|
||||
in = new ByteArrayInputStream(derIn.convert(indefData));
|
||||
in = new ByteArrayInputStream(
|
||||
DerIndefLenConverter.convertStream(in, lenByte, tag));
|
||||
if (tag != in.read())
|
||||
throw new IOException
|
||||
("Indefinite length encoding not supported");
|
||||
|
Loading…
x
Reference in New Issue
Block a user