Loading keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java +71 −23 Original line number Diff line number Diff line Loading @@ -19,12 +19,14 @@ package android.security.keystore; import android.os.IBinder; import android.security.KeyStore; import android.security.KeyStoreException; import android.security.keymaster.KeymasterDefs; import android.security.keymaster.OperationResult; import libcore.util.EmptyArray; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.security.ProviderException; /** * Helper for streaming a crypto operation's input and output via {@link KeyStore} service's Loading Loading @@ -135,14 +137,15 @@ class KeyStoreCryptoOperationChunkedStreamer implements KeyStoreCryptoOperationS mBuffered = EmptyArray.BYTE; mBufferedOffset = 0; mBufferedLength = 0; } else if (opResult.inputConsumed == 0) { } else if (opResult.inputConsumed <= 0) { // Nothing was consumed. More input needed. if (inputLength > 0) { // More input is available, but it wasn't included into the previous chunk // because the chunk reached its maximum permitted size. // Shouldn't have happened. throw new IllegalStateException("Nothing consumed from max-sized chunk: " + chunk.length + " bytes"); throw new KeyStoreException(KeymasterDefs.KM_ERROR_UNKNOWN_ERROR, "Keystore consumed nothing from max-sized chunk: " + chunk.length + " bytes"); } mBuffered = chunk; mBufferedOffset = 0; Loading @@ -153,8 +156,9 @@ class KeyStoreCryptoOperationChunkedStreamer implements KeyStoreCryptoOperationS mBufferedOffset = opResult.inputConsumed; mBufferedLength = chunk.length - opResult.inputConsumed; } else { throw new IllegalStateException("Consumed more than provided: " + opResult.inputConsumed + ", provided: " + chunk.length); throw new KeyStoreException(KeymasterDefs.KM_ERROR_UNKNOWN_ERROR, "Keystore consumed more input than provided. Provided: " + chunk.length + ", consumed: " + opResult.inputConsumed); } if ((opResult.output != null) && (opResult.output.length > 0)) { Loading @@ -165,7 +169,7 @@ class KeyStoreCryptoOperationChunkedStreamer implements KeyStoreCryptoOperationS try { bufferedOutput.write(opResult.output); } catch (IOException e) { throw new IllegalStateException("Failed to buffer output", e); throw new ProviderException("Failed to buffer output", e); } } } else { Loading @@ -179,7 +183,7 @@ class KeyStoreCryptoOperationChunkedStreamer implements KeyStoreCryptoOperationS try { bufferedOutput.write(opResult.output); } catch (IOException e) { throw new IllegalStateException("Failed to buffer output", e); throw new ProviderException("Failed to buffer output", e); } result = bufferedOutput.toByteArray(); } Loading Loading @@ -229,11 +233,11 @@ class KeyStoreCryptoOperationChunkedStreamer implements KeyStoreCryptoOperationS return EmptyArray.BYTE; } // Keep invoking the update operation with remaining buffered data until either all of the // buffered data is consumed or until update fails to consume anything. ByteArrayOutputStream bufferedOutput = null; while (mBufferedLength > 0) { byte[] chunk = ArrayUtils.subarray(mBuffered, mBufferedOffset, mBufferedLength); mBuffered = EmptyArray.BYTE; mBufferedLength = 0; mBufferedOffset = 0; OperationResult opResult = mKeyStoreStream.update(chunk); if (opResult == null) { throw new KeyStoreConnectException(); Loading @@ -241,15 +245,59 @@ class KeyStoreCryptoOperationChunkedStreamer implements KeyStoreCryptoOperationS throw KeyStore.getKeyStoreException(opResult.resultCode); } if (opResult.inputConsumed < chunk.length) { throw new IllegalStateException("Keystore failed to consume all input. Provided: " if (opResult.inputConsumed <= 0) { // Nothing was consumed. Break out of the loop to avoid an infinite loop. break; } if (opResult.inputConsumed >= chunk.length) { // All of the input was consumed mBuffered = EmptyArray.BYTE; mBufferedOffset = 0; mBufferedLength = 0; } else { // Some of the input was not consumed mBuffered = chunk; mBufferedOffset = opResult.inputConsumed; mBufferedLength = chunk.length - opResult.inputConsumed; } if (opResult.inputConsumed > chunk.length) { throw new KeyStoreException(KeymasterDefs.KM_ERROR_UNKNOWN_ERROR, "Keystore consumed more input than provided. Provided: " + chunk.length + ", consumed: " + opResult.inputConsumed); } else if (opResult.inputConsumed > chunk.length) { throw new IllegalStateException("Keystore consumed more input than provided" + " . Provided: " + chunk.length + ", consumed: " + opResult.inputConsumed); } byte[] result = (opResult.output != null) ? opResult.output : EmptyArray.BYTE; if ((opResult.output != null) && (opResult.output.length > 0)) { // Some output was produced by this update operation if (bufferedOutput == null) { // No output buffered yet. if (mBufferedLength == 0) { // No more output will be produced by this flush operation mProducedOutputSizeBytes += opResult.output.length; return opResult.output; } else { // More output might be produced by this flush operation -- buffer output. bufferedOutput = new ByteArrayOutputStream(); } } // Buffer the output from this update operation try { bufferedOutput.write(opResult.output); } catch (IOException e) { throw new ProviderException("Failed to buffer output", e); } } } if (mBufferedLength > 0) { throw new KeyStoreException(KeymasterDefs.KM_ERROR_INVALID_INPUT_LENGTH, "Keystore failed to consume last " + ((mBufferedLength != 1) ? (mBufferedLength + " bytes") : "byte") + " of input"); } byte[] result = (bufferedOutput != null) ? bufferedOutput.toByteArray() : EmptyArray.BYTE; mProducedOutputSizeBytes += result.length; return result; } Loading Loading
keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java +71 −23 Original line number Diff line number Diff line Loading @@ -19,12 +19,14 @@ package android.security.keystore; import android.os.IBinder; import android.security.KeyStore; import android.security.KeyStoreException; import android.security.keymaster.KeymasterDefs; import android.security.keymaster.OperationResult; import libcore.util.EmptyArray; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.security.ProviderException; /** * Helper for streaming a crypto operation's input and output via {@link KeyStore} service's Loading Loading @@ -135,14 +137,15 @@ class KeyStoreCryptoOperationChunkedStreamer implements KeyStoreCryptoOperationS mBuffered = EmptyArray.BYTE; mBufferedOffset = 0; mBufferedLength = 0; } else if (opResult.inputConsumed == 0) { } else if (opResult.inputConsumed <= 0) { // Nothing was consumed. More input needed. if (inputLength > 0) { // More input is available, but it wasn't included into the previous chunk // because the chunk reached its maximum permitted size. // Shouldn't have happened. throw new IllegalStateException("Nothing consumed from max-sized chunk: " + chunk.length + " bytes"); throw new KeyStoreException(KeymasterDefs.KM_ERROR_UNKNOWN_ERROR, "Keystore consumed nothing from max-sized chunk: " + chunk.length + " bytes"); } mBuffered = chunk; mBufferedOffset = 0; Loading @@ -153,8 +156,9 @@ class KeyStoreCryptoOperationChunkedStreamer implements KeyStoreCryptoOperationS mBufferedOffset = opResult.inputConsumed; mBufferedLength = chunk.length - opResult.inputConsumed; } else { throw new IllegalStateException("Consumed more than provided: " + opResult.inputConsumed + ", provided: " + chunk.length); throw new KeyStoreException(KeymasterDefs.KM_ERROR_UNKNOWN_ERROR, "Keystore consumed more input than provided. Provided: " + chunk.length + ", consumed: " + opResult.inputConsumed); } if ((opResult.output != null) && (opResult.output.length > 0)) { Loading @@ -165,7 +169,7 @@ class KeyStoreCryptoOperationChunkedStreamer implements KeyStoreCryptoOperationS try { bufferedOutput.write(opResult.output); } catch (IOException e) { throw new IllegalStateException("Failed to buffer output", e); throw new ProviderException("Failed to buffer output", e); } } } else { Loading @@ -179,7 +183,7 @@ class KeyStoreCryptoOperationChunkedStreamer implements KeyStoreCryptoOperationS try { bufferedOutput.write(opResult.output); } catch (IOException e) { throw new IllegalStateException("Failed to buffer output", e); throw new ProviderException("Failed to buffer output", e); } result = bufferedOutput.toByteArray(); } Loading Loading @@ -229,11 +233,11 @@ class KeyStoreCryptoOperationChunkedStreamer implements KeyStoreCryptoOperationS return EmptyArray.BYTE; } // Keep invoking the update operation with remaining buffered data until either all of the // buffered data is consumed or until update fails to consume anything. ByteArrayOutputStream bufferedOutput = null; while (mBufferedLength > 0) { byte[] chunk = ArrayUtils.subarray(mBuffered, mBufferedOffset, mBufferedLength); mBuffered = EmptyArray.BYTE; mBufferedLength = 0; mBufferedOffset = 0; OperationResult opResult = mKeyStoreStream.update(chunk); if (opResult == null) { throw new KeyStoreConnectException(); Loading @@ -241,15 +245,59 @@ class KeyStoreCryptoOperationChunkedStreamer implements KeyStoreCryptoOperationS throw KeyStore.getKeyStoreException(opResult.resultCode); } if (opResult.inputConsumed < chunk.length) { throw new IllegalStateException("Keystore failed to consume all input. Provided: " if (opResult.inputConsumed <= 0) { // Nothing was consumed. Break out of the loop to avoid an infinite loop. break; } if (opResult.inputConsumed >= chunk.length) { // All of the input was consumed mBuffered = EmptyArray.BYTE; mBufferedOffset = 0; mBufferedLength = 0; } else { // Some of the input was not consumed mBuffered = chunk; mBufferedOffset = opResult.inputConsumed; mBufferedLength = chunk.length - opResult.inputConsumed; } if (opResult.inputConsumed > chunk.length) { throw new KeyStoreException(KeymasterDefs.KM_ERROR_UNKNOWN_ERROR, "Keystore consumed more input than provided. Provided: " + chunk.length + ", consumed: " + opResult.inputConsumed); } else if (opResult.inputConsumed > chunk.length) { throw new IllegalStateException("Keystore consumed more input than provided" + " . Provided: " + chunk.length + ", consumed: " + opResult.inputConsumed); } byte[] result = (opResult.output != null) ? opResult.output : EmptyArray.BYTE; if ((opResult.output != null) && (opResult.output.length > 0)) { // Some output was produced by this update operation if (bufferedOutput == null) { // No output buffered yet. if (mBufferedLength == 0) { // No more output will be produced by this flush operation mProducedOutputSizeBytes += opResult.output.length; return opResult.output; } else { // More output might be produced by this flush operation -- buffer output. bufferedOutput = new ByteArrayOutputStream(); } } // Buffer the output from this update operation try { bufferedOutput.write(opResult.output); } catch (IOException e) { throw new ProviderException("Failed to buffer output", e); } } } if (mBufferedLength > 0) { throw new KeyStoreException(KeymasterDefs.KM_ERROR_INVALID_INPUT_LENGTH, "Keystore failed to consume last " + ((mBufferedLength != 1) ? (mBufferedLength + " bytes") : "byte") + " of input"); } byte[] result = (bufferedOutput != null) ? bufferedOutput.toByteArray() : EmptyArray.BYTE; mProducedOutputSizeBytes += result.length; return result; } Loading