1f878e438660d93f8689b864165230492e7a412d4Kenny Root/*
2f878e438660d93f8689b864165230492e7a412d4Kenny Root * Copyright (C) 2014 The Android Open Source Project
3f878e438660d93f8689b864165230492e7a412d4Kenny Root *
4f878e438660d93f8689b864165230492e7a412d4Kenny Root * Licensed under the Apache License, Version 2.0 (the "License");
5f878e438660d93f8689b864165230492e7a412d4Kenny Root * you may not use this file except in compliance with the License.
6f878e438660d93f8689b864165230492e7a412d4Kenny Root * You may obtain a copy of the License at
7f878e438660d93f8689b864165230492e7a412d4Kenny Root *
8f878e438660d93f8689b864165230492e7a412d4Kenny Root *      http://www.apache.org/licenses/LICENSE-2.0
9f878e438660d93f8689b864165230492e7a412d4Kenny Root *
10f878e438660d93f8689b864165230492e7a412d4Kenny Root * Unless required by applicable law or agreed to in writing, software
11f878e438660d93f8689b864165230492e7a412d4Kenny Root * distributed under the License is distributed on an "AS IS" BASIS,
12f878e438660d93f8689b864165230492e7a412d4Kenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f878e438660d93f8689b864165230492e7a412d4Kenny Root * See the License for the specific language governing permissions and
14f878e438660d93f8689b864165230492e7a412d4Kenny Root * limitations under the License.
15f878e438660d93f8689b864165230492e7a412d4Kenny Root */
16f878e438660d93f8689b864165230492e7a412d4Kenny Root
17f878e438660d93f8689b864165230492e7a412d4Kenny Rootpackage org.conscrypt;
18f878e438660d93f8689b864165230492e7a412d4Kenny Root
19f878e438660d93f8689b864165230492e7a412d4Kenny Rootimport java.io.IOException;
20f878e438660d93f8689b864165230492e7a412d4Kenny Rootimport java.io.InputStream;
21f878e438660d93f8689b864165230492e7a412d4Kenny Rootimport java.nio.ByteBuffer;
22f878e438660d93f8689b864165230492e7a412d4Kenny Root
235070bdfc6277af136b7eb5fe5d0d72ad2ff6a2ebKenny Root/**
245070bdfc6277af136b7eb5fe5d0d72ad2ff6a2ebKenny Root * Wrapped by a BoringSSL BIO to act as a source of bytes.
255070bdfc6277af136b7eb5fe5d0d72ad2ff6a2ebKenny Root *
265070bdfc6277af136b7eb5fe5d0d72ad2ff6a2ebKenny Root * @hide
275070bdfc6277af136b7eb5fe5d0d72ad2ff6a2ebKenny Root */
28dbe082cb70a1ffbe1a693bd583a06ecad585f46dNathan Mittler@Internal
29f878e438660d93f8689b864165230492e7a412d4Kenny Rootpublic final class OpenSSLBIOSource {
30f878e438660d93f8689b864165230492e7a412d4Kenny Root    private OpenSSLBIOInputStream source;
31f878e438660d93f8689b864165230492e7a412d4Kenny Root
32f878e438660d93f8689b864165230492e7a412d4Kenny Root    public static OpenSSLBIOSource wrap(ByteBuffer buffer) {
3366537ee0121bdd14737191d14927da223f0809eeAdam Langley        return new OpenSSLBIOSource(
3466537ee0121bdd14737191d14927da223f0809eeAdam Langley            new OpenSSLBIOInputStream(new ByteBufferInputStream(buffer), false));
35f878e438660d93f8689b864165230492e7a412d4Kenny Root    }
36f878e438660d93f8689b864165230492e7a412d4Kenny Root
37f878e438660d93f8689b864165230492e7a412d4Kenny Root    public OpenSSLBIOSource(OpenSSLBIOInputStream source) {
38f878e438660d93f8689b864165230492e7a412d4Kenny Root        this.source = source;
39f878e438660d93f8689b864165230492e7a412d4Kenny Root    }
40f878e438660d93f8689b864165230492e7a412d4Kenny Root
41f878e438660d93f8689b864165230492e7a412d4Kenny Root    public long getContext() {
42f878e438660d93f8689b864165230492e7a412d4Kenny Root        return source.getBioContext();
43f878e438660d93f8689b864165230492e7a412d4Kenny Root    }
44f878e438660d93f8689b864165230492e7a412d4Kenny Root
45f878e438660d93f8689b864165230492e7a412d4Kenny Root    public synchronized void release() {
46f878e438660d93f8689b864165230492e7a412d4Kenny Root        if (source != null) {
47f878e438660d93f8689b864165230492e7a412d4Kenny Root            NativeCrypto.BIO_free_all(source.getBioContext());
48f878e438660d93f8689b864165230492e7a412d4Kenny Root            source = null;
49f878e438660d93f8689b864165230492e7a412d4Kenny Root        }
50f878e438660d93f8689b864165230492e7a412d4Kenny Root    }
51f878e438660d93f8689b864165230492e7a412d4Kenny Root
52f878e438660d93f8689b864165230492e7a412d4Kenny Root    @Override
53f878e438660d93f8689b864165230492e7a412d4Kenny Root    protected void finalize() throws Throwable {
54f878e438660d93f8689b864165230492e7a412d4Kenny Root        try {
55f878e438660d93f8689b864165230492e7a412d4Kenny Root            release();
56f878e438660d93f8689b864165230492e7a412d4Kenny Root        } finally {
57f878e438660d93f8689b864165230492e7a412d4Kenny Root            super.finalize();
58f878e438660d93f8689b864165230492e7a412d4Kenny Root        }
59f878e438660d93f8689b864165230492e7a412d4Kenny Root    }
60f878e438660d93f8689b864165230492e7a412d4Kenny Root
61f878e438660d93f8689b864165230492e7a412d4Kenny Root    private static class ByteBufferInputStream extends InputStream {
62f878e438660d93f8689b864165230492e7a412d4Kenny Root        private final ByteBuffer source;
63f878e438660d93f8689b864165230492e7a412d4Kenny Root
64f878e438660d93f8689b864165230492e7a412d4Kenny Root        public ByteBufferInputStream(ByteBuffer source) {
65f878e438660d93f8689b864165230492e7a412d4Kenny Root            this.source = source;
66f878e438660d93f8689b864165230492e7a412d4Kenny Root        }
67f878e438660d93f8689b864165230492e7a412d4Kenny Root
68f878e438660d93f8689b864165230492e7a412d4Kenny Root        @Override
69f878e438660d93f8689b864165230492e7a412d4Kenny Root        public int read() throws IOException {
70f878e438660d93f8689b864165230492e7a412d4Kenny Root            if (source.remaining() > 0) {
71f878e438660d93f8689b864165230492e7a412d4Kenny Root                return source.get();
72f878e438660d93f8689b864165230492e7a412d4Kenny Root            } else {
73f878e438660d93f8689b864165230492e7a412d4Kenny Root                return -1;
74f878e438660d93f8689b864165230492e7a412d4Kenny Root            }
75f878e438660d93f8689b864165230492e7a412d4Kenny Root        }
76f878e438660d93f8689b864165230492e7a412d4Kenny Root
77f878e438660d93f8689b864165230492e7a412d4Kenny Root        @Override
78f878e438660d93f8689b864165230492e7a412d4Kenny Root        public int available() throws IOException {
79f878e438660d93f8689b864165230492e7a412d4Kenny Root            return source.limit() - source.position();
80f878e438660d93f8689b864165230492e7a412d4Kenny Root        }
81f878e438660d93f8689b864165230492e7a412d4Kenny Root
82f878e438660d93f8689b864165230492e7a412d4Kenny Root        @Override
83f878e438660d93f8689b864165230492e7a412d4Kenny Root        public int read(byte[] buffer) throws IOException {
84f878e438660d93f8689b864165230492e7a412d4Kenny Root            int originalPosition = source.position();
85f878e438660d93f8689b864165230492e7a412d4Kenny Root            source.get(buffer);
86f878e438660d93f8689b864165230492e7a412d4Kenny Root            return source.position() - originalPosition;
87f878e438660d93f8689b864165230492e7a412d4Kenny Root        }
88f878e438660d93f8689b864165230492e7a412d4Kenny Root
89f878e438660d93f8689b864165230492e7a412d4Kenny Root        @Override
90f878e438660d93f8689b864165230492e7a412d4Kenny Root        public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
91f878e438660d93f8689b864165230492e7a412d4Kenny Root            int toRead = Math.min(source.remaining(), byteCount);
92f878e438660d93f8689b864165230492e7a412d4Kenny Root            int originalPosition = source.position();
93f878e438660d93f8689b864165230492e7a412d4Kenny Root            source.get(buffer, byteOffset, toRead);
94f878e438660d93f8689b864165230492e7a412d4Kenny Root            return source.position() - originalPosition;
95f878e438660d93f8689b864165230492e7a412d4Kenny Root        }
96f878e438660d93f8689b864165230492e7a412d4Kenny Root
97f878e438660d93f8689b864165230492e7a412d4Kenny Root        @Override
98f878e438660d93f8689b864165230492e7a412d4Kenny Root        public void reset() throws IOException {
99f878e438660d93f8689b864165230492e7a412d4Kenny Root            source.reset();
100f878e438660d93f8689b864165230492e7a412d4Kenny Root        }
101f878e438660d93f8689b864165230492e7a412d4Kenny Root
102f878e438660d93f8689b864165230492e7a412d4Kenny Root        @Override
103f878e438660d93f8689b864165230492e7a412d4Kenny Root        public long skip(long byteCount) throws IOException {
104f878e438660d93f8689b864165230492e7a412d4Kenny Root            int originalPosition = source.position();
105f878e438660d93f8689b864165230492e7a412d4Kenny Root            source.position((int) (originalPosition + byteCount));
106f878e438660d93f8689b864165230492e7a412d4Kenny Root            return source.position() - originalPosition;
107f878e438660d93f8689b864165230492e7a412d4Kenny Root        }
108f878e438660d93f8689b864165230492e7a412d4Kenny Root    }
109f878e438660d93f8689b864165230492e7a412d4Kenny Root}
110