Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/javax/crypto/CipherInputStream.java
38829 views
/*1* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package javax.crypto;2627import java.io.InputStream;28import java.io.FilterInputStream;29import java.io.IOException;30import javax.crypto.BadPaddingException;31import javax.crypto.IllegalBlockSizeException;3233/**34* A CipherInputStream is composed of an InputStream and a Cipher so35* that read() methods return data that are read in from the36* underlying InputStream but have been additionally processed by the37* Cipher. The Cipher must be fully initialized before being used by38* a CipherInputStream.39*40* <p> For example, if the Cipher is initialized for decryption, the41* CipherInputStream will attempt to read in data and decrypt them,42* before returning the decrypted data.43*44* <p> This class adheres strictly to the semantics, especially the45* failure semantics, of its ancestor classes46* java.io.FilterInputStream and java.io.InputStream. This class has47* exactly those methods specified in its ancestor classes, and48* overrides them all. Moreover, this class catches all exceptions49* that are not thrown by its ancestor classes. In particular, the50* <code>skip</code> method skips, and the <code>available</code>51* method counts only data that have been processed by the encapsulated Cipher.52* This class may catch BadPaddingException and other exceptions thrown by53* failed integrity checks during decryption. These exceptions are not54* re-thrown, so the client may not be informed that integrity checks55* failed. Because of this behavior, this class may not be suitable56* for use with decryption in an authenticated mode of operation (e.g. GCM).57* Applications that require authenticated encryption can use the Cipher API58* directly as an alternative to using this class.59*60* <p> It is crucial for a programmer using this class not to use61* methods that are not defined or overriden in this class (such as a62* new method or constructor that is later added to one of the super63* classes), because the design and implementation of those methods64* are unlikely to have considered security impact with regard to65* CipherInputStream.66*67* @author Li Gong68* @see java.io.InputStream69* @see java.io.FilterInputStream70* @see javax.crypto.Cipher71* @see javax.crypto.CipherOutputStream72*73* @since 1.474*/7576public class CipherInputStream extends FilterInputStream {7778// the cipher engine to use to process stream data79private Cipher cipher;8081// the underlying input stream82private InputStream input;8384/* the buffer holding data that have been read in from the85underlying stream, but have not been processed by the cipher86engine. the size 512 bytes is somewhat randomly chosen */87private byte[] ibuffer = new byte[512];8889// having reached the end of the underlying input stream90private boolean done = false;9192/* the buffer holding data that have been processed by the cipher93engine, but have not been read out */94private byte[] obuffer;95// the offset pointing to the next "new" byte96private int ostart = 0;97// the offset pointing to the last "new" byte98private int ofinish = 0;99// stream status100private boolean closed = false;101102/**103* private convenience function.104*105* Entry condition: ostart = ofinish106*107* Exit condition: ostart <= ofinish108*109* return (ofinish-ostart) (we have this many bytes for you)110* return 0 (no data now, but could have more later)111* return -1 (absolutely no more data)112*113* Note: Exceptions are only thrown after the stream is completely read.114* For AEAD ciphers a read() of any length will internally cause the115* whole stream to be read fully and verify the authentication tag before116* returning decrypted data or exceptions.117*/118private int getMoreData() throws IOException {119if (done) return -1;120int readin = input.read(ibuffer);121if (readin == -1) {122done = true;123try {124obuffer = cipher.doFinal();125} catch (IllegalBlockSizeException | BadPaddingException e) {126obuffer = null;127throw new IOException(e);128}129if (obuffer == null)130return -1;131else {132ostart = 0;133ofinish = obuffer.length;134return ofinish;135}136}137try {138obuffer = cipher.update(ibuffer, 0, readin);139} catch (IllegalStateException e) {140obuffer = null;141throw e;142}143ostart = 0;144if (obuffer == null)145ofinish = 0;146else ofinish = obuffer.length;147return ofinish;148}149150/**151* Constructs a CipherInputStream from an InputStream and a152* Cipher.153* <br>Note: if the specified input stream or cipher is154* null, a NullPointerException may be thrown later when155* they are used.156* @param is the to-be-processed input stream157* @param c an initialized Cipher object158*/159public CipherInputStream(InputStream is, Cipher c) {160super(is);161input = is;162cipher = c;163}164165/**166* Constructs a CipherInputStream from an InputStream without167* specifying a Cipher. This has the effect of constructing a168* CipherInputStream using a NullCipher.169* <br>Note: if the specified input stream is null, a170* NullPointerException may be thrown later when it is used.171* @param is the to-be-processed input stream172*/173protected CipherInputStream(InputStream is) {174super(is);175input = is;176cipher = new NullCipher();177}178179/**180* Reads the next byte of data from this input stream. The value181* byte is returned as an <code>int</code> in the range182* <code>0</code> to <code>255</code>. If no byte is available183* because the end of the stream has been reached, the value184* <code>-1</code> is returned. This method blocks until input data185* is available, the end of the stream is detected, or an exception186* is thrown.187* <p>188*189* @return the next byte of data, or <code>-1</code> if the end of the190* stream is reached.191* @exception IOException if an I/O error occurs.192* @since JCE1.2193*/194public int read() throws IOException {195if (ostart >= ofinish) {196// we loop for new data as the spec says we are blocking197int i = 0;198while (i == 0) i = getMoreData();199if (i == -1) return -1;200}201return ((int) obuffer[ostart++] & 0xff);202};203204/**205* Reads up to <code>b.length</code> bytes of data from this input206* stream into an array of bytes.207* <p>208* The <code>read</code> method of <code>InputStream</code> calls209* the <code>read</code> method of three arguments with the arguments210* <code>b</code>, <code>0</code>, and <code>b.length</code>.211*212* @param b the buffer into which the data is read.213* @return the total number of bytes read into the buffer, or214* <code>-1</code> is there is no more data because the end of215* the stream has been reached.216* @exception IOException if an I/O error occurs.217* @see java.io.InputStream#read(byte[], int, int)218* @since JCE1.2219*/220public int read(byte b[]) throws IOException {221return read(b, 0, b.length);222}223224/**225* Reads up to <code>len</code> bytes of data from this input stream226* into an array of bytes. This method blocks until some input is227* available. If the first argument is <code>null,</code> up to228* <code>len</code> bytes are read and discarded.229*230* @param b the buffer into which the data is read.231* @param off the start offset in the destination array232* <code>buf</code>233* @param len the maximum number of bytes read.234* @return the total number of bytes read into the buffer, or235* <code>-1</code> if there is no more data because the end of236* the stream has been reached.237* @exception IOException if an I/O error occurs.238* @see java.io.InputStream#read()239* @since JCE1.2240*/241public int read(byte b[], int off, int len) throws IOException {242if (ostart >= ofinish) {243// we loop for new data as the spec says we are blocking244int i = 0;245while (i == 0) i = getMoreData();246if (i == -1) return -1;247}248if (len <= 0) {249return 0;250}251int available = ofinish - ostart;252if (len < available) available = len;253if (b != null) {254System.arraycopy(obuffer, ostart, b, off, available);255}256ostart = ostart + available;257return available;258}259260/**261* Skips <code>n</code> bytes of input from the bytes that can be read262* from this input stream without blocking.263*264* <p>Fewer bytes than requested might be skipped.265* The actual number of bytes skipped is equal to <code>n</code> or266* the result of a call to267* {@link #available() available},268* whichever is smaller.269* If <code>n</code> is less than zero, no bytes are skipped.270*271* <p>The actual number of bytes skipped is returned.272*273* @param n the number of bytes to be skipped.274* @return the actual number of bytes skipped.275* @exception IOException if an I/O error occurs.276* @since JCE1.2277*/278public long skip(long n) throws IOException {279int available = ofinish - ostart;280if (n > available) {281n = available;282}283if (n < 0) {284return 0;285}286ostart += n;287return n;288}289290/**291* Returns the number of bytes that can be read from this input292* stream without blocking. The <code>available</code> method of293* <code>InputStream</code> returns <code>0</code>. This method294* <B>should</B> be overridden by subclasses.295*296* @return the number of bytes that can be read from this input stream297* without blocking.298* @exception IOException if an I/O error occurs.299* @since JCE1.2300*/301public int available() throws IOException {302return (ofinish - ostart);303}304305/**306* Closes this input stream and releases any system resources307* associated with the stream.308* <p>309* The <code>close</code> method of <code>CipherInputStream</code>310* calls the <code>close</code> method of its underlying input311* stream.312*313* @exception IOException if an I/O error occurs.314* @since JCE1.2315*/316public void close() throws IOException {317if (closed) {318return;319}320321closed = true;322input.close();323324// Throw away the unprocessed data and throw no crypto exceptions.325// AEAD ciphers are fully readed before closing. Any authentication326// exceptions would occur while reading.327if (!done) {328try {329cipher.doFinal();330}331catch (BadPaddingException | IllegalBlockSizeException ex) {332// Catch exceptions as the rest of the stream is unused.333}334}335ostart = 0;336ofinish = 0;337}338339/**340* Tests if this input stream supports the <code>mark</code>341* and <code>reset</code> methods, which it does not.342*343* @return <code>false</code>, since this class does not support the344* <code>mark</code> and <code>reset</code> methods.345* @see java.io.InputStream#mark(int)346* @see java.io.InputStream#reset()347* @since JCE1.2348*/349public boolean markSupported() {350return false;351}352}353354355