Add isFinite flag to OpenSSLBIOInputStream.
The BIO created by OpenSSLBIOInputStream currently returns -1 and sets
the retry flag when read() returns zero on the underlying InputStream.
This is correct for “infinite” streams (like a socket), but isn't
correct for streams that have a definitive EOF.
This change adds a flag to OpenSSLBIOInputStream so that cases where the
input is finite (i.e. when parsing a PKCS#7 or X.509 block) can
correctly return 0 at EOF from |BIO_read|.
(cherry picked from commit 66537ee0121bdd14737191d14927da223f0809ee)
Bug: 21396526
Bug: 21209493
Change-Id: Iaad5845621ab8b89b42d5d3ca8e67e297278ca55
diff --git a/src/main/java/org/conscrypt/NativeCrypto.java b/src/main/java/org/conscrypt/NativeCrypto.java
index a4bc2ce..6267d4b 100644
--- a/src/main/java/org/conscrypt/NativeCrypto.java
+++ b/src/main/java/org/conscrypt/NativeCrypto.java
@@ -559,7 +559,7 @@
// --- BIO stream creation -------------------------------------------------
- public static native long create_BIO_InputStream(OpenSSLBIOInputStream is);
+ public static native long create_BIO_InputStream(OpenSSLBIOInputStream is, boolean isFinite);
public static native long create_BIO_OutputStream(OutputStream os);
diff --git a/src/main/java/org/conscrypt/OpenSSLBIOInputStream.java b/src/main/java/org/conscrypt/OpenSSLBIOInputStream.java
index cb5d0ca..cf220a6 100644
--- a/src/main/java/org/conscrypt/OpenSSLBIOInputStream.java
+++ b/src/main/java/org/conscrypt/OpenSSLBIOInputStream.java
@@ -28,10 +28,10 @@
public class OpenSSLBIOInputStream extends FilterInputStream {
private long ctx;
- public OpenSSLBIOInputStream(InputStream is) {
+ public OpenSSLBIOInputStream(InputStream is, boolean isFinite) {
super(is);
- ctx = NativeCrypto.create_BIO_InputStream(this);
+ ctx = NativeCrypto.create_BIO_InputStream(this, isFinite);
}
public long getBioContext() {
diff --git a/src/main/java/org/conscrypt/OpenSSLBIOSource.java b/src/main/java/org/conscrypt/OpenSSLBIOSource.java
index 61e966b..7bf2c3c 100644
--- a/src/main/java/org/conscrypt/OpenSSLBIOSource.java
+++ b/src/main/java/org/conscrypt/OpenSSLBIOSource.java
@@ -24,7 +24,8 @@
private OpenSSLBIOInputStream source;
public static OpenSSLBIOSource wrap(ByteBuffer buffer) {
- return new OpenSSLBIOSource(new OpenSSLBIOInputStream(new ByteBufferInputStream(buffer)));
+ return new OpenSSLBIOSource(
+ new OpenSSLBIOInputStream(new ByteBufferInputStream(buffer), false));
}
public OpenSSLBIOSource(OpenSSLBIOInputStream source) {
diff --git a/src/main/java/org/conscrypt/OpenSSLX509CRL.java b/src/main/java/org/conscrypt/OpenSSLX509CRL.java
index 3697b11..a063536 100644
--- a/src/main/java/org/conscrypt/OpenSSLX509CRL.java
+++ b/src/main/java/org/conscrypt/OpenSSLX509CRL.java
@@ -52,7 +52,7 @@
}
public static OpenSSLX509CRL fromX509DerInputStream(InputStream is) throws ParsingException {
- final OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(is);
+ final OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(is, true);
try {
final long crlCtx = NativeCrypto.d2i_X509_CRL_bio(bis.getBioContext());
@@ -69,7 +69,7 @@
public static List<OpenSSLX509CRL> fromPkcs7DerInputStream(InputStream is)
throws ParsingException {
- OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(is);
+ OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(is, true);
final long[] certRefs;
try {
@@ -91,7 +91,7 @@
}
public static OpenSSLX509CRL fromX509PemInputStream(InputStream is) throws ParsingException {
- final OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(is);
+ final OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(is, true);
try {
final long crlCtx = NativeCrypto.PEM_read_bio_X509_CRL(bis.getBioContext());
@@ -108,7 +108,7 @@
public static List<OpenSSLX509CRL> fromPkcs7PemInputStream(InputStream is)
throws ParsingException {
- OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(is);
+ OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(is, true);
final long[] certRefs;
try {
diff --git a/src/main/java/org/conscrypt/OpenSSLX509CertPath.java b/src/main/java/org/conscrypt/OpenSSLX509CertPath.java
index 6cea051..7663101 100644
--- a/src/main/java/org/conscrypt/OpenSSLX509CertPath.java
+++ b/src/main/java/org/conscrypt/OpenSSLX509CertPath.java
@@ -136,7 +136,7 @@
}
private static CertPath fromPkiPathEncoding(InputStream inStream) throws CertificateException {
- OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(inStream);
+ OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(inStream, true);
final boolean markable = inStream.markSupported();
if (markable) {
diff --git a/src/main/java/org/conscrypt/OpenSSLX509Certificate.java b/src/main/java/org/conscrypt/OpenSSLX509Certificate.java
index abd1ef2..aed141d 100644
--- a/src/main/java/org/conscrypt/OpenSSLX509Certificate.java
+++ b/src/main/java/org/conscrypt/OpenSSLX509Certificate.java
@@ -61,7 +61,7 @@
public static OpenSSLX509Certificate fromX509DerInputStream(InputStream is)
throws ParsingException {
@SuppressWarnings("resource")
- final OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(is);
+ final OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(is, true);
try {
final long certCtx = NativeCrypto.d2i_X509_bio(bis.getBioContext());
@@ -87,7 +87,7 @@
public static List<OpenSSLX509Certificate> fromPkcs7DerInputStream(InputStream is)
throws ParsingException {
@SuppressWarnings("resource")
- OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(is);
+ OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(is, true);
final long[] certRefs;
try {
@@ -116,7 +116,7 @@
public static OpenSSLX509Certificate fromX509PemInputStream(InputStream is)
throws ParsingException {
@SuppressWarnings("resource")
- final OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(is);
+ final OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(is, true);
try {
final long certCtx = NativeCrypto.PEM_read_bio_X509(bis.getBioContext());
@@ -134,7 +134,7 @@
public static List<OpenSSLX509Certificate> fromPkcs7PemInputStream(InputStream is)
throws ParsingException {
@SuppressWarnings("resource")
- OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(is);
+ OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(is, true);
final long[] certRefs;
try {
diff --git a/src/main/native/org_conscrypt_NativeCrypto.cpp b/src/main/native/org_conscrypt_NativeCrypto.cpp
index 9cb0638..c7ffdd6 100644
--- a/src/main/native/org_conscrypt_NativeCrypto.cpp
+++ b/src/main/native/org_conscrypt_NativeCrypto.cpp
@@ -1261,8 +1261,9 @@
class BIO_InputStream : public BIO_Stream {
public:
- BIO_InputStream(jobject stream) :
- BIO_Stream(stream) {
+ BIO_InputStream(jobject stream, bool isFinite) :
+ BIO_Stream(stream),
+ isFinite_(isFinite) {
}
int read(char *buf, int len) {
@@ -1280,7 +1281,13 @@
return read;
}
+ bool isFinite() const {
+ return isFinite_;
+ }
+
private:
+ const bool isFinite_;
+
int read_internal(char *buf, int len, jmethodID method) {
JNIEnv* env = getJNIEnv();
if (env == NULL) {
@@ -1385,7 +1392,11 @@
BIO_InputStream* stream = static_cast<BIO_InputStream*>(b->ptr);
int ret = stream->read(buf, len);
if (ret == 0) {
- // EOF is indicated by -1 with a BIO flag.
+ if (stream->isFinite()) {
+ return 0;
+ }
+ // If the BIO_InputStream is not finite then EOF doesn't mean that
+ // there's nothing more coming.
BIO_set_retry_read(b);
return -1;
}
@@ -5304,7 +5315,9 @@
return env->NewStringUTF(output);
}
-static jlong NativeCrypto_create_BIO_InputStream(JNIEnv* env, jclass, jobject streamObj) {
+static jlong NativeCrypto_create_BIO_InputStream(JNIEnv* env, jclass,
+ jobject streamObj,
+ jboolean isFinite) {
JNI_TRACE("create_BIO_InputStream(%p)", streamObj);
if (streamObj == NULL) {
@@ -5317,7 +5330,7 @@
return 0;
}
- bio_stream_assign(bio.get(), new BIO_InputStream(streamObj));
+ bio_stream_assign(bio.get(), new BIO_InputStream(streamObj, isFinite));
JNI_TRACE("create_BIO_InputStream(%p) => %p", streamObj, bio.get());
return static_cast<jlong>(reinterpret_cast<uintptr_t>(bio.release()));
@@ -10620,7 +10633,7 @@
NATIVE_METHOD(NativeCrypto, OBJ_txt2nid, "(Ljava/lang/String;)I"),
NATIVE_METHOD(NativeCrypto, OBJ_txt2nid_longName, "(Ljava/lang/String;)Ljava/lang/String;"),
NATIVE_METHOD(NativeCrypto, OBJ_txt2nid_oid, "(Ljava/lang/String;)Ljava/lang/String;"),
- NATIVE_METHOD(NativeCrypto, create_BIO_InputStream, ("(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLBIOInputStream;)J")),
+ NATIVE_METHOD(NativeCrypto, create_BIO_InputStream, ("(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLBIOInputStream;Z)J")),
NATIVE_METHOD(NativeCrypto, create_BIO_OutputStream, "(Ljava/io/OutputStream;)J"),
NATIVE_METHOD(NativeCrypto, BIO_read, "(J[B)I"),
NATIVE_METHOD(NativeCrypto, BIO_write, "(J[BII)V"),
diff --git a/src/test/java/org/conscrypt/NativeCryptoTest.java b/src/test/java/org/conscrypt/NativeCryptoTest.java
index ccad696..9e47e54 100644
--- a/src/test/java/org/conscrypt/NativeCryptoTest.java
+++ b/src/test/java/org/conscrypt/NativeCryptoTest.java
@@ -2824,7 +2824,7 @@
ByteArrayInputStream is = new ByteArrayInputStream(actual);
@SuppressWarnings("resource")
- OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(is);
+ OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(is, true);
try {
byte[] buffer = new byte[1024];
int numRead = NativeCrypto.BIO_read(bis.getBioContext(), buffer);