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.NonNull;
20d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubinimport android.os.IBinder;
21ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubinimport android.security.KeyStore;
22d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubinimport android.security.KeyStoreException;
23ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubinimport android.security.keymaster.KeyCharacteristics;
24ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubinimport android.security.keymaster.KeymasterArguments;
25ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubinimport android.security.keymaster.KeymasterDefs;
26ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin
27d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubinimport libcore.util.EmptyArray;
28d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin
29d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubinimport java.io.ByteArrayOutputStream;
30ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubinimport java.security.InvalidKeyException;
31ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubinimport java.security.SignatureSpi;
32ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin
33ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin/**
34ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * Base class for {@link SignatureSpi} providing Android KeyStore backed ECDSA signatures.
35ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin *
36ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin * @hide
37ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin */
38ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubinabstract class AndroidKeyStoreECDSASignatureSpi extends AndroidKeyStoreSignatureSpiBase {
39ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin
40ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin    public final static class NONE extends AndroidKeyStoreECDSASignatureSpi {
41ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin        public NONE() {
42ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin            super(KeymasterDefs.KM_DIGEST_NONE);
43ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin        }
44d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin
45d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin        @Override
46d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin        protected KeyStoreCryptoOperationStreamer createMainDataStreamer(KeyStore keyStore,
47d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin                IBinder operationToken) {
48d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin            return new TruncateToFieldSizeMessageStreamer(
49d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin                    super.createMainDataStreamer(keyStore, operationToken),
50d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin                    getGroupSizeBits());
51d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin        }
52d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin
53d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin        /**
54d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin         * Streamer which buffers all input, then truncates it to field size, and then sends it into
55d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin         * KeyStore via the provided delegate streamer.
56d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin         */
57d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin        private static class TruncateToFieldSizeMessageStreamer
58d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin                implements KeyStoreCryptoOperationStreamer {
59d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin
60d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin            private final KeyStoreCryptoOperationStreamer mDelegate;
61d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin            private final int mGroupSizeBits;
62d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin            private final ByteArrayOutputStream mInputBuffer = new ByteArrayOutputStream();
63d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin            private long mConsumedInputSizeBytes;
64d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin
65d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin            private TruncateToFieldSizeMessageStreamer(
66d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin                    KeyStoreCryptoOperationStreamer delegate,
67d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin                    int groupSizeBits) {
68d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin                mDelegate = delegate;
69d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin                mGroupSizeBits = groupSizeBits;
70d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin            }
71d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin
72d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin            @Override
73d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin            public byte[] update(byte[] input, int inputOffset, int inputLength)
74d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin                    throws KeyStoreException {
75d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin                if (inputLength > 0) {
76d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin                    mInputBuffer.write(input, inputOffset, inputLength);
77d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin                    mConsumedInputSizeBytes += inputLength;
78d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin                }
79d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin                return EmptyArray.BYTE;
80d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin            }
81d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin
82d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin            @Override
83d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin            public byte[] doFinal(byte[] input, int inputOffset, int inputLength, byte[] signature,
84d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin                    byte[] additionalEntropy) throws KeyStoreException {
85d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin                if (inputLength > 0) {
86d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin                    mConsumedInputSizeBytes += inputLength;
87d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin                    mInputBuffer.write(input, inputOffset, inputLength);
88d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin                }
89d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin
90d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin                byte[] bufferedInput = mInputBuffer.toByteArray();
91d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin                mInputBuffer.reset();
92d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin                // Truncate input at field size (bytes)
93d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin                return mDelegate.doFinal(bufferedInput,
94d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin                        0,
95d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin                        Math.min(bufferedInput.length, ((mGroupSizeBits + 7) / 8)),
96d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin                        signature, additionalEntropy);
97d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin            }
98d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin
99d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin            @Override
100d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin            public long getConsumedInputSizeBytes() {
101d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin                return mConsumedInputSizeBytes;
102d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin            }
103d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin
104d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin            @Override
105d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin            public long getProducedOutputSizeBytes() {
106d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin                return mDelegate.getProducedOutputSizeBytes();
107d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin            }
108d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin        }
109ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin    }
110ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin
111ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin    public final static class SHA1 extends AndroidKeyStoreECDSASignatureSpi {
112ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin        public SHA1() {
113ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin            super(KeymasterDefs.KM_DIGEST_SHA1);
114ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin        }
115ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin    }
116ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin
117ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin    public final static class SHA224 extends AndroidKeyStoreECDSASignatureSpi {
118ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin        public SHA224() {
119ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin            super(KeymasterDefs.KM_DIGEST_SHA_2_224);
120ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin        }
121ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin    }
122ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin
123ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin    public final static class SHA256 extends AndroidKeyStoreECDSASignatureSpi {
124ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin        public SHA256() {
125ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin            super(KeymasterDefs.KM_DIGEST_SHA_2_256);
126ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin        }
127ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin    }
128ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin
129ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin    public final static class SHA384 extends AndroidKeyStoreECDSASignatureSpi {
130ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin        public SHA384() {
131ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin            super(KeymasterDefs.KM_DIGEST_SHA_2_384);
132ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin        }
133ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin    }
134ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin
135ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin    public final static class SHA512 extends AndroidKeyStoreECDSASignatureSpi {
136ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin        public SHA512() {
137ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin            super(KeymasterDefs.KM_DIGEST_SHA_2_512);
138ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin        }
139ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin    }
140ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin
141ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin    private final int mKeymasterDigest;
142ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin
143d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin    private int mGroupSizeBits = -1;
144ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin
145ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin    AndroidKeyStoreECDSASignatureSpi(int keymasterDigest) {
146ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin        mKeymasterDigest = keymasterDigest;
147ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin    }
148ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin
149ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin    @Override
150ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin    protected final void initKey(AndroidKeyStoreKey key) throws InvalidKeyException {
151ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin        if (!KeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(key.getAlgorithm())) {
152ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin            throw new InvalidKeyException("Unsupported key algorithm: " + key.getAlgorithm()
153ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin                    + ". Only" + KeyProperties.KEY_ALGORITHM_EC + " supported");
154ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin        }
155ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin
156ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin        KeyCharacteristics keyCharacteristics = new KeyCharacteristics();
157ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin        int errorCode = getKeyStore().getKeyCharacteristics(
1583876b1be27e3aefde9a72eb2e4f856e94fc5f946Alex Klyubin                key.getAlias(), null, null, key.getUid(), keyCharacteristics);
159ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin        if (errorCode != KeyStore.NO_ERROR) {
1603876b1be27e3aefde9a72eb2e4f856e94fc5f946Alex Klyubin            throw getKeyStore().getInvalidKeyException(key.getAlias(), key.getUid(), errorCode);
161ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin        }
162ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin        long keySizeBits = keyCharacteristics.getUnsignedInt(KeymasterDefs.KM_TAG_KEY_SIZE, -1);
163ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin        if (keySizeBits == -1) {
164ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin            throw new InvalidKeyException("Size of key not known");
165ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin        } else if (keySizeBits > Integer.MAX_VALUE) {
166ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin            throw new InvalidKeyException("Key too large: " + keySizeBits + " bits");
167ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin        }
168d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin        mGroupSizeBits = (int) keySizeBits;
169ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin
170ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin        super.initKey(key);
171ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin    }
172ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin
173ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin    @Override
174ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin    protected final void resetAll() {
175d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin        mGroupSizeBits = -1;
176ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin        super.resetAll();
177ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin    }
178ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin
179ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin    @Override
180ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin    protected final void resetWhilePreservingInitState() {
181ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin        super.resetWhilePreservingInitState();
182ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin    }
183ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin
184ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin    @Override
185d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin    protected final void addAlgorithmSpecificParametersToBegin(
186ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin            @NonNull KeymasterArguments keymasterArgs) {
187ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin        keymasterArgs.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_EC);
188ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin        keymasterArgs.addEnum(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigest);
189ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin    }
190ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin
191ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin    @Override
192d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin    protected final int getAdditionalEntropyAmountForSign() {
193d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin        return (mGroupSizeBits + 7) / 8;
194d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin    }
195d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin
196d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin    protected final int getGroupSizeBits() {
197d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin        if (mGroupSizeBits == -1) {
198d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin            throw new IllegalStateException("Not initialized");
199d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin        }
200d23dc502b0a1952887d4453cba98aa2e3d2f5009Alex Klyubin        return mGroupSizeBits;
201ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin    }
202ccbe88a505848896e59ef8eb4e8405037ba94e88Alex Klyubin}
203