AndroidKeyStoreHmacSpi.java revision 058de02073a129301d391c22b050f2d65adadb0f
1cc21bb3a56915842b545a577d3481047005b1764Alex Klyubin/* 2cc21bb3a56915842b545a577d3481047005b1764Alex Klyubin * Copyright (C) 2015 The Android Open Source Project 3cc21bb3a56915842b545a577d3481047005b1764Alex Klyubin * 4cc21bb3a56915842b545a577d3481047005b1764Alex Klyubin * Licensed under the Apache License, Version 2.0 (the "License"); 5cc21bb3a56915842b545a577d3481047005b1764Alex Klyubin * you may not use this file except in compliance with the License. 6cc21bb3a56915842b545a577d3481047005b1764Alex Klyubin * You may obtain a copy of the License at 7cc21bb3a56915842b545a577d3481047005b1764Alex Klyubin * 8cc21bb3a56915842b545a577d3481047005b1764Alex Klyubin * http://www.apache.org/licenses/LICENSE-2.0 9cc21bb3a56915842b545a577d3481047005b1764Alex Klyubin * 10cc21bb3a56915842b545a577d3481047005b1764Alex Klyubin * Unless required by applicable law or agreed to in writing, software 11cc21bb3a56915842b545a577d3481047005b1764Alex Klyubin * distributed under the License is distributed on an "AS IS" BASIS, 12cc21bb3a56915842b545a577d3481047005b1764Alex Klyubin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13cc21bb3a56915842b545a577d3481047005b1764Alex Klyubin * See the License for the specific language governing permissions and 14cc21bb3a56915842b545a577d3481047005b1764Alex Klyubin * limitations under the License. 15cc21bb3a56915842b545a577d3481047005b1764Alex Klyubin */ 16cc21bb3a56915842b545a577d3481047005b1764Alex Klyubin 174ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubinpackage android.security; 184ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin 194ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubinimport android.os.IBinder; 204ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubinimport android.security.keymaster.KeymasterArguments; 214ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubinimport android.security.keymaster.KeymasterDefs; 224ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubinimport android.security.keymaster.OperationResult; 234ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin 244ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubinimport java.security.InvalidAlgorithmParameterException; 254ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubinimport java.security.InvalidKeyException; 264ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubinimport java.security.Key; 274ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubinimport java.security.spec.AlgorithmParameterSpec; 284ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin 294ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubinimport javax.crypto.MacSpi; 304ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin 314ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin/** 324ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin * {@link MacSpi} which provides HMAC implementations backed by Android KeyStore. 334ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin * 344ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin * @hide 354ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin */ 3652886ca77d4d93f6faf5d2a6836625a421e32403Alex Klyubinpublic abstract class KeyStoreHmacSpi extends MacSpi implements KeyStoreCryptoOperation { 374ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin 3870376a77280551791dae62586a6bb0c77ed9429aAlex Klyubin public static class HmacSHA1 extends KeyStoreHmacSpi { 3970376a77280551791dae62586a6bb0c77ed9429aAlex Klyubin public HmacSHA1() { 405927c9f1b12f597839a664c1c6593114175cbcd8Alex Klyubin super(KeymasterDefs.KM_DIGEST_SHA1); 4170376a77280551791dae62586a6bb0c77ed9429aAlex Klyubin } 4270376a77280551791dae62586a6bb0c77ed9429aAlex Klyubin } 4370376a77280551791dae62586a6bb0c77ed9429aAlex Klyubin 4470376a77280551791dae62586a6bb0c77ed9429aAlex Klyubin public static class HmacSHA224 extends KeyStoreHmacSpi { 4570376a77280551791dae62586a6bb0c77ed9429aAlex Klyubin public HmacSHA224() { 465927c9f1b12f597839a664c1c6593114175cbcd8Alex Klyubin super(KeymasterDefs.KM_DIGEST_SHA_2_224); 4770376a77280551791dae62586a6bb0c77ed9429aAlex Klyubin } 4870376a77280551791dae62586a6bb0c77ed9429aAlex Klyubin } 4970376a77280551791dae62586a6bb0c77ed9429aAlex Klyubin 504ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin public static class HmacSHA256 extends KeyStoreHmacSpi { 514ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin public HmacSHA256() { 525927c9f1b12f597839a664c1c6593114175cbcd8Alex Klyubin super(KeymasterDefs.KM_DIGEST_SHA_2_256); 5370376a77280551791dae62586a6bb0c77ed9429aAlex Klyubin } 5470376a77280551791dae62586a6bb0c77ed9429aAlex Klyubin } 5570376a77280551791dae62586a6bb0c77ed9429aAlex Klyubin 5670376a77280551791dae62586a6bb0c77ed9429aAlex Klyubin public static class HmacSHA384 extends KeyStoreHmacSpi { 5770376a77280551791dae62586a6bb0c77ed9429aAlex Klyubin public HmacSHA384() { 585927c9f1b12f597839a664c1c6593114175cbcd8Alex Klyubin super(KeymasterDefs.KM_DIGEST_SHA_2_384); 5970376a77280551791dae62586a6bb0c77ed9429aAlex Klyubin } 6070376a77280551791dae62586a6bb0c77ed9429aAlex Klyubin } 6170376a77280551791dae62586a6bb0c77ed9429aAlex Klyubin 6270376a77280551791dae62586a6bb0c77ed9429aAlex Klyubin public static class HmacSHA512 extends KeyStoreHmacSpi { 6370376a77280551791dae62586a6bb0c77ed9429aAlex Klyubin public HmacSHA512() { 645927c9f1b12f597839a664c1c6593114175cbcd8Alex Klyubin super(KeymasterDefs.KM_DIGEST_SHA_2_512); 654ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin } 664ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin } 674ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin 684ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin private final KeyStore mKeyStore = KeyStore.getInstance(); 695927c9f1b12f597839a664c1c6593114175cbcd8Alex Klyubin private final int mKeymasterDigest; 704ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin private final int mMacSizeBytes; 714ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin 726c4a842129db70a9d50b9c0a38cda107ddb943ddAlex Klyubin // Fields below are populated by engineInit and should be preserved after engineDoFinal. 736c4a842129db70a9d50b9c0a38cda107ddb943ddAlex Klyubin private KeyStoreSecretKey mKey; 744ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin 756c4a842129db70a9d50b9c0a38cda107ddb943ddAlex Klyubin // Fields below are reset when engineDoFinal succeeds. 764ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin private KeyStoreCryptoOperationChunkedStreamer mChunkedStreamer; 774ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin private IBinder mOperationToken; 7852886ca77d4d93f6faf5d2a6836625a421e32403Alex Klyubin private Long mOperationHandle; 794ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin 805927c9f1b12f597839a664c1c6593114175cbcd8Alex Klyubin protected KeyStoreHmacSpi(int keymasterDigest) { 815927c9f1b12f597839a664c1c6593114175cbcd8Alex Klyubin mKeymasterDigest = keymasterDigest; 825927c9f1b12f597839a664c1c6593114175cbcd8Alex Klyubin mMacSizeBytes = KeymasterUtils.getDigestOutputSizeBytes(keymasterDigest); 834ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin } 844ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin 854ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin @Override 864ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin protected int engineGetMacLength() { 874ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin return mMacSizeBytes; 884ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin } 894ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin 904ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin @Override 914ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin protected void engineInit(Key key, AlgorithmParameterSpec params) throws InvalidKeyException, 924ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin InvalidAlgorithmParameterException { 936c4a842129db70a9d50b9c0a38cda107ddb943ddAlex Klyubin resetAll(); 946c4a842129db70a9d50b9c0a38cda107ddb943ddAlex Klyubin 956c4a842129db70a9d50b9c0a38cda107ddb943ddAlex Klyubin boolean success = false; 966c4a842129db70a9d50b9c0a38cda107ddb943ddAlex Klyubin try { 976c4a842129db70a9d50b9c0a38cda107ddb943ddAlex Klyubin init(key, params); 986c4a842129db70a9d50b9c0a38cda107ddb943ddAlex Klyubin ensureKeystoreOperationInitialized(); 996c4a842129db70a9d50b9c0a38cda107ddb943ddAlex Klyubin success = true; 1006c4a842129db70a9d50b9c0a38cda107ddb943ddAlex Klyubin } finally { 1016c4a842129db70a9d50b9c0a38cda107ddb943ddAlex Klyubin if (!success) { 1026c4a842129db70a9d50b9c0a38cda107ddb943ddAlex Klyubin resetAll(); 1036c4a842129db70a9d50b9c0a38cda107ddb943ddAlex Klyubin } 1046c4a842129db70a9d50b9c0a38cda107ddb943ddAlex Klyubin } 1056c4a842129db70a9d50b9c0a38cda107ddb943ddAlex Klyubin } 1066c4a842129db70a9d50b9c0a38cda107ddb943ddAlex Klyubin 1076c4a842129db70a9d50b9c0a38cda107ddb943ddAlex Klyubin private void init(Key key, AlgorithmParameterSpec params) throws InvalidKeyException, 1086c4a842129db70a9d50b9c0a38cda107ddb943ddAlex Klyubin InvalidAlgorithmParameterException { 1094ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin if (key == null) { 1104ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin throw new InvalidKeyException("key == null"); 1114ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin } else if (!(key instanceof KeyStoreSecretKey)) { 1124ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin throw new InvalidKeyException( 1134ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin "Only Android KeyStore secret keys supported. Key: " + key); 1144ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin } 1156c4a842129db70a9d50b9c0a38cda107ddb943ddAlex Klyubin mKey = (KeyStoreSecretKey) key; 1164ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin 1174ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin if (params != null) { 1184ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin throw new InvalidAlgorithmParameterException( 1194ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin "Unsupported algorithm parameters: " + params); 1204ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin } 1214ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin 1226c4a842129db70a9d50b9c0a38cda107ddb943ddAlex Klyubin } 1236c4a842129db70a9d50b9c0a38cda107ddb943ddAlex Klyubin 1246c4a842129db70a9d50b9c0a38cda107ddb943ddAlex Klyubin private void resetAll() { 1256c4a842129db70a9d50b9c0a38cda107ddb943ddAlex Klyubin mKey = null; 1266c4a842129db70a9d50b9c0a38cda107ddb943ddAlex Klyubin IBinder operationToken = mOperationToken; 1276c4a842129db70a9d50b9c0a38cda107ddb943ddAlex Klyubin if (operationToken != null) { 1286c4a842129db70a9d50b9c0a38cda107ddb943ddAlex Klyubin mOperationToken = null; 1296c4a842129db70a9d50b9c0a38cda107ddb943ddAlex Klyubin mKeyStore.abort(operationToken); 130a80eee052dd729c2898829fab42a5584d6f5eaf0Alex Klyubin } 1316c4a842129db70a9d50b9c0a38cda107ddb943ddAlex Klyubin mOperationHandle = null; 1326c4a842129db70a9d50b9c0a38cda107ddb943ddAlex Klyubin mChunkedStreamer = null; 1334ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin } 1344ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin 1356c4a842129db70a9d50b9c0a38cda107ddb943ddAlex Klyubin private void resetWhilePreservingInitState() { 1364ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin IBinder operationToken = mOperationToken; 1374ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin if (operationToken != null) { 1384ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin mOperationToken = null; 1394ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin mKeyStore.abort(operationToken); 1404ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin } 14152886ca77d4d93f6faf5d2a6836625a421e32403Alex Klyubin mOperationHandle = null; 1424ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin mChunkedStreamer = null; 143a80eee052dd729c2898829fab42a5584d6f5eaf0Alex Klyubin } 144a80eee052dd729c2898829fab42a5584d6f5eaf0Alex Klyubin 1456c4a842129db70a9d50b9c0a38cda107ddb943ddAlex Klyubin @Override 1466c4a842129db70a9d50b9c0a38cda107ddb943ddAlex Klyubin protected void engineReset() { 1476c4a842129db70a9d50b9c0a38cda107ddb943ddAlex Klyubin resetWhilePreservingInitState(); 1486c4a842129db70a9d50b9c0a38cda107ddb943ddAlex Klyubin } 1496c4a842129db70a9d50b9c0a38cda107ddb943ddAlex Klyubin 150ad9ba10ecda10c14e46d00f40fc3e431cc2d9bc2Alex Klyubin private void ensureKeystoreOperationInitialized() throws InvalidKeyException { 151a80eee052dd729c2898829fab42a5584d6f5eaf0Alex Klyubin if (mChunkedStreamer != null) { 152a80eee052dd729c2898829fab42a5584d6f5eaf0Alex Klyubin return; 153a80eee052dd729c2898829fab42a5584d6f5eaf0Alex Klyubin } 1546c4a842129db70a9d50b9c0a38cda107ddb943ddAlex Klyubin if (mKey == null) { 155a80eee052dd729c2898829fab42a5584d6f5eaf0Alex Klyubin throw new IllegalStateException("Not initialized"); 156a80eee052dd729c2898829fab42a5584d6f5eaf0Alex Klyubin } 1574ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin 1584ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin KeymasterArguments keymasterArgs = new KeymasterArguments(); 1595927c9f1b12f597839a664c1c6593114175cbcd8Alex Klyubin keymasterArgs.addInt(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_HMAC); 1605927c9f1b12f597839a664c1c6593114175cbcd8Alex Klyubin keymasterArgs.addInt(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigest); 1614ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin 1626c4a842129db70a9d50b9c0a38cda107ddb943ddAlex Klyubin OperationResult opResult = mKeyStore.begin( 1636c4a842129db70a9d50b9c0a38cda107ddb943ddAlex Klyubin mKey.getAlias(), 1644ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin KeymasterDefs.KM_PURPOSE_SIGN, 1654ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin true, 1664ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin keymasterArgs, 1674ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin null, 1684ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin new KeymasterArguments()); 1694ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin if (opResult == null) { 1704ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin throw new KeyStoreConnectException(); 171058de02073a129301d391c22b050f2d65adadb0fAlex Klyubin } else if ((opResult.resultCode != KeyStore.NO_ERROR) 172058de02073a129301d391c22b050f2d65adadb0fAlex Klyubin && (opResult.resultCode != KeyStore.OP_AUTH_NEEDED)) { 173708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin throw mKeyStore.getInvalidKeyException(mKey.getAlias(), opResult.resultCode); 1744ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin } 175058de02073a129301d391c22b050f2d65adadb0fAlex Klyubin 176a80eee052dd729c2898829fab42a5584d6f5eaf0Alex Klyubin if (opResult.token == null) { 177ad9ba10ecda10c14e46d00f40fc3e431cc2d9bc2Alex Klyubin throw new IllegalStateException("Keystore returned null operation token"); 1784ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin } 179058de02073a129301d391c22b050f2d65adadb0fAlex Klyubin // The operation handle/token is now either valid for use immediately or needs to be 180058de02073a129301d391c22b050f2d65adadb0fAlex Klyubin // authorized through user authentication (if the error code was OP_AUTH_NEEDED). 181a80eee052dd729c2898829fab42a5584d6f5eaf0Alex Klyubin mOperationToken = opResult.token; 18252886ca77d4d93f6faf5d2a6836625a421e32403Alex Klyubin mOperationHandle = opResult.operationHandle; 1834ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin mChunkedStreamer = new KeyStoreCryptoOperationChunkedStreamer( 184b406f242911fa4d910a4cf915a61e39aeace1e1bAlex Klyubin new KeyStoreCryptoOperationChunkedStreamer.MainDataStream( 185b406f242911fa4d910a4cf915a61e39aeace1e1bAlex Klyubin mKeyStore, mOperationToken)); 1864ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin } 1874ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin 1884ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin @Override 1894ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin protected void engineUpdate(byte input) { 1904ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin engineUpdate(new byte[] {input}, 0, 1); 1914ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin } 1924ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin 1934ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin @Override 1944ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin protected void engineUpdate(byte[] input, int offset, int len) { 195ad9ba10ecda10c14e46d00f40fc3e431cc2d9bc2Alex Klyubin try { 196ad9ba10ecda10c14e46d00f40fc3e431cc2d9bc2Alex Klyubin ensureKeystoreOperationInitialized(); 197ad9ba10ecda10c14e46d00f40fc3e431cc2d9bc2Alex Klyubin } catch (InvalidKeyException e) { 198ad9ba10ecda10c14e46d00f40fc3e431cc2d9bc2Alex Klyubin throw new IllegalStateException("Failed to reinitialize MAC", e); 199ad9ba10ecda10c14e46d00f40fc3e431cc2d9bc2Alex Klyubin } 2004ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin 2014ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin byte[] output; 2024ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin try { 2034ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin output = mChunkedStreamer.update(input, offset, len); 204b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin } catch (KeyStoreException e) { 205ad9ba10ecda10c14e46d00f40fc3e431cc2d9bc2Alex Klyubin throw new IllegalStateException("Keystore operation failed", e); 2064ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin } 2074ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin if ((output != null) && (output.length != 0)) { 208ad9ba10ecda10c14e46d00f40fc3e431cc2d9bc2Alex Klyubin throw new IllegalStateException("Update operation unexpectedly produced output"); 2094ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin } 2104ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin } 2114ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin 2124ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin @Override 2134ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin protected byte[] engineDoFinal() { 214ad9ba10ecda10c14e46d00f40fc3e431cc2d9bc2Alex Klyubin try { 215ad9ba10ecda10c14e46d00f40fc3e431cc2d9bc2Alex Klyubin ensureKeystoreOperationInitialized(); 216ad9ba10ecda10c14e46d00f40fc3e431cc2d9bc2Alex Klyubin } catch (InvalidKeyException e) { 217ad9ba10ecda10c14e46d00f40fc3e431cc2d9bc2Alex Klyubin throw new IllegalStateException("Failed to reinitialize MAC", e); 218ad9ba10ecda10c14e46d00f40fc3e431cc2d9bc2Alex Klyubin } 2194ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin 2204ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin byte[] result; 2214ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin try { 2224ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin result = mChunkedStreamer.doFinal(null, 0, 0); 223b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin } catch (KeyStoreException e) { 224ad9ba10ecda10c14e46d00f40fc3e431cc2d9bc2Alex Klyubin throw new IllegalStateException("Keystore operation failed", e); 2254ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin } 2264ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin 2276c4a842129db70a9d50b9c0a38cda107ddb943ddAlex Klyubin resetWhilePreservingInitState(); 2284ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin return result; 2294ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin } 2304ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin 2314ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin @Override 2324ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin public void finalize() throws Throwable { 2334ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin try { 2344ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin IBinder operationToken = mOperationToken; 2354ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin if (operationToken != null) { 2364ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin mKeyStore.abort(operationToken); 2374ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin } 2384ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin } finally { 2394ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin super.finalize(); 2404ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin } 2414ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin } 24252886ca77d4d93f6faf5d2a6836625a421e32403Alex Klyubin 24352886ca77d4d93f6faf5d2a6836625a421e32403Alex Klyubin @Override 24452886ca77d4d93f6faf5d2a6836625a421e32403Alex Klyubin public Long getOperationHandle() { 24552886ca77d4d93f6faf5d2a6836625a421e32403Alex Klyubin return mOperationHandle; 24652886ca77d4d93f6faf5d2a6836625a421e32403Alex Klyubin } 2474ab8ea4498aa25eafdbaadd238fed6eab3f6ee59Alex Klyubin} 248