/* * Read one block (blockSize bytes) of data from the underlying * FileInputStream, decrypt it and store it in blockBuf for consumption via * read() methods */ private int readBlock() throws IOException, EncFSCorruptDataException, EncFSUnsupportedException { byte[] cipherBuf = new byte[blockSize]; boolean zeroBlock = false; int bytesRead = 0; int lastBytesRead = 0; // Read until we read a whole block or we reach the end of the input while (bytesRead < blockSize) { lastBytesRead = in.read(cipherBuf, bytesRead, blockSize - bytesRead); if (lastBytesRead > 0) { bytesRead += lastBytesRead; } else if (lastBytesRead < 0) { /* * If we read some bytes return that, if not then we're at the * end of the stream */ if (bytesRead == 0) { bytesRead = -1; } break; } } if (bytesRead == blockSize) { // block decode /* * If file holes are allowed then we need to test whether the whole * block is made up of 0's. If not (which is going to be the case * for MAC header by default), we will do block decryption. */ if (config.isHolesAllowed()) { zeroBlock = true; for (int i = 0; i < cipherBuf.length; i++) if (cipherBuf[i] != 0) { zeroBlock = false; break; } } try { if (zeroBlock == true) { blockBuf = cipherBuf; } else { blockBuf = EncFSCrypto.blockDecode(volume, getBlockIV(), cipherBuf); } } catch (InvalidAlgorithmParameterException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { throw new EncFSCorruptDataException(e); } catch (BadPaddingException e) { throw new EncFSCorruptDataException(e); } bufCursor = blockHeaderSize; blockNum++; } else if (bytesRead > 0) { // stream decode try { blockBuf = EncFSCrypto.streamDecode(volume, getBlockIV(), cipherBuf, 0, bytesRead); } catch (InvalidAlgorithmParameterException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { throw new EncFSCorruptDataException(e); } catch (BadPaddingException e) { throw new EncFSCorruptDataException(e); } bufCursor = blockHeaderSize; blockNum++; } // Verify the block header if ((bytesRead > 0) && (blockHeaderSize > 0) && (zeroBlock == false)) { byte mac[] = EncFSCrypto.mac64(volume.getMac(), blockBuf, numMACBytes); for (int i = 0; i < numMACBytes; i++) { if (mac[7 - i] != blockBuf[i]) { throw new EncFSCorruptDataException("Block MAC mismatch"); } } } return bytesRead; }