From d976c5a4ee0d093592a93ada6e5118dec6892e9b Mon Sep 17 00:00:00 2001 From: Alex Klyubin Date: Tue, 24 Nov 2015 17:22:27 -0800 Subject: [PATCH] Custom engineUpdate/engineDoFinal(ByteBuffer, ByteBuffer). This makes Android Keystore's Cipher implementation use a custom implementation of engineUpdate(ByteBuffer, ByteBuffer) and engineDoFinal(ByteBuffer, ByteBuffer). The implementation is explicitly designed around the fact that Android Keystore transmits input and receives output via Binder and thus there's no need to attempt any optimizations to avoid copying input and output. Bug: 25863382 Change-Id: I311072891f02f5e7a283628b51b8d6058b55231c --- .../AndroidKeyStoreCipherSpiBase.java | 67 ++++++++++++++++++- 1 file changed, 65 insertions(+), 2 deletions(-) diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java b/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java index 38cacd0c43b49..03a64a7ebb465 100644 --- a/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java +++ b/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java @@ -28,6 +28,7 @@ import android.security.keymaster.OperationResult; import libcore.util.EmptyArray; +import java.nio.BufferOverflowException; import java.nio.ByteBuffer; import java.security.AlgorithmParameters; import java.security.GeneralSecurityException; @@ -385,7 +386,38 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor @Override protected final int engineUpdate(ByteBuffer input, ByteBuffer output) throws ShortBufferException { - return super.engineUpdate(input, output); + if (input == null) { + throw new NullPointerException("input == null"); + } + if (output == null) { + throw new NullPointerException("output == null"); + } + + int inputSize = input.remaining(); + byte[] outputArray; + if (input.hasArray()) { + outputArray = + engineUpdate( + input.array(), input.arrayOffset() + input.position(), inputSize); + input.position(input.position() + inputSize); + } else { + byte[] inputArray = new byte[inputSize]; + input.get(inputArray); + outputArray = engineUpdate(inputArray, 0, inputSize); + } + + int outputSize = (outputArray != null) ? outputArray.length : 0; + if (outputSize > 0) { + int outputBufferAvailable = output.remaining(); + try { + output.put(outputArray); + } catch (BufferOverflowException e) { + throw new ShortBufferException( + "Output buffer too small. Produced: " + outputSize + ", available: " + + outputBufferAvailable); + } + } + return outputSize; } @Override @@ -511,7 +543,38 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor @Override protected final int engineDoFinal(ByteBuffer input, ByteBuffer output) throws ShortBufferException, IllegalBlockSizeException, BadPaddingException { - return super.engineDoFinal(input, output); + if (input == null) { + throw new NullPointerException("input == null"); + } + if (output == null) { + throw new NullPointerException("output == null"); + } + + int inputSize = input.remaining(); + byte[] outputArray; + if (input.hasArray()) { + outputArray = + engineDoFinal( + input.array(), input.arrayOffset() + input.position(), inputSize); + input.position(input.position() + inputSize); + } else { + byte[] inputArray = new byte[inputSize]; + input.get(inputArray); + outputArray = engineDoFinal(inputArray, 0, inputSize); + } + + int outputSize = (outputArray != null) ? outputArray.length : 0; + if (outputSize > 0) { + int outputBufferAvailable = output.remaining(); + try { + output.put(outputArray); + } catch (BufferOverflowException e) { + throw new ShortBufferException( + "Output buffer too small. Produced: " + outputSize + ", available: " + + outputBufferAvailable); + } + } + return outputSize; } @Override