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