1ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin/* 2ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * Copyright (C) 2015 The Android Open Source Project 3ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * 4ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * Licensed under the Apache License, Version 2.0 (the "License"); 5ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * you may not use this file except in compliance with the License. 6ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * You may obtain a copy of the License at 7ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * 8ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * http://www.apache.org/licenses/LICENSE-2.0 9ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * 10ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * Unless required by applicable law or agreed to in writing, software 11ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * distributed under the License is distributed on an "AS IS" BASIS, 12ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * See the License for the specific language governing permissions and 14ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * limitations under the License. 15ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin */ 16ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 17ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubinpackage android.security.keystore; 18ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 19ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubinimport android.annotation.CallSuper; 20ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubinimport android.annotation.NonNull; 21ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubinimport android.os.IBinder; 22ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubinimport android.security.KeyStore; 23ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubinimport android.security.KeyStoreException; 24ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubinimport android.security.keymaster.KeymasterArguments; 25ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubinimport android.security.keymaster.KeymasterDefs; 26ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubinimport android.security.keymaster.OperationResult; 27ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 284a0ff7ca984d29bd34b02e54441957cad65e8b53Alex Klyubinimport libcore.util.EmptyArray; 29ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 30ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubinimport java.nio.ByteBuffer; 31ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubinimport java.security.InvalidKeyException; 32ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubinimport java.security.InvalidParameterException; 33ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubinimport java.security.PrivateKey; 34ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubinimport java.security.ProviderException; 35ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubinimport java.security.PublicKey; 36ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubinimport java.security.SecureRandom; 37ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubinimport java.security.SignatureException; 38ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubinimport java.security.SignatureSpi; 39ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 40ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin/** 41ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * Base class for {@link SignatureSpi} implementations of Android KeyStore backed ciphers. 42ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * 43ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * @hide 44ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin */ 45ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubinabstract class AndroidKeyStoreSignatureSpiBase extends SignatureSpi 46ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin implements KeyStoreCryptoOperation { 47ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin private final KeyStore mKeyStore; 48ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 49ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin // Fields below are populated by SignatureSpi.engineInitSign/engineInitVerify and KeyStore.begin 50ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin // and should be preserved after SignatureSpi.engineSign/engineVerify finishes. 51ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin private boolean mSigning; 52ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin private AndroidKeyStoreKey mKey; 53ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 54ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin /** 55ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * Token referencing this operation inside keystore service. It is initialized by 56ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * {@code engineInitSign}/{@code engineInitVerify} and is invalidated when 57ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * {@code engineSign}/{@code engineVerify} succeeds and on some error conditions in between. 58ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin */ 59ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin private IBinder mOperationToken; 60ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin private long mOperationHandle; 61d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin private KeyStoreCryptoOperationStreamer mMessageStreamer; 62ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 63ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin /** 64ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * Encountered exception which could not be immediately thrown because it was encountered inside 65ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * a method that does not throw checked exception. This exception will be thrown from 66ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * {@code engineSign} or {@code engineVerify}. Once such an exception is encountered, 67ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * {@code engineUpdate} starts ignoring input data. 68ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin */ 69ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin private Exception mCachedException; 70ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 71ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin AndroidKeyStoreSignatureSpiBase() { 72ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin mKeyStore = KeyStore.getInstance(); 73ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 74ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 75ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin @Override 76ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin protected final void engineInitSign(PrivateKey key) throws InvalidKeyException { 77ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin engineInitSign(key, null); 78ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 79ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 80ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin @Override 81ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin protected final void engineInitSign(PrivateKey privateKey, SecureRandom random) 82ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin throws InvalidKeyException { 83ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin resetAll(); 84ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 85ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin boolean success = false; 86ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin try { 87ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin if (privateKey == null) { 88ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin throw new InvalidKeyException("Unsupported key: null"); 89ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 90ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin AndroidKeyStoreKey keystoreKey; 91ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin if (privateKey instanceof AndroidKeyStorePrivateKey) { 92ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin keystoreKey = (AndroidKeyStoreKey) privateKey; 93ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } else { 94ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin throw new InvalidKeyException("Unsupported private key type: " + privateKey); 95ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 96ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin mSigning = true; 97ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin initKey(keystoreKey); 98ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin appRandom = random; 99ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin ensureKeystoreOperationInitialized(); 100ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin success = true; 101ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } finally { 102ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin if (!success) { 103ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin resetAll(); 104ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 105ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 106ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 107ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 108ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin @Override 109ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin protected final void engineInitVerify(PublicKey publicKey) throws InvalidKeyException { 110ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin resetAll(); 111ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 112ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin boolean success = false; 113ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin try { 114ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin if (publicKey == null) { 115ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin throw new InvalidKeyException("Unsupported key: null"); 116ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 117ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin AndroidKeyStoreKey keystoreKey; 118ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin if (publicKey instanceof AndroidKeyStorePublicKey) { 119ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin keystoreKey = (AndroidKeyStorePublicKey) publicKey; 120ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } else { 121ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin throw new InvalidKeyException("Unsupported public key type: " + publicKey); 122ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 123ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin mSigning = false; 124ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin initKey(keystoreKey); 125ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin appRandom = null; 126ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin ensureKeystoreOperationInitialized(); 127ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin success = true; 128ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } finally { 129ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin if (!success) { 130ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin resetAll(); 131ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 132ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 133ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 134ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 135ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin /** 136ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * Configures this signature instance to use the provided key. 137ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * 138ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * @throws InvalidKeyException if the {@code key} is not suitable. 139ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin */ 140ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin @CallSuper 141ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin protected void initKey(AndroidKeyStoreKey key) throws InvalidKeyException { 142ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin mKey = key; 143ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 144ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 145ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin /** 146ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * Resets this cipher to its pristine pre-init state. This must be equivalent to obtaining a new 147ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * cipher instance. 148ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * 149ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * <p>Subclasses storing additional state should override this method, reset the additional 150ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * state, and then chain to superclass. 151ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin */ 152ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin @CallSuper 153ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin protected void resetAll() { 154ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin IBinder operationToken = mOperationToken; 155ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin if (operationToken != null) { 156ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin mOperationToken = null; 157ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin mKeyStore.abort(operationToken); 158ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 159ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin mSigning = false; 160ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin mKey = null; 161ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin appRandom = null; 162ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin mOperationToken = null; 163ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin mOperationHandle = 0; 164ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin mMessageStreamer = null; 165ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin mCachedException = null; 166ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 167ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 168ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin /** 169ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * Resets this cipher while preserving the initialized state. This must be equivalent to 170ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * rolling back the cipher's state to just after the most recent {@code engineInit} completed 171ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * successfully. 172ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * 173ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * <p>Subclasses storing additional post-init state should override this method, reset the 174ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * additional state, and then chain to superclass. 175ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin */ 176ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin @CallSuper 177ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin protected void resetWhilePreservingInitState() { 178ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin IBinder operationToken = mOperationToken; 179ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin if (operationToken != null) { 180ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin mOperationToken = null; 181ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin mKeyStore.abort(operationToken); 182ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 183ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin mOperationHandle = 0; 184ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin mMessageStreamer = null; 185ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin mCachedException = null; 186ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 187ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 188ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin private void ensureKeystoreOperationInitialized() throws InvalidKeyException { 189ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin if (mMessageStreamer != null) { 190ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin return; 191ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 192ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin if (mCachedException != null) { 193ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin return; 194ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 195ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin if (mKey == null) { 196ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin throw new IllegalStateException("Not initialized"); 197ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 198ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 199ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin KeymasterArguments keymasterInputArgs = new KeymasterArguments(); 200ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin addAlgorithmSpecificParametersToBegin(keymasterInputArgs); 201ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 202ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin OperationResult opResult = mKeyStore.begin( 203ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin mKey.getAlias(), 204ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin mSigning ? KeymasterDefs.KM_PURPOSE_SIGN : KeymasterDefs.KM_PURPOSE_VERIFY, 205ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin true, // permit aborting this operation if keystore runs out of resources 206ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin keymasterInputArgs, 2073876b1be27e3aefde9a72eb2e4f856e94fc5f946Alex Klyubin null, // no additional entropy for begin -- only finish might need some 2083876b1be27e3aefde9a72eb2e4f856e94fc5f946Alex Klyubin mKey.getUid()); 209ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin if (opResult == null) { 210ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin throw new KeyStoreConnectException(); 211ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 212ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 213ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin // Store operation token and handle regardless of the error code returned by KeyStore to 214ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin // ensure that the operation gets aborted immediately if the code below throws an exception. 215ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin mOperationToken = opResult.token; 216ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin mOperationHandle = opResult.operationHandle; 217ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 218ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin // If necessary, throw an exception due to KeyStore operation having failed. 219ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin InvalidKeyException e = KeyStoreCryptoOperationUtils.getInvalidKeyExceptionForInit( 220ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin mKeyStore, mKey, opResult.resultCode); 221ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin if (e != null) { 222ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin throw e; 223ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 224ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 225ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin if (mOperationToken == null) { 226ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin throw new ProviderException("Keystore returned null operation token"); 227ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 228ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin if (mOperationHandle == 0) { 229ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin throw new ProviderException("Keystore returned invalid operation handle"); 230ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 231ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 232d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin mMessageStreamer = createMainDataStreamer(mKeyStore, opResult.token); 233d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin } 234d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin 235d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin /** 236d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin * Creates a streamer which sends the message to be signed/verified into the provided KeyStore 237d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin * 238d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin * <p>This implementation returns a working streamer. 239d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin */ 240d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin @NonNull 241d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin protected KeyStoreCryptoOperationStreamer createMainDataStreamer( 242d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin KeyStore keyStore, IBinder operationToken) { 243d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin return new KeyStoreCryptoOperationChunkedStreamer( 244ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin new KeyStoreCryptoOperationChunkedStreamer.MainDataStream( 245d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin keyStore, operationToken)); 246ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 247ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 248ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin @Override 249ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin public final long getOperationHandle() { 250ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin return mOperationHandle; 251ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 252ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 253ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin @Override 254ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin protected final void engineUpdate(byte[] b, int off, int len) throws SignatureException { 255ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin if (mCachedException != null) { 256ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin throw new SignatureException(mCachedException); 257ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 258ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 259ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin try { 260ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin ensureKeystoreOperationInitialized(); 261ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } catch (InvalidKeyException e) { 262ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin throw new SignatureException(e); 263ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 264ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 265ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin if (len == 0) { 266ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin return; 267ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 268ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 269ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin byte[] output; 270ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin try { 271ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin output = mMessageStreamer.update(b, off, len); 272ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } catch (KeyStoreException e) { 273ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin throw new SignatureException(e); 274ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 275ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 276ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin if (output.length != 0) { 277ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin throw new ProviderException( 278ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin "Update operation unexpectedly produced output: " + output.length + " bytes"); 279ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 280ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 281ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 282ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin @Override 283ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin protected final void engineUpdate(byte b) throws SignatureException { 284ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin engineUpdate(new byte[] {b}, 0, 1); 285ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 286ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 287ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin @Override 288ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin protected final void engineUpdate(ByteBuffer input) { 289ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin byte[] b; 290ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin int off; 291ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin int len = input.remaining(); 292ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin if (input.hasArray()) { 293ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin b = input.array(); 294ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin off = input.arrayOffset() + input.position(); 295ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin input.position(input.limit()); 296ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } else { 297ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin b = new byte[len]; 298ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin off = 0; 299ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin input.get(b); 300ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 301ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 302ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin try { 303ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin engineUpdate(b, off, len); 304ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } catch (SignatureException e) { 305ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin mCachedException = e; 306ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 307ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 308ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 309ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin @Override 310ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin protected final int engineSign(byte[] out, int outOffset, int outLen) 311ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin throws SignatureException { 312ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin return super.engineSign(out, outOffset, outLen); 313ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 314ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 315ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin @Override 316ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin protected final byte[] engineSign() throws SignatureException { 317ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin if (mCachedException != null) { 318ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin throw new SignatureException(mCachedException); 319ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 320ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 321ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin byte[] signature; 322ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin try { 323ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin ensureKeystoreOperationInitialized(); 324a72b55195c23fc06d1600efe8f6aac85290c7f8fAlex Klyubin 325a72b55195c23fc06d1600efe8f6aac85290c7f8fAlex Klyubin byte[] additionalEntropy = 326a72b55195c23fc06d1600efe8f6aac85290c7f8fAlex Klyubin KeyStoreCryptoOperationUtils.getRandomBytesToMixIntoKeystoreRng( 327a72b55195c23fc06d1600efe8f6aac85290c7f8fAlex Klyubin appRandom, getAdditionalEntropyAmountForSign()); 328d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin signature = mMessageStreamer.doFinal( 329d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin EmptyArray.BYTE, 0, 0, 330d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin null, // no signature provided -- it'll be generated by this invocation 331d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin additionalEntropy); 332ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } catch (InvalidKeyException | KeyStoreException e) { 333ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin throw new SignatureException(e); 334ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 335ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 336ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin resetWhilePreservingInitState(); 337ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin return signature; 338ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 339ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 340ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin @Override 341ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin protected final boolean engineVerify(byte[] signature) throws SignatureException { 342ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin if (mCachedException != null) { 343ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin throw new SignatureException(mCachedException); 344ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 345ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 346ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin try { 347ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin ensureKeystoreOperationInitialized(); 348d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin } catch (InvalidKeyException e) { 349d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin throw new SignatureException(e); 350d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin } 351d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin 352d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin boolean verified; 353d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin try { 354d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin byte[] output = mMessageStreamer.doFinal( 355d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin EmptyArray.BYTE, 0, 0, 356d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin signature, 357d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin null // no additional entropy needed -- verification is deterministic 358d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin ); 359d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin if (output.length != 0) { 360d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin throw new ProviderException( 361d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin "Signature verification unexpected produced output: " + output.length 362d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin + " bytes"); 363ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 364d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin verified = true; 365d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin } catch (KeyStoreException e) { 366d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin switch (e.getErrorCode()) { 367ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin case KeymasterDefs.KM_ERROR_VERIFICATION_FAILED: 368d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin verified = false; 369ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin break; 370ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin default: 371d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin throw new SignatureException(e); 372ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 373ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 374ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 375ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin resetWhilePreservingInitState(); 376d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin return verified; 377ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 378ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 379ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin @Override 380ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin protected final boolean engineVerify(byte[] sigBytes, int offset, int len) 381ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin throws SignatureException { 382ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin return engineVerify(ArrayUtils.subarray(sigBytes, offset, len)); 383ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 384ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 385ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin @Deprecated 386ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin @Override 387ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin protected final Object engineGetParameter(String param) throws InvalidParameterException { 388ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin throw new InvalidParameterException(); 389ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 390ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 391ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin @Deprecated 392ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin @Override 393ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin protected final void engineSetParameter(String param, Object value) 394ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin throws InvalidParameterException { 395ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin throw new InvalidParameterException(); 396ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 397ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 398ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin protected final KeyStore getKeyStore() { 399ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin return mKeyStore; 400ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 401ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 402ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin /** 403ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * Returns {@code true} if this signature is initialized for signing, {@code false} if this 404ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * signature is initialized for verification. 405ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin */ 406ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin protected final boolean isSigning() { 407ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin return mSigning; 408ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin } 409ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 410ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin // The methods below need to be implemented by subclasses. 411ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 412ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin /** 413ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * Returns the amount of additional entropy (in bytes) to be provided to the KeyStore's 414a72b55195c23fc06d1600efe8f6aac85290c7f8fAlex Klyubin * {@code finish} operation when generating a signature. 415ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * 416a72b55195c23fc06d1600efe8f6aac85290c7f8fAlex Klyubin * <p>This value should match (or exceed) the amount of Shannon entropy of the produced 417a72b55195c23fc06d1600efe8f6aac85290c7f8fAlex Klyubin * signature assuming the key and the message are known. For example, for ECDSA signature this 418a72b55195c23fc06d1600efe8f6aac85290c7f8fAlex Klyubin * should be the size of {@code R}, whereas for the RSA signature with PKCS#1 padding this 419a72b55195c23fc06d1600efe8f6aac85290c7f8fAlex Klyubin * should be {@code 0}. 420ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin */ 421a72b55195c23fc06d1600efe8f6aac85290c7f8fAlex Klyubin protected abstract int getAdditionalEntropyAmountForSign(); 422ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin 423ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin /** 424ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * Invoked to add algorithm-specific parameters for the KeyStore's {@code begin} operation. 425ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * 426ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * @param keymasterArgs keystore/keymaster arguments to be populated with algorithm-specific 427ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * parameters. 428ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin */ 429ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin protected abstract void addAlgorithmSpecificParametersToBegin( 430ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin @NonNull KeymasterArguments keymasterArgs); 431ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin} 432