1d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root/*
2d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root * Copyright (C) 2012 The Android Open Source Project
3d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root *
4d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root * Licensed under the Apache License, Version 2.0 (the "License");
5d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root * you may not use this file except in compliance with the License.
6d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root * You may obtain a copy of the License at
7d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root *
8d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root *      http://www.apache.org/licenses/LICENSE-2.0
9d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root *
10d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root * Unless required by applicable law or agreed to in writing, software
11d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root * distributed under the License is distributed on an "AS IS" BASIS,
12d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root * See the License for the specific language governing permissions and
14d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root * limitations under the License.
15d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root */
16d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root
17860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootpackage org.conscrypt;
18d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root
19d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Rootimport java.io.FilterInputStream;
20d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Rootimport java.io.IOException;
21d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Rootimport java.io.InputStream;
22d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root
23d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root/**
24d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root * Provides an interface to OpenSSL's BIO system directly from a Java
25d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root * InputStream. It allows an OpenSSL API to read directly from something more
26d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root * flexible interface than a byte array.
27d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root */
2829916ef38dc9cb4e4c6e3fdb87d4e921546d3ef4Nathan Mittlerclass OpenSSLBIOInputStream extends FilterInputStream {
29d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root    private long ctx;
30d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root
3129916ef38dc9cb4e4c6e3fdb87d4e921546d3ef4Nathan Mittler    OpenSSLBIOInputStream(InputStream is, boolean isFinite) {
32d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root        super(is);
33d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root
3466537ee0121bdd14737191d14927da223f0809eeAdam Langley        ctx = NativeCrypto.create_BIO_InputStream(this, isFinite);
35d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root    }
36d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root
3729916ef38dc9cb4e4c6e3fdb87d4e921546d3ef4Nathan Mittler    long getBioContext() {
38d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root        return ctx;
39d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root    }
40d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root
4129916ef38dc9cb4e4c6e3fdb87d4e921546d3ef4Nathan Mittler    void release() {
4219fdf1af6bada9ebf4820839780d8713ac3824faKenny Root        NativeCrypto.BIO_free_all(ctx);
4319fdf1af6bada9ebf4820839780d8713ac3824faKenny Root    }
4419fdf1af6bada9ebf4820839780d8713ac3824faKenny Root
4532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    /**
4632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root     * Similar to a {@code readLine} method, but matches what OpenSSL expects
4732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root     * from a {@code BIO_gets} method.
4832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root     */
4929916ef38dc9cb4e4c6e3fdb87d4e921546d3ef4Nathan Mittler    int gets(byte[] buffer) throws IOException {
50d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root        if (buffer == null || buffer.length == 0) {
51d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root            return 0;
52d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root        }
53d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root
54d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root        int offset = 0;
5532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root        int inputByte = 0;
5632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root        while (offset < buffer.length) {
57d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root            inputByte = read();
5877be80dd2cfed6c565ffb64fd87131f3e6f43ec7Kenny Root            if (inputByte == -1) {
5977be80dd2cfed6c565ffb64fd87131f3e6f43ec7Kenny Root                // EOF
6077be80dd2cfed6c565ffb64fd87131f3e6f43ec7Kenny Root                break;
6177be80dd2cfed6c565ffb64fd87131f3e6f43ec7Kenny Root            }
6277be80dd2cfed6c565ffb64fd87131f3e6f43ec7Kenny Root            if (inputByte == '\n') {
6332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                if (offset == 0) {
6432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                    // If we haven't read anything yet, ignore CRLF.
6532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                    continue;
6632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                } else {
6732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                    break;
6832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                }
6932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root            }
70d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root
7132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root            buffer[offset++] = (byte) inputByte;
72d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root        }
73d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root
74d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root        return offset;
75d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root    }
76d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root}
77