Commit 66537ee0 authored by Adam Langley's avatar Adam Langley Committed by Kenny Root
Browse files

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|.

Bug: 21396526
Bug: 21209493
Change-Id: Iaad5845621ab8b89b42d5d3ca8e67e297278ca55
parent d8606d56
......@@ -555,7 +555,7 @@ public final class NativeCrypto {
// --- 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);
......
......@@ -28,10 +28,10 @@ import java.io.InputStream;
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() {
......
......@@ -24,7 +24,8 @@ public final class OpenSSLBIOSource {
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) {
......
......@@ -52,7 +52,7 @@ public class OpenSSLX509CRL extends X509CRL {
}
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 class OpenSSLX509CRL extends X509CRL {
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 class OpenSSLX509CRL extends X509CRL {
}
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 class OpenSSLX509CRL extends X509CRL {
public static List<OpenSSLX509CRL> fromPkcs7PemInputStream(InputStream is)
throws ParsingException {
OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(is);
OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(is, true);
final long[] certRefs;
try {
......
......@@ -136,7 +136,7 @@ public class OpenSSLX509CertPath extends CertPath {
}
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) {
......
......@@ -61,7 +61,7 @@ public class OpenSSLX509Certificate extends X509Certificate {
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 class OpenSSLX509Certificate extends X509Certificate {
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 class OpenSSLX509Certificate extends X509Certificate {
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 class OpenSSLX509Certificate extends X509Certificate {
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 {
......
......@@ -1261,8 +1261,9 @@ private:
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 @@ public:
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 @@ static int bio_stream_read(BIO *b, char *buf, int len) {
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;
}
......@@ -5246,7 +5257,9 @@ static jstring ASN1_OBJECT_to_OID_string(JNIEnv* env, const ASN1_OBJECT* obj) {
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) {
......@@ -5259,7 +5272,7 @@ static jlong NativeCrypto_create_BIO_InputStream(JNIEnv* env, jclass, jobject st
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()));
......@@ -10560,7 +10573,7 @@ static JNINativeMethod sNativeCryptoMethods[] = {
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"),
......
......@@ -2824,7 +2824,7 @@ public class NativeCryptoTest extends TestCase {
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);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment