100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin/*
200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin * Copyright (C) 2015 The Android Open Source Project
300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin *
400af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin * Licensed under the Apache License, Version 2.0 (the "License");
500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin * you may not use this file except in compliance with the License.
600af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin * You may obtain a copy of the License at
700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin *
800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin *      http://www.apache.org/licenses/LICENSE-2.0
900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin *
1000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin * Unless required by applicable law or agreed to in writing, software
1100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin * distributed under the License is distributed on an "AS IS" BASIS,
1200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin * See the License for the specific language governing permissions and
1400af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin * limitations under the License.
1500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin */
1600af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
1700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubinpackage android.security.keystore;
1800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
1900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubinimport android.annotation.NonNull;
2000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubinimport android.annotation.Nullable;
2100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubinimport android.os.IBinder;
2200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubinimport android.security.KeyStore;
2300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubinimport android.security.KeyStoreException;
2400af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubinimport android.security.keymaster.KeymasterArguments;
2500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubinimport android.security.keymaster.KeymasterDefs;
2600af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubinimport android.security.keymaster.OperationResult;
2700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubinimport android.security.keystore.KeyStoreCryptoOperationChunkedStreamer.Stream;
2800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
2900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubinimport libcore.util.EmptyArray;
3000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
3100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubinimport java.io.ByteArrayOutputStream;
3200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubinimport java.io.IOException;
3300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubinimport java.security.AlgorithmParameters;
3400af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubinimport java.security.InvalidAlgorithmParameterException;
3500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubinimport java.security.InvalidKeyException;
3600af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubinimport java.security.Key;
3700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubinimport java.security.NoSuchAlgorithmException;
3800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubinimport java.security.ProviderException;
3900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubinimport java.security.spec.AlgorithmParameterSpec;
4000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubinimport java.security.spec.InvalidParameterSpecException;
4100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubinimport java.util.Arrays;
4200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
4300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubinimport javax.crypto.CipherSpi;
4400af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubinimport javax.crypto.spec.GCMParameterSpec;
4500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
4600af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin/**
4700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin * Base class for Android Keystore authenticated AES {@link CipherSpi} implementations.
4800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin *
4900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin * @hide
5000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin */
5100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubinabstract class AndroidKeyStoreAuthenticatedAESCipherSpi extends AndroidKeyStoreCipherSpiBase {
5200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
5300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin    abstract static class GCM extends AndroidKeyStoreAuthenticatedAESCipherSpi {
54a95550f8016bbb0dba086dbd73eec63e6cdbbe98Alex Klyubin        static final int MIN_SUPPORTED_TAG_LENGTH_BITS = 96;
5500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        private static final int MAX_SUPPORTED_TAG_LENGTH_BITS = 128;
5600af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        private static final int DEFAULT_TAG_LENGTH_BITS = 128;
5700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        private static final int IV_LENGTH_BYTES = 12;
5800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
5900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        private int mTagLengthBits = DEFAULT_TAG_LENGTH_BITS;
6000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
6100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        GCM(int keymasterPadding) {
6200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            super(KeymasterDefs.KM_MODE_GCM, keymasterPadding);
6300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        }
6400af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
6500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        @Override
6600af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        protected final void resetAll() {
6700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            mTagLengthBits = DEFAULT_TAG_LENGTH_BITS;
6800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            super.resetAll();
6900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        }
7000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
7100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        @Override
7200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        protected final void resetWhilePreservingInitState() {
7300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            super.resetWhilePreservingInitState();
7400af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        }
7500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
7600af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        @Override
7700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        protected final void initAlgorithmSpecificParameters() throws InvalidKeyException {
7800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            if (!isEncrypting()) {
7900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                throw new InvalidKeyException("IV required when decrypting"
8000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                        + ". Use IvParameterSpec or AlgorithmParameters to provide it.");
8100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            }
8200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        }
8300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
8400af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        @Override
8500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        protected final void initAlgorithmSpecificParameters(AlgorithmParameterSpec params)
8600af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                throws InvalidAlgorithmParameterException {
8700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            // IV is used
8800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            if (params == null) {
8900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                if (!isEncrypting()) {
9000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                    // IV must be provided by the caller
9100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                    throw new InvalidAlgorithmParameterException(
9200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                            "GCMParameterSpec must be provided when decrypting");
9300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                }
9400af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                return;
9500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            }
9600af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            if (!(params instanceof GCMParameterSpec)) {
9700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                throw new InvalidAlgorithmParameterException("Only GCMParameterSpec supported");
9800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            }
9900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            GCMParameterSpec spec = (GCMParameterSpec) params;
10000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            byte[] iv = spec.getIV();
10100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            if (iv == null) {
10200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                throw new InvalidAlgorithmParameterException("Null IV in GCMParameterSpec");
10300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            } else if (iv.length != IV_LENGTH_BYTES) {
10400af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                throw new InvalidAlgorithmParameterException("Unsupported IV length: "
10500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                        + iv.length + " bytes. Only " + IV_LENGTH_BYTES
10600af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                        + " bytes long IV supported");
10700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            }
10800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            int tagLengthBits = spec.getTLen();
10900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            if ((tagLengthBits < MIN_SUPPORTED_TAG_LENGTH_BITS)
11000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                    || (tagLengthBits > MAX_SUPPORTED_TAG_LENGTH_BITS)
11100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                    || ((tagLengthBits % 8) != 0)) {
11200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                throw new InvalidAlgorithmParameterException(
11300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                        "Unsupported tag length: " + tagLengthBits + " bits"
11400af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                        + ". Supported lengths: 96, 104, 112, 120, 128");
11500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            }
11600af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            setIv(iv);
11700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            mTagLengthBits = tagLengthBits;
11800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        }
11900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
12000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        @Override
12100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        protected final void initAlgorithmSpecificParameters(AlgorithmParameters params)
12200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                throws InvalidAlgorithmParameterException {
12300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            if (params == null) {
12400af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                if (!isEncrypting()) {
12500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                    // IV must be provided by the caller
12600af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                    throw new InvalidAlgorithmParameterException("IV required when decrypting"
12700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                            + ". Use GCMParameterSpec or GCM AlgorithmParameters to provide it.");
12800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                }
12900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                return;
13000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            }
13100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
1325c38e7918aea36ee8f516793d5641b05a8de710eAlex Klyubin            if (!"GCM".equalsIgnoreCase(params.getAlgorithm())) {
1335c38e7918aea36ee8f516793d5641b05a8de710eAlex Klyubin                throw new InvalidAlgorithmParameterException(
1345c38e7918aea36ee8f516793d5641b05a8de710eAlex Klyubin                        "Unsupported AlgorithmParameters algorithm: " + params.getAlgorithm()
1355c38e7918aea36ee8f516793d5641b05a8de710eAlex Klyubin                        + ". Supported: GCM");
1365c38e7918aea36ee8f516793d5641b05a8de710eAlex Klyubin            }
1375c38e7918aea36ee8f516793d5641b05a8de710eAlex Klyubin
13800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            GCMParameterSpec spec;
13900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            try {
14000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                spec = params.getParameterSpec(GCMParameterSpec.class);
14100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            } catch (InvalidParameterSpecException e) {
14200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                if (!isEncrypting()) {
14300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                    // IV must be provided by the caller
14400af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                    throw new InvalidAlgorithmParameterException("IV and tag length required when"
14500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                            + " decrypting, but not found in parameters: " + params, e);
14600af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                }
14700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                setIv(null);
14800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                return;
14900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            }
15000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            initAlgorithmSpecificParameters(spec);
15100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        }
15200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
15300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        @Nullable
15400af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        @Override
15500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        protected final AlgorithmParameters engineGetParameters() {
15600af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            byte[] iv = getIv();
15700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            if ((iv != null) && (iv.length > 0)) {
15800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                try {
15900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                    AlgorithmParameters params = AlgorithmParameters.getInstance("GCM");
16000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                    params.init(new GCMParameterSpec(mTagLengthBits, iv));
16100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                    return params;
16200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                } catch (NoSuchAlgorithmException e) {
16300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                    throw new ProviderException(
16400af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                            "Failed to obtain GCM AlgorithmParameters", e);
16500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                } catch (InvalidParameterSpecException e) {
16600af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                    throw new ProviderException(
16700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                            "Failed to initialize GCM AlgorithmParameters", e);
16800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                }
16900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            }
17000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            return null;
17100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        }
17200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
17300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        @NonNull
17400af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        @Override
17500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        protected KeyStoreCryptoOperationStreamer createMainDataStreamer(
17600af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                KeyStore keyStore, IBinder operationToken) {
17700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            KeyStoreCryptoOperationStreamer streamer = new KeyStoreCryptoOperationChunkedStreamer(
17800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                    new KeyStoreCryptoOperationChunkedStreamer.MainDataStream(
17900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                            keyStore, operationToken));
18000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            if (isEncrypting()) {
18100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                return streamer;
18200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            } else {
18300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                // When decrypting, to avoid leaking unauthenticated plaintext, do not return any
18400af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                // plaintext before ciphertext is authenticated by KeyStore.finish.
18500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                return new BufferAllOutputUntilDoFinalStreamer(streamer);
18600af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            }
18700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        }
18800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
18900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        @NonNull
19000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        @Override
19100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        protected final KeyStoreCryptoOperationStreamer createAdditionalAuthenticationDataStreamer(
19200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                KeyStore keyStore, IBinder operationToken) {
19300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            return new KeyStoreCryptoOperationChunkedStreamer(
19400af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                    new AdditionalAuthenticationDataStream(keyStore, operationToken));
19500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        }
19600af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
19700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        @Override
19800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        protected final int getAdditionalEntropyAmountForBegin() {
19900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            if ((getIv() == null) && (isEncrypting())) {
20000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                // IV will need to be generated
20100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                return IV_LENGTH_BYTES;
20200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            }
20300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
20400af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            return 0;
20500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        }
20600af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
20700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        @Override
20800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        protected final int getAdditionalEntropyAmountForFinish() {
20900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            return 0;
21000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        }
21100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
21200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        @Override
21300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        protected final void addAlgorithmSpecificParametersToBegin(
21400af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                @NonNull KeymasterArguments keymasterArgs) {
21500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            super.addAlgorithmSpecificParametersToBegin(keymasterArgs);
216ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin            keymasterArgs.addUnsignedInt(KeymasterDefs.KM_TAG_MAC_LENGTH, mTagLengthBits);
21700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        }
21800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
21900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        protected final int getTagLengthBits() {
22000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            return mTagLengthBits;
22100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        }
22200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
22300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        public static final class NoPadding extends GCM {
22400af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            public NoPadding() {
22500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                super(KeymasterDefs.KM_PAD_NONE);
22600af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            }
22700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
22800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            @Override
22900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            protected final int engineGetOutputSize(int inputLen) {
23000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                int tagLengthBytes = (getTagLengthBits() + 7) / 8;
23100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                long result;
23200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                if (isEncrypting()) {
23300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                    result = getConsumedInputSizeBytes() - getProducedOutputSizeBytes() + inputLen
23400af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                            + tagLengthBytes;
23500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                } else {
23600af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                    result = getConsumedInputSizeBytes() - getProducedOutputSizeBytes() + inputLen
23700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                            - tagLengthBytes;
23800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                }
23900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                if (result < 0) {
24000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                    return 0;
24100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                } else if (result > Integer.MAX_VALUE) {
24200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                    return Integer.MAX_VALUE;
24300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                }
24400af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                return (int) result;
24500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            }
24600af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        }
24700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin    }
24800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
24900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin    private static final int BLOCK_SIZE_BYTES = 16;
25000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
25100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin    private final int mKeymasterBlockMode;
25200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin    private final int mKeymasterPadding;
25300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
25400af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin    private byte[] mIv;
25500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
25600af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin    /** Whether the current {@code #mIv} has been used by the underlying crypto operation. */
25700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin    private boolean mIvHasBeenUsed;
25800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
25900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin    AndroidKeyStoreAuthenticatedAESCipherSpi(
26000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            int keymasterBlockMode,
26100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            int keymasterPadding) {
26200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        mKeymasterBlockMode = keymasterBlockMode;
26300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        mKeymasterPadding = keymasterPadding;
26400af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin    }
26500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
26600af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin    @Override
26700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin    protected void resetAll() {
26800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        mIv = null;
26900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        mIvHasBeenUsed = false;
27000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        super.resetAll();
27100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin    }
27200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
27300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin    @Override
27400af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin    protected final void initKey(int opmode, Key key) throws InvalidKeyException {
27500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        if (!(key instanceof AndroidKeyStoreSecretKey)) {
27600af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            throw new InvalidKeyException(
27700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                    "Unsupported key: " + ((key != null) ? key.getClass().getName() : "null"));
27800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        }
27900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        if (!KeyProperties.KEY_ALGORITHM_AES.equalsIgnoreCase(key.getAlgorithm())) {
28000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            throw new InvalidKeyException(
28100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                    "Unsupported key algorithm: " + key.getAlgorithm() + ". Only " +
28200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                    KeyProperties.KEY_ALGORITHM_AES + " supported");
28300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        }
28400af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        setKey((AndroidKeyStoreSecretKey) key);
28500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin    }
28600af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
28700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin    @Override
28800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin    protected void addAlgorithmSpecificParametersToBegin(
28900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            @NonNull KeymasterArguments keymasterArgs) {
29000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        if ((isEncrypting()) && (mIvHasBeenUsed)) {
29100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            // IV is being reused for encryption: this violates security best practices.
29200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            throw new IllegalStateException(
29300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                    "IV has already been used. Reusing IV in encryption mode violates security best"
29400af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                    + " practices.");
29500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        }
29600af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
297ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin        keymasterArgs.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_AES);
298ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin        keymasterArgs.addEnum(KeymasterDefs.KM_TAG_BLOCK_MODE, mKeymasterBlockMode);
299ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin        keymasterArgs.addEnum(KeymasterDefs.KM_TAG_PADDING, mKeymasterPadding);
30000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        if (mIv != null) {
301ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin            keymasterArgs.addBytes(KeymasterDefs.KM_TAG_NONCE, mIv);
30200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        }
30300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin    }
30400af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
30500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin    @Override
30600af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin    protected final void loadAlgorithmSpecificParametersFromBeginResult(
30700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            @NonNull KeymasterArguments keymasterArgs) {
30800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        mIvHasBeenUsed = true;
30900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
31000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        // NOTE: Keymaster doesn't always return an IV, even if it's used.
311ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin        byte[] returnedIv = keymasterArgs.getBytes(KeymasterDefs.KM_TAG_NONCE, null);
31200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        if ((returnedIv != null) && (returnedIv.length == 0)) {
31300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            returnedIv = null;
31400af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        }
31500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
31600af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        if (mIv == null) {
31700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            mIv = returnedIv;
31800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        } else if ((returnedIv != null) && (!Arrays.equals(returnedIv, mIv))) {
31900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            throw new ProviderException("IV in use differs from provided IV");
32000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        }
32100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin    }
32200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
32300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin    @Override
32400af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin    protected final int engineGetBlockSize() {
32500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        return BLOCK_SIZE_BYTES;
32600af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin    }
32700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
32800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin    @Override
32900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin    protected final byte[] engineGetIV() {
33000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        return ArrayUtils.cloneIfNotEmpty(mIv);
33100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin    }
33200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
33300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin    protected void setIv(byte[] iv) {
33400af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        mIv = iv;
33500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin    }
33600af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
33700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin    protected byte[] getIv() {
33800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        return mIv;
33900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin    }
34000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
34100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin    /**
34200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin     * {@link KeyStoreCryptoOperationStreamer} which buffers all output until {@code doFinal} from
34300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin     * which it returns all output in one go, provided {@code doFinal} succeeds.
34400af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin     */
34500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin    private static class BufferAllOutputUntilDoFinalStreamer
34600af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        implements KeyStoreCryptoOperationStreamer {
34700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
34800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        private final KeyStoreCryptoOperationStreamer mDelegate;
34900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        private ByteArrayOutputStream mBufferedOutput = new ByteArrayOutputStream();
35000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        private long mProducedOutputSizeBytes;
35100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
35200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        private BufferAllOutputUntilDoFinalStreamer(KeyStoreCryptoOperationStreamer delegate) {
35300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            mDelegate = delegate;
35400af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        }
35500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
35600af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        @Override
35700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        public byte[] update(byte[] input, int inputOffset, int inputLength)
35800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                throws KeyStoreException {
35900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            byte[] output = mDelegate.update(input, inputOffset, inputLength);
36000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            if (output != null) {
36100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                try {
36200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                    mBufferedOutput.write(output);
36300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                } catch (IOException e) {
36400af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                    throw new ProviderException("Failed to buffer output", e);
36500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                }
36600af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            }
36700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            return EmptyArray.BYTE;
36800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        }
36900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
37000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        @Override
37100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        public byte[] doFinal(byte[] input, int inputOffset, int inputLength,
372d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin                byte[] signature, byte[] additionalEntropy) throws KeyStoreException {
373d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin            byte[] output = mDelegate.doFinal(input, inputOffset, inputLength, signature,
374d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin                    additionalEntropy);
37500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            if (output != null) {
37600af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                try {
37700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                    mBufferedOutput.write(output);
37800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                } catch (IOException e) {
37900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                    throw new ProviderException("Failed to buffer output", e);
38000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                }
38100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            }
38200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            byte[] result = mBufferedOutput.toByteArray();
38300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            mBufferedOutput.reset();
38400af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            mProducedOutputSizeBytes += result.length;
38500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            return result;
38600af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        }
38700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
38800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        @Override
38900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        public long getConsumedInputSizeBytes() {
39000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            return mDelegate.getConsumedInputSizeBytes();
39100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        }
39200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
39300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        @Override
39400af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        public long getProducedOutputSizeBytes() {
39500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            return mProducedOutputSizeBytes;
39600af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        }
39700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin    }
39800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
39900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin    /**
40000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin     * Additional Authentication Data (AAD) stream via a KeyStore streaming operation. This stream
40100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin     * sends AAD into the KeyStore.
40200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin     */
40300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin    private static class AdditionalAuthenticationDataStream implements Stream {
40400af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
40500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        private final KeyStore mKeyStore;
40600af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        private final IBinder mOperationToken;
40700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
40800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        private AdditionalAuthenticationDataStream(KeyStore keyStore, IBinder operationToken) {
40900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            mKeyStore = keyStore;
41000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            mOperationToken = operationToken;
41100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        }
41200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
41300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        @Override
41400af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        public OperationResult update(byte[] input) {
41500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            KeymasterArguments keymasterArgs = new KeymasterArguments();
416ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin            keymasterArgs.addBytes(KeymasterDefs.KM_TAG_ASSOCIATED_DATA, input);
41700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
41800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            // KeyStore does not reflect AAD in inputConsumed, but users of Stream rely on this
41900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            // field. We fix this discrepancy here. KeyStore.update contract is that all of AAD
42000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            // has been consumed if the method succeeds.
42100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            OperationResult result = mKeyStore.update(mOperationToken, keymasterArgs, null);
42200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            if (result.resultCode == KeyStore.NO_ERROR) {
42300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                result = new OperationResult(
42400af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                        result.resultCode,
42500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                        result.token,
42600af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                        result.operationHandle,
42700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                        input.length, // inputConsumed
42800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                        result.output,
42900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                        result.outParams);
43000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            }
43100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            return result;
43200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        }
43300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin
43400af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        @Override
435d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin        public OperationResult finish(byte[] signature, byte[] additionalEntropy) {
43600af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            if ((additionalEntropy != null) && (additionalEntropy.length > 0)) {
43700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                throw new ProviderException("AAD stream does not support additional entropy");
43800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            }
43900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin            return new OperationResult(
44000af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                    KeyStore.NO_ERROR,
44100af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                    mOperationToken,
44200af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                    0, // operation handle -- nobody cares about this being returned from finish
44300af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                    0, // inputConsumed
44400af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                    EmptyArray.BYTE, // output
44500af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                    new KeymasterArguments() // additional params returned by finish
44600af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin                    );
44700af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin        }
44800af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin    }
44900af27b7d9010eb41e45959dab7c4ff6de119897Alex Klyubin}