More CTS tests for ECDSA and RSA signatures.

This makes Android Keystore Signature tests run for keys of all
typical sizes, instead of just one RSA and one EC key.

Known-Answer Tests still use only one RSA and one EC key for now.

Bug: 21936191
Bug: 22492259
Change-Id: I857e82e20aa5ef35ea9b2bdd7b745a7403e0812c
diff --git a/tests/tests/keystore/res/raw/ec_key3_secp224r1_cert.der b/tests/tests/keystore/res/raw/ec_key3_secp224r1_cert.der
new file mode 100644
index 0000000..454edb3
--- /dev/null
+++ b/tests/tests/keystore/res/raw/ec_key3_secp224r1_cert.der
Binary files differ
diff --git a/tests/tests/keystore/res/raw/ec_key3_secp224r1_pkcs8.der b/tests/tests/keystore/res/raw/ec_key3_secp224r1_pkcs8.der
new file mode 100644
index 0000000..2b89ca3
--- /dev/null
+++ b/tests/tests/keystore/res/raw/ec_key3_secp224r1_pkcs8.der
Binary files differ
diff --git a/tests/tests/keystore/res/raw/ec_key4_secp256r1_cert.der b/tests/tests/keystore/res/raw/ec_key4_secp256r1_cert.der
new file mode 100644
index 0000000..1641a65
--- /dev/null
+++ b/tests/tests/keystore/res/raw/ec_key4_secp256r1_cert.der
Binary files differ
diff --git a/tests/tests/keystore/res/raw/ec_key4_secp256r1_pkcs8.der b/tests/tests/keystore/res/raw/ec_key4_secp256r1_pkcs8.der
new file mode 100644
index 0000000..2631a6e
--- /dev/null
+++ b/tests/tests/keystore/res/raw/ec_key4_secp256r1_pkcs8.der
Binary files differ
diff --git a/tests/tests/keystore/res/raw/ec_key5_secp384r1_cert.der b/tests/tests/keystore/res/raw/ec_key5_secp384r1_cert.der
new file mode 100644
index 0000000..cf19be8
--- /dev/null
+++ b/tests/tests/keystore/res/raw/ec_key5_secp384r1_cert.der
Binary files differ
diff --git a/tests/tests/keystore/res/raw/ec_key5_secp384r1_pkcs8.der b/tests/tests/keystore/res/raw/ec_key5_secp384r1_pkcs8.der
new file mode 100644
index 0000000..f864258
--- /dev/null
+++ b/tests/tests/keystore/res/raw/ec_key5_secp384r1_pkcs8.der
Binary files differ
diff --git a/tests/tests/keystore/res/raw/ec_key6_secp521r1_cert.der b/tests/tests/keystore/res/raw/ec_key6_secp521r1_cert.der
new file mode 100644
index 0000000..cc5d973
--- /dev/null
+++ b/tests/tests/keystore/res/raw/ec_key6_secp521r1_cert.der
Binary files differ
diff --git a/tests/tests/keystore/res/raw/ec_key6_secp521r1_pkcs8.der b/tests/tests/keystore/res/raw/ec_key6_secp521r1_pkcs8.der
new file mode 100644
index 0000000..d21815f
--- /dev/null
+++ b/tests/tests/keystore/res/raw/ec_key6_secp521r1_pkcs8.der
Binary files differ
diff --git a/tests/tests/keystore/res/raw/rsa_key3_1024_cert.der b/tests/tests/keystore/res/raw/rsa_key3_1024_cert.der
new file mode 100644
index 0000000..36f6820
--- /dev/null
+++ b/tests/tests/keystore/res/raw/rsa_key3_1024_cert.der
Binary files differ
diff --git a/tests/tests/keystore/res/raw/rsa_key3_1024_pkcs8.der b/tests/tests/keystore/res/raw/rsa_key3_1024_pkcs8.der
new file mode 100644
index 0000000..3b70b0d
--- /dev/null
+++ b/tests/tests/keystore/res/raw/rsa_key3_1024_pkcs8.der
Binary files differ
diff --git a/tests/tests/keystore/res/raw/rsa_key4_4096_cert.der b/tests/tests/keystore/res/raw/rsa_key4_4096_cert.der
new file mode 100644
index 0000000..24d9a52
--- /dev/null
+++ b/tests/tests/keystore/res/raw/rsa_key4_4096_cert.der
Binary files differ
diff --git a/tests/tests/keystore/res/raw/rsa_key4_4096_pkcs8.der b/tests/tests/keystore/res/raw/rsa_key4_4096_pkcs8.der
new file mode 100644
index 0000000..d3d08ca
--- /dev/null
+++ b/tests/tests/keystore/res/raw/rsa_key4_4096_pkcs8.der
Binary files differ
diff --git a/tests/tests/keystore/res/raw/rsa_key5_512_cert.der b/tests/tests/keystore/res/raw/rsa_key5_512_cert.der
new file mode 100644
index 0000000..56079dc
--- /dev/null
+++ b/tests/tests/keystore/res/raw/rsa_key5_512_cert.der
Binary files differ
diff --git a/tests/tests/keystore/res/raw/rsa_key5_512_pkcs8.der b/tests/tests/keystore/res/raw/rsa_key5_512_pkcs8.der
new file mode 100644
index 0000000..8f723d3
--- /dev/null
+++ b/tests/tests/keystore/res/raw/rsa_key5_512_pkcs8.der
Binary files differ
diff --git a/tests/tests/keystore/res/raw/rsa_key6_768_cert.der b/tests/tests/keystore/res/raw/rsa_key6_768_cert.der
new file mode 100644
index 0000000..8afc59b
--- /dev/null
+++ b/tests/tests/keystore/res/raw/rsa_key6_768_cert.der
Binary files differ
diff --git a/tests/tests/keystore/res/raw/rsa_key6_768_pkcs8.der b/tests/tests/keystore/res/raw/rsa_key6_768_pkcs8.der
new file mode 100644
index 0000000..7d25fe7
--- /dev/null
+++ b/tests/tests/keystore/res/raw/rsa_key6_768_pkcs8.der
Binary files differ
diff --git a/tests/tests/keystore/res/raw/rsa_key7_3072_cert.der b/tests/tests/keystore/res/raw/rsa_key7_3072_cert.der
new file mode 100644
index 0000000..414c35d
--- /dev/null
+++ b/tests/tests/keystore/res/raw/rsa_key7_3072_cert.der
Binary files differ
diff --git a/tests/tests/keystore/res/raw/rsa_key7_3072_pksc8.der b/tests/tests/keystore/res/raw/rsa_key7_3072_pksc8.der
new file mode 100644
index 0000000..32788d2
--- /dev/null
+++ b/tests/tests/keystore/res/raw/rsa_key7_3072_pksc8.der
Binary files differ
diff --git a/tests/tests/keystore/res/raw/rsa_key8_2048_cert.der b/tests/tests/keystore/res/raw/rsa_key8_2048_cert.der
new file mode 100644
index 0000000..bbbd81b
--- /dev/null
+++ b/tests/tests/keystore/res/raw/rsa_key8_2048_cert.der
Binary files differ
diff --git a/tests/tests/keystore/res/raw/rsa_key8_2048_pkcs8.der b/tests/tests/keystore/res/raw/rsa_key8_2048_pkcs8.der
new file mode 100644
index 0000000..94211ad
--- /dev/null
+++ b/tests/tests/keystore/res/raw/rsa_key8_2048_pkcs8.der
Binary files differ
diff --git a/tests/tests/keystore/src/android/keystore/cts/ECDSASignatureTest.java b/tests/tests/keystore/src/android/keystore/cts/ECDSASignatureTest.java
index 271b40b..ea3940d 100644
--- a/tests/tests/keystore/src/android/keystore/cts/ECDSASignatureTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/ECDSASignatureTest.java
@@ -16,38 +16,37 @@
 
 package android.keystore.cts;
 
-import android.security.keystore.KeyGenParameterSpec;
-import android.security.keystore.KeyProperties;
+import android.content.Context;
+import android.security.keystore.KeyProtection;
+import android.test.AndroidTestCase;
 
-import junit.framework.TestCase;
+import com.android.cts.keystore.R;
 
 import java.security.KeyPair;
-import java.security.KeyPairGenerator;
 import java.security.Security;
 import java.security.Signature;
+import java.util.Arrays;
+import java.util.Collection;
 
-public class ECDSASignatureTest extends TestCase {
+public class ECDSASignatureTest extends AndroidTestCase {
 
     public void testNONEwithECDSATruncatesInputToFieldSize() throws Exception {
-        assertNONEwithECDSATruncatesInputToFieldSize(224);
-        assertNONEwithECDSATruncatesInputToFieldSize(256);
-        assertNONEwithECDSATruncatesInputToFieldSize(384);
-        assertNONEwithECDSATruncatesInputToFieldSize(521);
+        for (ImportedKey key : importKatKeyPairs("NONEwithECDSA")) {
+            try {
+                assertNONEwithECDSATruncatesInputToFieldSize(key.getKeystoreBackedKeyPair());
+            } catch (Throwable e) {
+                throw new RuntimeException("Failed for " + key.getAlias(), e);
+            }
+        }
     }
 
-    private void assertNONEwithECDSATruncatesInputToFieldSize(int keySizeBits) throws Exception {
+    private void assertNONEwithECDSATruncatesInputToFieldSize(KeyPair keyPair)
+            throws Exception {
+        int keySizeBits = TestUtils.getKeySizeBits(keyPair.getPublic());
         byte[] message = new byte[(keySizeBits * 3) / 8];
         for (int i = 0; i < message.length; i++) {
             message[i] = (byte) (i + 1);
         }
-        KeyPairGenerator generator = KeyPairGenerator.getInstance("EC", "AndroidKeyStore");
-        generator.initialize(new KeyGenParameterSpec.Builder(
-                "test1",
-                KeyProperties.PURPOSE_SIGN)
-                .setDigests(KeyProperties.DIGEST_NONE)
-                .setKeySize(keySizeBits)
-                .build());
-        KeyPair keyPair = generator.generateKeyPair();
 
         Signature signature = Signature.getInstance("NONEwithECDSA");
         signature.initSign(keyPair.getPrivate());
@@ -73,26 +72,23 @@
     }
 
     public void testNONEwithECDSASupportsMessagesShorterThanFieldSize() throws Exception {
-        assertNONEwithECDSASupportsMessagesShorterThanFieldSize(224);
-        assertNONEwithECDSASupportsMessagesShorterThanFieldSize(256);
-        assertNONEwithECDSASupportsMessagesShorterThanFieldSize(384);
-        assertNONEwithECDSASupportsMessagesShorterThanFieldSize(521);
+        for (ImportedKey key : importKatKeyPairs("NONEwithECDSA")) {
+            try {
+                assertNONEwithECDSASupportsMessagesShorterThanFieldSize(
+                        key.getKeystoreBackedKeyPair());
+            } catch (Throwable e) {
+                throw new RuntimeException("Failed for " + key.getAlias(), e);
+            }
+        }
     }
 
-    private void assertNONEwithECDSASupportsMessagesShorterThanFieldSize(
-            int keySizeBits) throws Exception {
+    private void assertNONEwithECDSASupportsMessagesShorterThanFieldSize(KeyPair keyPair)
+            throws Exception {
+        int keySizeBits = TestUtils.getKeySizeBits(keyPair.getPublic());
         byte[] message = new byte[(keySizeBits * 3 / 4) / 8];
         for (int i = 0; i < message.length; i++) {
             message[i] = (byte) (i + 1);
         }
-        KeyPairGenerator generator = KeyPairGenerator.getInstance("EC", "AndroidKeyStore");
-        generator.initialize(new KeyGenParameterSpec.Builder(
-                "test1",
-                KeyProperties.PURPOSE_SIGN)
-                .setDigests(KeyProperties.DIGEST_NONE)
-                .setKeySize(keySizeBits)
-                .build());
-        KeyPair keyPair = generator.generateKeyPair();
 
         Signature signature = Signature.getInstance("NONEwithECDSA");
         signature.initSign(keyPair.getPrivate());
@@ -113,4 +109,25 @@
         signature.update(fullLengthMessage);
         assertTrue(signature.verify(sigBytes));
     }
+
+    private Collection<ImportedKey> importKatKeyPairs(String signatureAlgorithm)
+            throws Exception {
+        KeyProtection params =
+                TestUtils.getMinimalWorkingImportParametersForSigningingWith(signatureAlgorithm);
+        return importKatKeyPairs(getContext(), params);
+    }
+
+    static Collection<ImportedKey> importKatKeyPairs(
+            Context context, KeyProtection importParams) throws Exception {
+        return Arrays.asList(new ImportedKey[] {
+                TestUtils.importIntoAndroidKeyStore("testECsecp224r1", context,
+                        R.raw.ec_key3_secp224r1_pkcs8, R.raw.ec_key3_secp224r1_cert, importParams),
+                TestUtils.importIntoAndroidKeyStore("testECsecp256r1", context,
+                        R.raw.ec_key4_secp256r1_pkcs8, R.raw.ec_key4_secp256r1_cert, importParams),
+                TestUtils.importIntoAndroidKeyStore("testECsecp384r1", context,
+                        R.raw.ec_key5_secp384r1_pkcs8, R.raw.ec_key5_secp384r1_cert, importParams),
+                TestUtils.importIntoAndroidKeyStore("testECsecp521r1", context,
+                        R.raw.ec_key6_secp521r1_pkcs8, R.raw.ec_key6_secp521r1_cert, importParams),
+                });
+    }
 }
diff --git a/tests/tests/keystore/src/android/keystore/cts/ImportedKey.java b/tests/tests/keystore/src/android/keystore/cts/ImportedKey.java
new file mode 100644
index 0000000..647f8f3
--- /dev/null
+++ b/tests/tests/keystore/src/android/keystore/cts/ImportedKey.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.keystore.cts;
+
+import java.security.Key;
+import java.security.KeyPair;
+
+import javax.crypto.SecretKey;
+
+public class ImportedKey {
+    private final boolean mSymmetric;
+    private final String mAlias;
+    private final KeyPair mOriginalKeyPair;
+    private final KeyPair mKeystoreBackedKeyPair;
+    private final SecretKey mOriginalSecretKey;
+    private final SecretKey mKeystoreBackedSecretKey;
+
+    public ImportedKey(String alias, KeyPair original, KeyPair keystoreBacked) {
+        mAlias = alias;
+        mSymmetric = false;
+        mOriginalKeyPair = original;
+        mKeystoreBackedKeyPair = keystoreBacked;
+        mOriginalSecretKey = null;
+        mKeystoreBackedSecretKey = null;
+    }
+
+    public String getAlias() {
+        return mAlias;
+    }
+
+    public Key getOriginalEncryptionKey() {
+        if (mSymmetric) {
+            return mOriginalSecretKey;
+        } else {
+            return mOriginalKeyPair.getPublic();
+        }
+    }
+
+    public Key getOriginalDecryptionKey() {
+        if (mSymmetric) {
+            return mOriginalSecretKey;
+        } else {
+            return mOriginalKeyPair.getPrivate();
+        }
+    }
+
+    public Key getOriginalSigningKey() {
+        if (mSymmetric) {
+            return mOriginalSecretKey;
+        } else {
+            return mOriginalKeyPair.getPrivate();
+        }
+    }
+
+    public Key getOriginalVerificationKey() {
+        if (mSymmetric) {
+            return mOriginalSecretKey;
+        } else {
+            return mOriginalKeyPair.getPublic();
+        }
+    }
+
+    public Key getKeystoreBackedEncryptionKey() {
+        if (mSymmetric) {
+            return mKeystoreBackedSecretKey;
+        } else {
+            return mKeystoreBackedKeyPair.getPublic();
+        }
+    }
+
+    public Key getKeystoreBackedDecryptionKey() {
+        if (mSymmetric) {
+            return mKeystoreBackedSecretKey;
+        } else {
+            return mKeystoreBackedKeyPair.getPrivate();
+        }
+    }
+
+    public Key getKeystoreBackedSigningKey() {
+        if (mSymmetric) {
+            return mKeystoreBackedSecretKey;
+        } else {
+            return mKeystoreBackedKeyPair.getPrivate();
+        }
+    }
+
+    public Key getKeystoreBackedVerificationKey() {
+        if (mSymmetric) {
+            return mKeystoreBackedSecretKey;
+        } else {
+            return mKeystoreBackedKeyPair.getPublic();
+        }
+    }
+
+
+    public KeyPair getOriginalKeyPair() {
+        checkIsKeyPair();
+        return mOriginalKeyPair;
+    }
+
+    public KeyPair getKeystoreBackedKeyPair() {
+        checkIsKeyPair();
+        return mKeystoreBackedKeyPair;
+    }
+
+    public SecretKey getOriginalSecretKey() {
+        checkIsSecretKey();
+        return mOriginalSecretKey;
+    }
+
+    public SecretKey getKeystoreBackedSecretKey() {
+        checkIsSecretKey();
+        return mKeystoreBackedSecretKey;
+    }
+
+    private void checkIsKeyPair() {
+        if (mSymmetric) {
+            throw new IllegalStateException("Not a KeyPair");
+        }
+    }
+
+    private void checkIsSecretKey() {
+        if (mSymmetric) {
+            throw new IllegalStateException("Not a SecretKey");
+        }
+    }
+}
diff --git a/tests/tests/keystore/src/android/keystore/cts/RSASignatureTest.java b/tests/tests/keystore/src/android/keystore/cts/RSASignatureTest.java
new file mode 100644
index 0000000..15d9116
--- /dev/null
+++ b/tests/tests/keystore/src/android/keystore/cts/RSASignatureTest.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package android.keystore.cts;
+
+import java.security.InvalidKeyException;
+import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.Provider;
+import java.security.PublicKey;
+import java.security.Security;
+import java.security.Signature;
+import java.security.SignatureException;
+import java.security.interfaces.RSAKey;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+import com.android.cts.keystore.R;
+
+import android.content.Context;
+import android.security.keystore.KeyProperties;
+import android.security.keystore.KeyProtection;
+import android.test.AndroidTestCase;
+
+public class RSASignatureTest extends AndroidTestCase {
+
+    private static final String EXPECTED_PROVIDER_NAME = SignatureTest.EXPECTED_PROVIDER_NAME;
+
+    private static final String[] SIGNATURE_ALGORITHMS;
+
+    static {
+        List<String> sigAlgs = new ArrayList<>();
+        for (String algorithm : SignatureTest.EXPECTED_SIGNATURE_ALGORITHMS) {
+            String keyAlgorithm = TestUtils.getSignatureAlgorithmKeyAlgorithm(algorithm);
+            if (KeyProperties.KEY_ALGORITHM_RSA.equalsIgnoreCase(keyAlgorithm)) {
+                sigAlgs.add(algorithm);
+            }
+        }
+        SIGNATURE_ALGORITHMS = sigAlgs.toArray(new String[sigAlgs.size()]);
+    }
+
+    public void testMaxMessageSizeWhenNoDigestUsed() throws Exception {
+        Provider provider = Security.getProvider(EXPECTED_PROVIDER_NAME);
+        assertNotNull(provider);
+
+        for (ImportedKey keyPair : importKatKeyPairs("NONEwithRSA")) {
+            PublicKey publicKey = keyPair.getKeystoreBackedKeyPair().getPublic();
+            PrivateKey privateKey = keyPair.getKeystoreBackedKeyPair().getPrivate();
+            int modulusSizeBits = ((RSAKey) publicKey).getModulus().bitLength();
+            try {
+                int modulusSizeBytes = (modulusSizeBits + 7) / 8;
+                // PKCS#1 signature padding must be at least 11 bytes long (00 || 01 || PS || 00)
+                // where PS must be at least 8 bytes long).
+                int expectedMaxMessageSizeBytes = modulusSizeBytes - 11;
+                byte[] msg = new byte[expectedMaxMessageSizeBytes + 1];
+                Arrays.fill(msg, (byte) 0xf0);
+
+                // Assert that a message of expected maximum length is accepted
+                Signature signature = Signature.getInstance("NONEwithRSA", provider);
+                signature.initSign(privateKey);
+                signature.update(msg, 0, expectedMaxMessageSizeBytes);
+                byte[] sigBytes = signature.sign();
+
+                signature.initVerify(publicKey);
+                signature.update(msg, 0, expectedMaxMessageSizeBytes);
+                assertTrue(signature.verify(sigBytes));
+
+                // Assert that a message longer than expected maximum length is rejected
+                signature = Signature.getInstance(signature.getAlgorithm(), provider);
+                signature.initSign(privateKey);
+                try {
+                    signature.update(msg, 0, expectedMaxMessageSizeBytes + 1);
+                    signature.sign();
+                    fail();
+                } catch (SignatureException expected) {
+                }
+
+                signature.initVerify(publicKey);
+                try {
+                    signature.update(msg, 0, expectedMaxMessageSizeBytes + 1);
+                    signature.verify(sigBytes);
+                    fail();
+                } catch (SignatureException expected) {
+                }
+            } catch (Throwable e) {
+                throw new RuntimeException("Failed for " + modulusSizeBits + " bit key", e);
+            }
+        }
+    }
+
+    public void testSmallKeyRejected() throws Exception {
+        // Use a 512 bit key which should prevent the use of any digests larger than SHA-256
+        // because the padded form of the digested message will be larger than modulus size.
+        Provider provider = Security.getProvider(EXPECTED_PROVIDER_NAME);
+        assertNotNull(provider);
+
+        for (String algorithm : SIGNATURE_ALGORITHMS) {
+            try {
+                String digest = TestUtils.getSignatureAlgorithmDigest(algorithm);
+                if (KeyProperties.DIGEST_NONE.equalsIgnoreCase(digest)) {
+                    // Ignore signature algorithms without digest -- this is tested in a separate
+                    // test above.
+                    continue;
+                }
+                int digestOutputSizeBits = TestUtils.getDigestOutputSizeBits(digest);
+                if (digestOutputSizeBits <= 256) {
+                    // 256-bit and shorter digests are short enough to work with a 512 bit key.
+                    continue;
+                }
+
+                KeyPair keyPair = TestUtils.importIntoAndroidKeyStore("test1",
+                        getContext(),
+                        R.raw.rsa_key5_512_pkcs8,
+                        R.raw.rsa_key5_512_cert,
+                        TestUtils.getMinimalWorkingImportParametersForSigningingWith(algorithm))
+                        .getKeystoreBackedKeyPair();
+                assertEquals(512, ((RSAKey) keyPair.getPrivate()).getModulus().bitLength());
+                assertEquals(512, ((RSAKey) keyPair.getPublic()).getModulus().bitLength());
+
+                Signature signature = Signature.getInstance(algorithm, provider);
+                // Assert that either initSign or sign fails. We don't expect all keymaster
+                // implementations to fail early, during initSign.
+                try {
+                    signature.initSign(keyPair.getPrivate());
+                    signature.update("A message".getBytes("UTF-8"));
+                    byte[] sigBytes = signature.sign();
+                    fail("Unexpectedly generated a signature (" + sigBytes.length + " bytes): "
+                            + HexEncoding.encode(sigBytes));
+                } catch (InvalidKeyException | SignatureException expected) {
+                }
+            } catch (Throwable e) {
+                throw new RuntimeException("Failed for " + algorithm, e);
+            }
+        }
+    }
+
+    private Collection<ImportedKey> importKatKeyPairs(String signatureAlgorithm)
+            throws Exception {
+        KeyProtection params =
+                TestUtils.getMinimalWorkingImportParametersForSigningingWith(signatureAlgorithm);
+        return importKatKeyPairs(getContext(), params);
+    }
+
+    static Collection<ImportedKey> importKatKeyPairs(
+            Context context, KeyProtection importParams) throws Exception {
+        return Arrays.asList(new ImportedKey[] {
+                TestUtils.importIntoAndroidKeyStore("testRSA512", context,
+                        R.raw.rsa_key5_512_pkcs8, R.raw.rsa_key5_512_cert, importParams),
+                TestUtils.importIntoAndroidKeyStore("testRSA768", context,
+                        R.raw.rsa_key6_768_pkcs8, R.raw.rsa_key6_768_cert, importParams),
+                TestUtils.importIntoAndroidKeyStore("testRSA1024", context,
+                        R.raw.rsa_key3_1024_pkcs8, R.raw.rsa_key3_1024_cert, importParams),
+                TestUtils.importIntoAndroidKeyStore("testRSA2024", context,
+                        R.raw.rsa_key8_2048_pkcs8, R.raw.rsa_key8_2048_cert, importParams),
+                TestUtils.importIntoAndroidKeyStore("testRSA3072", context,
+                        R.raw.rsa_key7_3072_pksc8, R.raw.rsa_key7_3072_cert, importParams),
+                TestUtils.importIntoAndroidKeyStore("testRsa4096", context,
+                        R.raw.rsa_key4_4096_pkcs8, R.raw.rsa_key4_4096_cert, importParams),
+                });
+    }
+}
diff --git a/tests/tests/keystore/src/android/keystore/cts/SignatureTest.java b/tests/tests/keystore/src/android/keystore/cts/SignatureTest.java
index 4e1380a..30d1dee 100644
--- a/tests/tests/keystore/src/android/keystore/cts/SignatureTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/SignatureTest.java
@@ -27,7 +27,6 @@
 import java.security.Security;
 import java.security.Signature;
 import java.security.SignatureException;
-import java.security.interfaces.ECKey;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Date;
@@ -37,6 +36,7 @@
 import java.util.Set;
 import java.util.TreeMap;
 
+import android.content.Context;
 import android.security.keystore.KeyProperties;
 import android.security.keystore.KeyProtection;
 import android.test.AndroidTestCase;
@@ -50,7 +50,7 @@
 
     static final String EXPECTED_PROVIDER_NAME = TestUtils.EXPECTED_CRYPTO_OP_PROVIDER_NAME;
 
-    private static final String[] EXPECTED_SIGNATURE_ALGORITHMS = {
+    static final String[] EXPECTED_SIGNATURE_ALGORITHMS = {
         "NONEwithRSA",
         "MD5withRSA",
         "SHA1withRSA",
@@ -363,13 +363,11 @@
 
     public void testAndroidKeyStoreKeysHandledByAndroidKeyStoreProviderWhenSigning()
             throws Exception {
-        Collection<KeyPair> keyPairs = importDefaultKatKeyPairs();
-
         Provider provider = Security.getProvider(EXPECTED_PROVIDER_NAME);
         assertNotNull(provider);
         for (String sigAlgorithm : EXPECTED_SIGNATURE_ALGORITHMS) {
             try {
-                KeyPair keyPair = getKeyPairForSignatureAlgorithm(sigAlgorithm, keyPairs);
+                KeyPair keyPair = importDefaultKatKeyPair(sigAlgorithm).getKeystoreBackedKeyPair();
                 Signature signature = Signature.getInstance(sigAlgorithm);
                 signature.initSign(keyPair.getPrivate());
                 assertSame(provider, signature.getProvider());
@@ -381,13 +379,11 @@
 
     public void testAndroidKeyStorePublicKeysAcceptedByHighestPriorityProviderWhenVerifying()
             throws Exception {
-        Collection<KeyPair> keyPairs = importDefaultKatKeyPairs();
-
         Provider provider = Security.getProvider(EXPECTED_PROVIDER_NAME);
         assertNotNull(provider);
         for (String sigAlgorithm : EXPECTED_SIGNATURE_ALGORITHMS) {
             try {
-                KeyPair keyPair = getKeyPairForSignatureAlgorithm(sigAlgorithm, keyPairs);
+                KeyPair keyPair = importDefaultKatKeyPair(sigAlgorithm).getKeystoreBackedKeyPair();
                 Signature signature = Signature.getInstance(sigAlgorithm);
                 signature.initVerify(keyPair.getPublic());
             } catch (Throwable e) {
@@ -398,106 +394,118 @@
 
     public void testSignatureGeneratedByAndroidKeyStoreVerifiesByAndroidKeyStore()
             throws Exception {
-        Collection<KeyPair> keyPairs = importDefaultKatKeyPairs();
-
         Provider provider = Security.getProvider(EXPECTED_PROVIDER_NAME);
         assertNotNull(provider);
         for (String sigAlgorithm : EXPECTED_SIGNATURE_ALGORITHMS) {
-            try {
-                KeyPair keyPair = getKeyPairForSignatureAlgorithm(sigAlgorithm, keyPairs);
+            for (ImportedKey key : importKatKeyPairsForSigning(getContext(), sigAlgorithm)) {
+                if (!TestUtils.isKeyLongEnoughForSignatureAlgorithm(
+                        sigAlgorithm, key.getOriginalSigningKey())) {
+                    continue;
+                }
+                try {
+                    KeyPair keyPair = key.getKeystoreBackedKeyPair();
 
-                // Generate a signature
-                Signature signature = Signature.getInstance(sigAlgorithm, provider);
-                signature.initSign(keyPair.getPrivate());
-                byte[] message = "This is a test".getBytes("UTF-8");
-                signature.update(message);
-                byte[] sigBytes = signature.sign();
+                    // Generate a signature
+                    Signature signature = Signature.getInstance(sigAlgorithm, provider);
+                    signature.initSign(keyPair.getPrivate());
+                    byte[] message = "This is a test".getBytes("UTF-8");
+                    signature.update(message);
+                    byte[] sigBytes = signature.sign();
 
-                // Assert that it verifies using our own Provider
-                assertSignatureVerifiesOneShot(
-                        sigAlgorithm, provider, keyPair.getPublic(), message, sigBytes);
-            } catch (Throwable e) {
-                throw new RuntimeException(sigAlgorithm + " failed", e);
+                    // Assert that it verifies using our own Provider
+                    assertSignatureVerifiesOneShot(
+                            sigAlgorithm, provider, keyPair.getPublic(), message, sigBytes);
+                } catch (Throwable e) {
+                    throw new RuntimeException(
+                            "Failed for " + sigAlgorithm + " with key " + key.getAlias(), e);
+                }
             }
         }
     }
 
     public void testSignatureGeneratedByAndroidKeyStoreVerifiesByHighestPriorityProvider()
             throws Exception {
-        Collection<KeyPair> keyPairs = getDefaultKatKeyPairs();
-        Collection<KeyPair> keystoreKeyPairs = importDefaultKatKeyPairs();
-
         Provider keystoreProvider = Security.getProvider(EXPECTED_PROVIDER_NAME);
         assertNotNull(keystoreProvider);
         for (String sigAlgorithm : EXPECTED_SIGNATURE_ALGORITHMS) {
-            try {
-                PrivateKey keystorePrivateKey =
-                        getKeyPairForSignatureAlgorithm(sigAlgorithm, keystoreKeyPairs)
-                                .getPrivate();
-
-                // Generate a signature
-                Signature signature = Signature.getInstance(sigAlgorithm, keystoreProvider);
-                signature.initSign(keystorePrivateKey);
-                byte[] message = "This is a test".getBytes("UTF-8");
-                signature.update(message);
-                byte[] sigBytes = signature.sign();
-
-                // Assert that it verifies using whatever Provider is chosen by JCA by default for
-                // this signature algorithm and public key.
-                PublicKey publicKey =
-                        getKeyPairForSignatureAlgorithm(sigAlgorithm, keyPairs).getPublic();
-                Provider verificationProvider;
-                try {
-                    signature = Signature.getInstance(sigAlgorithm);
-                    signature.initVerify(publicKey);
-                    verificationProvider = signature.getProvider();
-                } catch (InvalidKeyException e) {
-                    // No providers support verifying signatures using this algorithm and key.
+            for (ImportedKey key : importKatKeyPairsForSigning(getContext(), sigAlgorithm)) {
+                if (!TestUtils.isKeyLongEnoughForSignatureAlgorithm(
+                        sigAlgorithm, key.getOriginalSigningKey())) {
                     continue;
                 }
-                assertSignatureVerifiesOneShot(
-                        sigAlgorithm, verificationProvider, publicKey, message, sigBytes);
-            } catch (Throwable e) {
-                throw new RuntimeException(sigAlgorithm + " failed", e);
+                Provider verificationProvider = null;
+                try {
+                    PrivateKey keystorePrivateKey = key.getKeystoreBackedKeyPair().getPrivate();
+
+                    // Generate a signature
+                    Signature signature = Signature.getInstance(sigAlgorithm, keystoreProvider);
+                    signature.initSign(keystorePrivateKey);
+                    byte[] message = "This is a test".getBytes("UTF-8");
+                    signature.update(message);
+                    byte[] sigBytes = signature.sign();
+
+                    // Assert that it verifies using whatever Provider is chosen by JCA by default
+                    // for this signature algorithm and public key.
+                    PublicKey publicKey = key.getOriginalKeyPair().getPublic();
+                    try {
+                        signature = Signature.getInstance(sigAlgorithm);
+                        signature.initVerify(publicKey);
+                        verificationProvider = signature.getProvider();
+                    } catch (InvalidKeyException e) {
+                        // No providers support verifying signatures using this algorithm and key.
+                        continue;
+                    }
+                    assertSignatureVerifiesOneShot(
+                            sigAlgorithm, verificationProvider, publicKey, message, sigBytes);
+                } catch (Throwable e) {
+                    throw new RuntimeException(
+                            "Failed for " + sigAlgorithm + " with key " + key.getAlias()
+                                    + ", verification provider: " + verificationProvider,
+                            e);
+                }
             }
         }
     }
 
     public void testSignatureGeneratedByHighestPriorityProviderVerifiesByAndroidKeyStore()
             throws Exception {
-        Collection<KeyPair> keyPairs = getDefaultKatKeyPairs();
-        Collection<KeyPair> keystoreKeyPairs = importDefaultKatKeyPairs();
 
         Provider keystoreProvider = Security.getProvider(EXPECTED_PROVIDER_NAME);
         assertNotNull(keystoreProvider);
         for (String sigAlgorithm : EXPECTED_SIGNATURE_ALGORITHMS) {
-            Provider signingProvider = null;
-            try {
-                PrivateKey privateKey =
-                        getKeyPairForSignatureAlgorithm(sigAlgorithm, keyPairs).getPrivate();
-
-                // Generate a signature
-                Signature signature;
-                try {
-                    signature = Signature.getInstance(sigAlgorithm);
-                    signature.initSign(privateKey);
-                    signingProvider = signature.getProvider();
-                } catch (InvalidKeyException e) {
-                    // No providers support signing using this algorithm and key.
+            for (ImportedKey key : importKatKeyPairsForSigning(getContext(), sigAlgorithm)) {
+                if (!TestUtils.isKeyLongEnoughForSignatureAlgorithm(
+                        sigAlgorithm, key.getOriginalSigningKey())) {
                     continue;
                 }
-                byte[] message = "This is a test".getBytes("UTF-8");
-                signature.update(message);
-                byte[] sigBytes = signature.sign();
+                Provider signingProvider = null;
+                try {
+                    PrivateKey privateKey = key.getOriginalKeyPair().getPrivate();
 
-                // Assert that the signature verifies using the Android Keystore provider.
-                PublicKey keystorePublicKey =
-                        getKeyPairForSignatureAlgorithm(sigAlgorithm, keystoreKeyPairs).getPublic();
-                assertSignatureVerifiesOneShot(
-                        sigAlgorithm, keystoreProvider, keystorePublicKey, message, sigBytes);
-            } catch (Throwable e) {
-                throw new RuntimeException(
-                        sigAlgorithm + " failed, signing provider: " + signingProvider, e);
+                    // Generate a signature
+                    Signature signature;
+                    try {
+                        signature = Signature.getInstance(sigAlgorithm);
+                        signature.initSign(privateKey);
+                        signingProvider = signature.getProvider();
+                    } catch (InvalidKeyException e) {
+                        // No providers support signing using this algorithm and key.
+                        continue;
+                    }
+                    byte[] message = "This is a test".getBytes("UTF-8");
+                    signature.update(message);
+                    byte[] sigBytes = signature.sign();
+
+                    // Assert that the signature verifies using the Android Keystore provider.
+                    PublicKey keystorePublicKey = key.getKeystoreBackedKeyPair().getPublic();
+                    assertSignatureVerifiesOneShot(
+                            sigAlgorithm, keystoreProvider, keystorePublicKey, message, sigBytes);
+                } catch (Throwable e) {
+                    throw new RuntimeException(
+                            "Failed for " + sigAlgorithm + " with key " + key.getAlias()
+                                    + ", signing provider: " + signingProvider,
+                            e);
+                }
             }
         }
     }
@@ -508,54 +516,57 @@
         // SecureRandom. There is no need to check that Signature.verify does not consume entropy
         // because Signature.initVerify does not take a SecureRandom.
 
-        Collection<KeyPair> keyPairs = importDefaultKatKeyPairs();
-
         Provider provider = Security.getProvider(EXPECTED_PROVIDER_NAME);
         assertNotNull(provider);
 
         CountingSecureRandom rng = new CountingSecureRandom();
         for (String sigAlgorithm : EXPECTED_SIGNATURE_ALGORITHMS) {
-            try {
-                PrivateKey privateKey =
-                        getKeyPairForSignatureAlgorithm(sigAlgorithm, keyPairs).getPrivate();
-                Signature signature = Signature.getInstance(sigAlgorithm, provider);
-
-                // Signature.initSign should not consume entropy.
-                rng.resetCounters();
-                signature.initSign(privateKey, rng);
-                assertEquals(0, rng.getOutputSizeBytes());
-
-                // Signature.update should not consume entropy.
-                byte[] message = "This is a test message".getBytes("UTF-8");
-                rng.resetCounters();
-                signature.update(message);
-                assertEquals(0, rng.getOutputSizeBytes());
-
-                // Signature.sign may consume entropy.
-                rng.resetCounters();
-                signature.sign();
-                int expectedEntropyBytesConsumed;
-                String algorithmUpperCase = sigAlgorithm.toUpperCase(Locale.US);
-                if (algorithmUpperCase.endsWith("WITHECDSA")) {
-                    int fieldSizeBits =
-                            ((ECKey) privateKey).getParams().getCurve().getField().getFieldSize();
-                    expectedEntropyBytesConsumed = (fieldSizeBits + 7) / 8;
-                } else if (algorithmUpperCase.endsWith("WITHRSA")) {
-                    expectedEntropyBytesConsumed = 0;
-                } else if (algorithmUpperCase.endsWith("WITHRSA/PSS")) {
-                    expectedEntropyBytesConsumed = 20; // salt length
-                } else {
-                    throw new RuntimeException("Unsupported algorithm: " + sigAlgorithm);
+            for (ImportedKey key : importKatKeyPairsForSigning(getContext(), sigAlgorithm)) {
+                if (!TestUtils.isKeyLongEnoughForSignatureAlgorithm(
+                        sigAlgorithm, key.getOriginalSigningKey())) {
+                    continue;
                 }
-                assertEquals(expectedEntropyBytesConsumed, rng.getOutputSizeBytes());
-            } catch (Throwable e) {
-                throw new RuntimeException("Failed for " + sigAlgorithm, e);
+                try {
+                    KeyPair keyPair = key.getKeystoreBackedKeyPair();
+                    PrivateKey privateKey = keyPair.getPrivate();
+                    Signature signature = Signature.getInstance(sigAlgorithm, provider);
+
+                    // Signature.initSign should not consume entropy.
+                    rng.resetCounters();
+                    signature.initSign(privateKey, rng);
+                    assertEquals(0, rng.getOutputSizeBytes());
+
+                    // Signature.update should not consume entropy.
+                    byte[] message = "This is a test message".getBytes("UTF-8");
+                    rng.resetCounters();
+                    signature.update(message);
+                    assertEquals(0, rng.getOutputSizeBytes());
+
+                    // Signature.sign may consume entropy.
+                    rng.resetCounters();
+                    signature.sign();
+                    int expectedEntropyBytesConsumed;
+                    String algorithmUpperCase = sigAlgorithm.toUpperCase(Locale.US);
+                    if (algorithmUpperCase.endsWith("WITHECDSA")) {
+                        expectedEntropyBytesConsumed =
+                                (TestUtils.getKeySizeBits(privateKey) + 7) / 8;
+                    } else if (algorithmUpperCase.endsWith("WITHRSA")) {
+                        expectedEntropyBytesConsumed = 0;
+                    } else if (algorithmUpperCase.endsWith("WITHRSA/PSS")) {
+                        expectedEntropyBytesConsumed = 20; // salt length
+                    } else {
+                        throw new RuntimeException("Unsupported algorithm: " + sigAlgorithm);
+                    }
+                    assertEquals(expectedEntropyBytesConsumed, rng.getOutputSizeBytes());
+                } catch (Throwable e) {
+                    throw new RuntimeException(
+                            "Failed for " + sigAlgorithm + " with key " + key.getAlias(), e);
+                }
             }
         }
     }
 
     public void testSmallMsgKat() throws Exception {
-        Collection<KeyPair> keyPairs = importDefaultKatKeyPairs();
         byte[] message = SHORT_MSG_KAT_MESSAGE;
 
         Provider provider = Security.getProvider(EXPECTED_PROVIDER_NAME);
@@ -564,7 +575,7 @@
             try {
                 byte[] goodSigBytes = SHORT_MSG_KAT_SIGNATURES.get(algorithm);
                 assertNotNull(goodSigBytes);
-                KeyPair keyPair = getKeyPairForSignatureAlgorithm(algorithm, keyPairs);
+                KeyPair keyPair = importDefaultKatKeyPair(algorithm).getKeystoreBackedKeyPair();
                 // Assert that AndroidKeyStore provider can verify the known good signature.
                 assertSignatureVerifiesOneShot(
                         algorithm, provider, keyPair.getPublic(), message, goodSigBytes);
@@ -654,23 +665,25 @@
     }
 
     public void testLongMsgKat() throws Exception {
-        Collection<KeyPair> keyPairs = importDefaultKatKeyPairs();
         byte[] message = TestUtils.generateLargeKatMsg(LONG_MSG_KAT_SEED, LONG_MSG_KAT_SIZE_BYTES);
 
         Provider provider = Security.getProvider(EXPECTED_PROVIDER_NAME);
         assertNotNull(provider);
         for (String algorithm : EXPECTED_SIGNATURE_ALGORITHMS) {
-            KeyPair keyPair = getKeyPairForSignatureAlgorithm(algorithm, keyPairs);
-
             try {
-                if (algorithm.toLowerCase(Locale.US).startsWith("nonewithrsa")) {
-                    // This algorithm cannot accept large messages
+                KeyPair keyPair = importDefaultKatKeyPair(algorithm).getKeystoreBackedKeyPair();
+                String digest = TestUtils.getSignatureAlgorithmDigest(algorithm);
+                String keyAlgorithm = TestUtils.getSignatureAlgorithmKeyAlgorithm(algorithm);
+                if ((KeyProperties.DIGEST_NONE.equalsIgnoreCase(digest))
+                        && (!KeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(keyAlgorithm))) {
+                    // This algorithm does not accept large messages
                     Signature signature = Signature.getInstance(algorithm, provider);
                     signature.initSign(keyPair.getPrivate());
                     try {
                         signature.update(message);
-                        signature.sign();
-                        fail();
+                        byte[] sigBytes = signature.sign();
+                        fail("Unexpectedly generated signature (" + sigBytes.length + "): "
+                                + HexEncoding.encode(sigBytes));
                     } catch (SignatureException expected) {}
 
                     // Bogus signature generated using SHA-256 digest -- shouldn't because the
@@ -703,8 +716,9 @@
                 signature.initSign(keyPair.getPrivate());
                 signature.update(message);
                 byte[] generatedSigBytes = signature.sign();
+                String paddingScheme = TestUtils.getSignatureAlgorithmPadding(algorithm);
                 boolean deterministicSignatureScheme =
-                        algorithm.toLowerCase().endsWith("withrsa");
+                        KeyProperties.SIGNATURE_PADDING_RSA_PKCS1.equalsIgnoreCase(paddingScheme);
                 if (deterministicSignatureScheme) {
                     MoreAsserts.assertEquals(goodSigBytes, generatedSigBytes);
                 } else {
@@ -778,8 +792,8 @@
 
         for (String algorithm : EXPECTED_SIGNATURE_ALGORITHMS) {
             try {
-                KeyProtection.Builder good = getWorkingImportParamsForSigning(algorithm);
-                assertInitSignSucceeds(algorithm, good.build());
+                KeyProtection good = getMinimalWorkingImportParamsForSigning(algorithm);
+                assertInitSignSucceeds(algorithm, good);
                 assertInitSignThrowsInvalidKeyException(algorithm,
                         TestUtils.buildUpon(good, badPurposes).build());
             } catch (Throwable e) {
@@ -794,8 +808,8 @@
 
         for (String algorithm : EXPECTED_SIGNATURE_ALGORITHMS) {
             try {
-                KeyProtection.Builder good = getWorkingImportParamsForVerifying(algorithm);
-                assertInitVerifySucceeds(algorithm, good.build());
+                KeyProtection good = getMinimalWorkingImportParamsForVerifying(algorithm);
+                assertInitVerifySucceeds(algorithm, good);
                 assertInitVerifySucceeds(algorithm,
                         TestUtils.buildUpon(good, badPurposes).build());
             } catch (Throwable e) {
@@ -807,12 +821,13 @@
     public void testInitSignFailsWhenDigestNotAuthorized() throws Exception {
         for (String algorithm : EXPECTED_SIGNATURE_ALGORITHMS) {
             try {
-                KeyProtection.Builder good = getWorkingImportParamsForSigning(algorithm);
-                assertInitSignSucceeds(algorithm, good.build());
+                KeyProtection good = getMinimalWorkingImportParamsForSigning(algorithm);
+                assertInitSignSucceeds(algorithm, good);
 
-                String algorithmUpperCase = algorithm.toUpperCase(Locale.US);
+                String digest = TestUtils.getSignatureAlgorithmDigest(algorithm);
                 String badDigest =
-                        (algorithmUpperCase.startsWith("SHA256")) ? "SHA-384" : "SHA-256";
+                        (KeyProperties.DIGEST_SHA256.equalsIgnoreCase(digest))
+                        ? KeyProperties.DIGEST_SHA384 : KeyProperties.DIGEST_SHA256;
                 assertInitSignThrowsInvalidKeyException(algorithm,
                         TestUtils.buildUpon(good).setDigests(badDigest).build());
             } catch (Throwable e) {
@@ -824,12 +839,13 @@
     public void testInitVerifyIgnoresThatDigestNotAuthorized() throws Exception {
         for (String algorithm : EXPECTED_SIGNATURE_ALGORITHMS) {
             try {
-                KeyProtection.Builder good = getWorkingImportParamsForVerifying(algorithm);
-                assertInitVerifySucceeds(algorithm, good.build());
+                KeyProtection good = getMinimalWorkingImportParamsForVerifying(algorithm);
+                assertInitVerifySucceeds(algorithm, good);
 
-                String algorithmUpperCase = algorithm.toUpperCase(Locale.US);
+                String digest = TestUtils.getSignatureAlgorithmDigest(algorithm);
                 String badDigest =
-                        (algorithmUpperCase.startsWith("SHA256")) ? "SHA-384" : "SHA-256";
+                        (KeyProperties.DIGEST_SHA256.equalsIgnoreCase(digest))
+                        ? KeyProperties.DIGEST_SHA384 : KeyProperties.DIGEST_SHA256;
                 assertInitVerifySucceeds(algorithm,
                         TestUtils.buildUpon(good).setDigests(badDigest).build());
             } catch (Throwable e) {
@@ -841,22 +857,23 @@
     public void testInitSignFailsWhenPaddingNotAuthorized() throws Exception {
         for (String algorithm : EXPECTED_SIGNATURE_ALGORITHMS) {
             try {
-                String algorithmUpperCase = algorithm.toUpperCase(Locale.US);
+                String paddingScheme = TestUtils.getSignatureAlgorithmPadding(algorithm);
                 String badPaddingScheme;
-                if (algorithmUpperCase.endsWith("WITHECDSA")) {
-                    // Test does not apply to ECDSA because ECDSA doesn't any signature padding
-                    // schemes.
+                if (paddingScheme == null) {
+                    // No padding scheme used by this algorithm -- ignore.
                     continue;
-                } else if (algorithmUpperCase.endsWith("WITHRSA")) {
+                } else if (KeyProperties.SIGNATURE_PADDING_RSA_PKCS1.equalsIgnoreCase(
+                        paddingScheme)) {
                     badPaddingScheme = KeyProperties.SIGNATURE_PADDING_RSA_PSS;
-                } else if (algorithmUpperCase.endsWith("WITHRSA/PSS")) {
+                } else if (KeyProperties.SIGNATURE_PADDING_RSA_PSS.equalsIgnoreCase(
+                        paddingScheme)) {
                     badPaddingScheme = KeyProperties.SIGNATURE_PADDING_RSA_PKCS1;
                 } else {
                     throw new IllegalArgumentException("Unsupported algorithm: " + algorithm);
                 }
 
-                KeyProtection.Builder good = getWorkingImportParamsForSigning(algorithm);
-                assertInitSignSucceeds(algorithm, good.build());
+                KeyProtection good = getMinimalWorkingImportParamsForSigning(algorithm);
+                assertInitSignSucceeds(algorithm, good);
                 assertInitSignThrowsInvalidKeyException(algorithm,
                         TestUtils.buildUpon(good).setSignaturePaddings(badPaddingScheme).build());
             } catch (Throwable e) {
@@ -868,22 +885,23 @@
     public void testInitVerifyIgnoresThatPaddingNotAuthorized() throws Exception {
         for (String algorithm : EXPECTED_SIGNATURE_ALGORITHMS) {
             try {
-                String algorithmUpperCase = algorithm.toUpperCase(Locale.US);
+                String paddingScheme = TestUtils.getSignatureAlgorithmPadding(algorithm);
                 String badPaddingScheme;
-                if (algorithmUpperCase.endsWith("WITHECDSA")) {
-                    // Test does not apply to ECDSA because ECDSA doesn't any signature padding
-                    // schemes.
+                if (paddingScheme == null) {
+                    // No padding scheme used by this algorithm -- ignore.
                     continue;
-                } else if (algorithmUpperCase.endsWith("WITHRSA")) {
+                } else if (KeyProperties.SIGNATURE_PADDING_RSA_PKCS1.equalsIgnoreCase(
+                        paddingScheme)) {
                     badPaddingScheme = KeyProperties.SIGNATURE_PADDING_RSA_PSS;
-                } else if (algorithmUpperCase.endsWith("WITHRSA/PSS")) {
+                } else if (KeyProperties.SIGNATURE_PADDING_RSA_PSS.equalsIgnoreCase(
+                        paddingScheme)) {
                     badPaddingScheme = KeyProperties.SIGNATURE_PADDING_RSA_PKCS1;
                 } else {
                     throw new IllegalArgumentException("Unsupported algorithm: " + algorithm);
                 }
 
-                KeyProtection.Builder good = getWorkingImportParamsForVerifying(algorithm);
-                assertInitVerifySucceeds(algorithm, good.build());
+                KeyProtection good = getMinimalWorkingImportParamsForVerifying(algorithm);
+                assertInitVerifySucceeds(algorithm, good);
                 assertInitVerifySucceeds(algorithm,
                         TestUtils.buildUpon(good).setSignaturePaddings(badPaddingScheme).build());
             } catch (Throwable e) {
@@ -896,8 +914,8 @@
         Date badStartDate = new Date(System.currentTimeMillis() + DAY_IN_MILLIS);
         for (String algorithm : EXPECTED_SIGNATURE_ALGORITHMS) {
             try {
-                KeyProtection.Builder good = getWorkingImportParamsForSigning(algorithm);
-                assertInitSignSucceeds(algorithm, good.build());
+                KeyProtection good = getMinimalWorkingImportParamsForSigning(algorithm);
+                assertInitSignSucceeds(algorithm, good);
                 assertInitSignThrowsInvalidKeyException(algorithm,
                         TestUtils.buildUpon(good).setKeyValidityStart(badStartDate).build());
             } catch (Throwable e) {
@@ -910,8 +928,8 @@
         Date badStartDate = new Date(System.currentTimeMillis() + DAY_IN_MILLIS);
         for (String algorithm : EXPECTED_SIGNATURE_ALGORITHMS) {
             try {
-                KeyProtection.Builder good = getWorkingImportParamsForVerifying(algorithm);
-                assertInitVerifySucceeds(algorithm, good.build());
+                KeyProtection good = getMinimalWorkingImportParamsForVerifying(algorithm);
+                assertInitVerifySucceeds(algorithm, good);
                 assertInitVerifySucceeds(algorithm,
                         TestUtils.buildUpon(good).setKeyValidityStart(badStartDate).build());
             } catch (Throwable e) {
@@ -924,8 +942,8 @@
         Date badEndDate = new Date(System.currentTimeMillis() - DAY_IN_MILLIS);
         for (String algorithm : EXPECTED_SIGNATURE_ALGORITHMS) {
             try {
-                KeyProtection.Builder good = getWorkingImportParamsForSigning(algorithm);
-                assertInitSignSucceeds(algorithm, good.build());
+                KeyProtection good = getMinimalWorkingImportParamsForSigning(algorithm);
+                assertInitSignSucceeds(algorithm, good);
                 assertInitSignThrowsInvalidKeyException(algorithm,
                         TestUtils.buildUpon(good)
                                 .setKeyValidityForOriginationEnd(badEndDate)
@@ -940,8 +958,8 @@
         Date badEndDate = new Date(System.currentTimeMillis() - DAY_IN_MILLIS);
         for (String algorithm : EXPECTED_SIGNATURE_ALGORITHMS) {
             try {
-                KeyProtection.Builder good = getWorkingImportParamsForVerifying(algorithm);
-                assertInitVerifySucceeds(algorithm, good.build());
+                KeyProtection good = getMinimalWorkingImportParamsForVerifying(algorithm);
+                assertInitVerifySucceeds(algorithm, good);
                 assertInitVerifySucceeds(algorithm,
                         TestUtils.buildUpon(good)
                                 .setKeyValidityForOriginationEnd(badEndDate)
@@ -956,8 +974,8 @@
         Date badEndDate = new Date(System.currentTimeMillis() - DAY_IN_MILLIS);
         for (String algorithm : EXPECTED_SIGNATURE_ALGORITHMS) {
             try {
-                KeyProtection.Builder good = getWorkingImportParamsForSigning(algorithm);
-                assertInitSignSucceeds(algorithm, good.build());
+                KeyProtection good = getMinimalWorkingImportParamsForSigning(algorithm);
+                assertInitSignSucceeds(algorithm, good);
                 assertInitSignSucceeds(algorithm,
                         TestUtils.buildUpon(good)
                                 .setKeyValidityForConsumptionEnd(badEndDate)
@@ -972,8 +990,8 @@
         Date badEndDate = new Date(System.currentTimeMillis() - DAY_IN_MILLIS);
         for (String algorithm : EXPECTED_SIGNATURE_ALGORITHMS) {
             try {
-                KeyProtection.Builder good = getWorkingImportParamsForVerifying(algorithm);
-                assertInitVerifySucceeds(algorithm, good.build());
+                KeyProtection good = getMinimalWorkingImportParamsForVerifying(algorithm);
+                assertInitVerifySucceeds(algorithm, good);
                 assertInitVerifySucceeds(algorithm,
                         TestUtils.buildUpon(good)
                                 .setKeyValidityForConsumptionEnd(badEndDate)
@@ -1001,10 +1019,8 @@
             int certResId,
             KeyProtection keyProtection) throws Exception {
         PublicKey publicKey = TestUtils.importIntoAndroidKeyStore(
-                "test1",
-                TestUtils.getRawResPrivateKey(getContext(), privateKeyResId),
-                TestUtils.getRawResX509Certificate(getContext(), certResId),
-                keyProtection)
+                "test1", getContext(), privateKeyResId, certResId, keyProtection)
+                .getKeystoreBackedKeyPair()
                 .getPublic();
         Signature signature = Signature.getInstance(signatureAlgorithm, EXPECTED_PROVIDER_NAME);
         signature.initVerify(publicKey);
@@ -1027,10 +1043,8 @@
             int certResId,
             KeyProtection keyProtection) throws Exception {
         PrivateKey privateKey = TestUtils.importIntoAndroidKeyStore(
-                "test1",
-                TestUtils.getRawResPrivateKey(getContext(), privateKeyResId),
-                TestUtils.getRawResX509Certificate(getContext(), certResId),
-                keyProtection)
+                "test1", getContext(), privateKeyResId, certResId, keyProtection)
+                .getKeystoreBackedKeyPair()
                 .getPrivate();
         Signature signature = Signature.getInstance(signatureAlgorithm, EXPECTED_PROVIDER_NAME);
         signature.initSign(privateKey);
@@ -1062,10 +1076,8 @@
             int certResId,
             KeyProtection keyProtection) throws Exception {
         PrivateKey privateKey = TestUtils.importIntoAndroidKeyStore(
-                "test1",
-                TestUtils.getRawResPrivateKey(getContext(), privateKeyResId),
-                TestUtils.getRawResX509Certificate(getContext(), certResId),
-                keyProtection)
+                "test1", getContext(), privateKeyResId, certResId, keyProtection)
+                .getKeystoreBackedKeyPair()
                 .getPrivate();
         Signature signature = Signature.getInstance(signatureAlgorithm, EXPECTED_PROVIDER_NAME);
         try {
@@ -1075,72 +1087,39 @@
     }
 
     static int[] getDefaultKeyAndCertResIds(String signatureAlgorithm) {
-        String sigAlgLowerCase = signatureAlgorithm.toLowerCase();
-        if (sigAlgLowerCase.contains("ecdsa")) {
+        String keyAlgorithm = TestUtils.getSignatureAlgorithmKeyAlgorithm(signatureAlgorithm);
+        if (KeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(keyAlgorithm)) {
             return new int[] {R.raw.ec_key1_pkcs8, R.raw.ec_key1_cert};
-        } else if (sigAlgLowerCase.contains("rsa")) {
+        } else if (KeyProperties.KEY_ALGORITHM_RSA.equalsIgnoreCase(keyAlgorithm)) {
             return new int[] {R.raw.rsa_key1_pkcs8, R.raw.rsa_key1_cert};
         } else {
-            throw new IllegalArgumentException(
-                    "Unknown signature algorithm: " + signatureAlgorithm);
+            throw new IllegalArgumentException("Unknown key algorithm: " + keyAlgorithm);
         }
     }
 
-    private static String getKeyAlgorithmForSignatureAlgorithm(String signatureAlgorithm) {
-        String algLowerCase = signatureAlgorithm.toLowerCase();
-        if (algLowerCase.contains("withecdsa")) {
-            return KeyProperties.KEY_ALGORITHM_EC;
-        } else if (algLowerCase.contains("withrsa")) {
-            return KeyProperties.KEY_ALGORITHM_RSA;
+    private ImportedKey importDefaultKatKeyPair(String signatureAlgorithm) throws Exception {
+        String keyAlgorithm = TestUtils.getSignatureAlgorithmKeyAlgorithm(signatureAlgorithm);
+        KeyProtection importParams =
+                TestUtils.getMinimalWorkingImportParametersForSigningingWith(signatureAlgorithm);
+        if (KeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(keyAlgorithm)) {
+            return TestUtils.importIntoAndroidKeyStore(
+                    "testEc",
+                    getContext(),
+                    R.raw.ec_key1_pkcs8,
+                    R.raw.ec_key1_cert,
+                    importParams);
+        } else if (KeyProperties.KEY_ALGORITHM_RSA.equalsIgnoreCase(keyAlgorithm)) {
+            return TestUtils.importIntoAndroidKeyStore(
+                    "testRsa",
+                    getContext(),
+                    R.raw.rsa_key1_pkcs8,
+                    R.raw.rsa_key1_cert,
+                    importParams);
         } else {
-            throw new IllegalArgumentException(
-                    "Unsupported signature algorithm: " + signatureAlgorithm);
+            throw new IllegalArgumentException("Unsupported key algorithm: " + keyAlgorithm);
         }
     }
 
-    private static KeyPair getKeyPairForSignatureAlgorithm(String signatureAlgorithm,
-            Iterable<KeyPair> keyPairs) {
-        return TestUtils.getKeyPairForKeyAlgorithm(
-                getKeyAlgorithmForSignatureAlgorithm(signatureAlgorithm), keyPairs);
-    }
-
-    private Collection<KeyPair> getDefaultKatKeyPairs() throws Exception {
-        return Arrays.asList(
-                new KeyPair(
-                        TestUtils.getRawResX509Certificate(getContext(), R.raw.rsa_key1_cert)
-                                .getPublicKey(),
-                        TestUtils.getRawResPrivateKey(getContext(), R.raw.rsa_key1_pkcs8)),
-                new KeyPair(
-                        TestUtils.getRawResX509Certificate(getContext(), R.raw.ec_key1_cert)
-                                .getPublicKey(),
-                        TestUtils.getRawResPrivateKey(getContext(), R.raw.ec_key1_pkcs8))
-                );
-    }
-
-    private Collection<KeyPair> importDefaultKatKeyPairs() throws Exception {
-        return Arrays.asList(
-                TestUtils.importIntoAndroidKeyStore(
-                        "testRsa",
-                        TestUtils.getRawResPrivateKey(getContext(), R.raw.rsa_key1_pkcs8),
-                        TestUtils.getRawResX509Certificate(getContext(), R.raw.rsa_key1_cert),
-                        new KeyProtection.Builder(
-                                KeyProperties.PURPOSE_SIGN)
-                                .setDigests(KeyProperties.DIGEST_NONE)
-                                .setSignaturePaddings(
-                                        KeyProperties.SIGNATURE_PADDING_RSA_PKCS1,
-                                        KeyProperties.SIGNATURE_PADDING_RSA_PSS)
-                                .build()),
-                TestUtils.importIntoAndroidKeyStore(
-                        "testEc",
-                        TestUtils.getRawResPrivateKey(getContext(), R.raw.ec_key1_pkcs8),
-                        TestUtils.getRawResX509Certificate(getContext(), R.raw.ec_key1_cert),
-                        new KeyProtection.Builder(
-                                KeyProperties.PURPOSE_SIGN)
-                                .setDigests(KeyProperties.DIGEST_NONE)
-                                .build())
-                );
-    }
-
     private void assertSignatureVerifiesOneShot(
             String algorithm,
             PublicKey publicKey,
@@ -1251,26 +1230,28 @@
         }
     }
 
-    private static KeyProtection.Builder getWorkingImportParamsForSigning(String algorithm) {
-        KeyProtection.Builder result = new KeyProtection.Builder(
-                KeyProperties.PURPOSE_SIGN)
-                .setDigests(KeyProperties.DIGEST_NONE);
-        String algorithmUpperCase = algorithm.toUpperCase(Locale.US);
-        if (algorithmUpperCase.endsWith("WITHECDSA")) {
-            // No need for padding
-        } else if (algorithmUpperCase.endsWith("WITHRSA")) {
-            result.setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PKCS1);
-        } else if (algorithmUpperCase.endsWith("WITHRSA/PSS")) {
-            result.setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PSS);
-        } else {
-            throw new IllegalArgumentException("Unsupported algorithm: " + algorithm);
-        }
-        return result;
+    private static KeyProtection getMinimalWorkingImportParamsForSigning(String algorithm) {
+        return TestUtils.getMinimalWorkingImportParametersForSigningingWith(algorithm);
     }
 
-    private static KeyProtection.Builder getWorkingImportParamsForVerifying(String algorithm) {
-        return TestUtils.buildUpon(
-                getWorkingImportParamsForSigning(algorithm),
-                KeyProperties.PURPOSE_VERIFY);
+    private static KeyProtection getMinimalWorkingImportParamsForVerifying(
+            @SuppressWarnings("unused") String algorithm) {
+        // No need to authorize anything because verification does not use the private key.
+        // Operations using public keys do not need authorization.
+        return new KeyProtection.Builder(0).build();
+    }
+
+    static Collection<ImportedKey> importKatKeyPairsForSigning(
+            Context context, String signatureAlgorithm) throws Exception {
+        String keyAlgorithm = TestUtils.getSignatureAlgorithmKeyAlgorithm(signatureAlgorithm);
+        KeyProtection importParams =
+                TestUtils.getMinimalWorkingImportParametersForSigningingWith(signatureAlgorithm);
+        if (KeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(keyAlgorithm)) {
+            return ECDSASignatureTest.importKatKeyPairs(context, importParams);
+        } else if (KeyProperties.KEY_ALGORITHM_RSA.equalsIgnoreCase(keyAlgorithm)) {
+            return RSASignatureTest.importKatKeyPairs(context, importParams);
+        } else {
+            throw new IllegalArgumentException("Unsupported key algorithm: " + keyAlgorithm);
+        }
     }
 }
diff --git a/tests/tests/keystore/src/android/keystore/cts/TestUtils.java b/tests/tests/keystore/src/android/keystore/cts/TestUtils.java
index 8d4a61f..423c32b 100644
--- a/tests/tests/keystore/src/android/keystore/cts/TestUtils.java
+++ b/tests/tests/keystore/src/android/keystore/cts/TestUtils.java
@@ -27,10 +27,10 @@
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.math.BigInteger;
 import java.security.Key;
 import java.security.KeyFactory;
 import java.security.KeyPair;
-import java.security.KeyPairGenerator;
 import java.security.KeyStore;
 import java.security.KeyStoreException;
 import java.security.MessageDigest;
@@ -114,7 +114,7 @@
         }
     }
 
-    private static int getKeySizeBits(Key key) {
+    static int getKeySizeBits(Key key) {
         if (key instanceof ECKey) {
             return ((ECKey) key).getParams().getCurve().getField().getFieldSize();
         } else if (key instanceof RSAKey) {
@@ -374,18 +374,6 @@
         return result;
     }
 
-    static Certificate generateSelfSignedCert(String keyAlgorithm) throws Exception {
-        KeyPairGenerator generator =
-                KeyPairGenerator.getInstance(keyAlgorithm, "AndroidKeyStore");
-        generator.initialize(new KeyGenParameterSpec.Builder(
-                "test1",
-                KeyProperties.PURPOSE_SIGN)
-                .build());
-        KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
-        keyStore.load(null);
-        return keyStore.getCertificate("test1");
-    }
-
     static PrivateKey getRawResPrivateKey(Context context, int resId) throws Exception {
         byte[] pkcs8EncodedForm;
         try (InputStream in = context.getResources().openRawResource(resId)) {
@@ -438,6 +426,50 @@
         return (SecretKey) keyStore.getKey(alias, null);
     }
 
+    static ImportedKey importIntoAndroidKeyStore(
+            String alias, Context context, int privateResId, int certResId, KeyProtection params)
+                    throws Exception {
+        Certificate originalCert = TestUtils.getRawResX509Certificate(context, certResId);
+        PublicKey originalPublicKey = originalCert.getPublicKey();
+        PrivateKey originalPrivateKey = TestUtils.getRawResPrivateKey(context, privateResId);
+
+        // Check that the domain parameters match between the private key and the public key. This
+        // is to catch accidental errors where a test provides the wrong resource ID as one of the
+        // parameters.
+        if (!originalPublicKey.getAlgorithm().equalsIgnoreCase(originalPrivateKey.getAlgorithm())) {
+            throw new IllegalArgumentException("Key algorithm mismatch."
+                    + " Public: " + originalPublicKey.getAlgorithm()
+                    + ", private: " + originalPrivateKey.getAlgorithm());
+        }
+        String keyAlgorithm = originalPublicKey.getAlgorithm();
+        if (KeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(keyAlgorithm)) {
+            ECParameterSpec publicKeyParams = ((ECKey) originalPublicKey).getParams();
+            ECParameterSpec privateKeyParams = ((ECKey) originalPrivateKey).getParams();
+            assertECParameterSpecEqualsIgnoreSeedIfNotPresent(
+                    publicKeyParams, privateKeyParams);
+        } else if (KeyProperties.KEY_ALGORITHM_RSA.equalsIgnoreCase(keyAlgorithm)) {
+            BigInteger publicKeyModulus = ((RSAKey) originalPublicKey).getModulus();
+            BigInteger privateKeyModulus = ((RSAKey) originalPrivateKey).getModulus();
+            if (!publicKeyModulus.equals(privateKeyModulus)) {
+                throw new IllegalArgumentException("RSA key pair modulus mismatch."
+                        + " Public (" + publicKeyModulus.bitLength() + " bit): "
+                        + publicKeyModulus.toString(16)
+                        + ", private (" + privateKeyModulus.bitLength() + " bit): "
+                        + privateKeyModulus.toString(16));
+            }
+        } else {
+            throw new IllegalArgumentException("Unsupported key algorithm: " + keyAlgorithm);
+        }
+
+        KeyPair keystoreBacked = TestUtils.importIntoAndroidKeyStore(
+                alias, originalPrivateKey, originalCert,
+                params);
+        return new ImportedKey(
+                alias,
+                new KeyPair(originalCert.getPublicKey(), originalPrivateKey),
+                keystoreBacked);
+    }
+
     static byte[] drain(InputStream in) throws IOException {
         ByteArrayOutputStream result = new ByteArrayOutputStream();
         byte[] buffer = new byte[16 * 1024];
@@ -448,19 +480,26 @@
         return result.toByteArray();
     }
 
+    static KeyProtection.Builder buildUpon(KeyProtection params) {
+        return buildUponInternal(params, null);
+    }
+
+    static KeyProtection.Builder buildUpon(KeyProtection params, int newPurposes) {
+        return buildUponInternal(params, newPurposes);
+    }
+
     static KeyProtection.Builder buildUpon(
             KeyProtection.Builder builder) {
-        return buildUponInternal(builder, null);
+        return buildUponInternal(builder.build(), null);
     }
 
     static KeyProtection.Builder buildUpon(
             KeyProtection.Builder builder, int newPurposes) {
-        return buildUponInternal(builder, newPurposes);
+        return buildUponInternal(builder.build(), newPurposes);
     }
 
     private static KeyProtection.Builder buildUponInternal(
-            KeyProtection.Builder builder, Integer newPurposes) {
-        KeyProtection spec = builder.build();
+            KeyProtection spec, Integer newPurposes) {
         int purposes = (newPurposes == null) ? spec.getPurposes() : newPurposes;
         KeyProtection.Builder result = new KeyProtection.Builder(purposes);
         result.setBlockModes(spec.getBlockModes());
@@ -479,19 +518,26 @@
         return result;
     }
 
+    static KeyGenParameterSpec.Builder buildUpon(KeyGenParameterSpec spec) {
+        return buildUponInternal(spec, null);
+    }
+
+    static KeyGenParameterSpec.Builder buildUpon(KeyGenParameterSpec spec, int newPurposes) {
+        return buildUponInternal(spec, newPurposes);
+    }
+
     static KeyGenParameterSpec.Builder buildUpon(
             KeyGenParameterSpec.Builder builder) {
-        return buildUponInternal(builder, null);
+        return buildUponInternal(builder.build(), null);
     }
 
     static KeyGenParameterSpec.Builder buildUpon(
             KeyGenParameterSpec.Builder builder, int newPurposes) {
-        return buildUponInternal(builder, newPurposes);
+        return buildUponInternal(builder.build(), newPurposes);
     }
 
     private static KeyGenParameterSpec.Builder buildUponInternal(
-            KeyGenParameterSpec.Builder builder, Integer newPurposes) {
-        KeyGenParameterSpec spec = builder.build();
+            KeyGenParameterSpec spec, Integer newPurposes) {
         int purposes = (newPurposes == null) ? spec.getPurposes() : newPurposes;
         KeyGenParameterSpec.Builder result =
                 new KeyGenParameterSpec.Builder(spec.getKeystoreAlias(), purposes);
@@ -588,6 +634,95 @@
         return result;
     }
 
+    static String getSignatureAlgorithmDigest(String algorithm) {
+        String algorithmUpperCase = algorithm.toUpperCase(Locale.US);
+        int withIndex = algorithmUpperCase.indexOf("WITH");
+        if (withIndex == -1) {
+            throw new IllegalArgumentException("Unsupported algorithm: " + algorithm);
+        }
+        String digest = algorithmUpperCase.substring(0, withIndex);
+        if (digest.startsWith("SHA")) {
+            digest = "SHA-" + digest.substring("SHA".length());
+        }
+        return digest;
+    }
+
+    static String getSignatureAlgorithmPadding(String algorithm) {
+        String algorithmUpperCase = algorithm.toUpperCase(Locale.US);
+        if (algorithmUpperCase.endsWith("WITHECDSA")) {
+            return null;
+        } else if (algorithmUpperCase.endsWith("WITHRSA")) {
+            return KeyProperties.SIGNATURE_PADDING_RSA_PKCS1;
+        } else if (algorithmUpperCase.endsWith("WITHRSA/PSS")) {
+            return KeyProperties.SIGNATURE_PADDING_RSA_PSS;
+        } else {
+            throw new IllegalArgumentException("Unsupported algorithm: " + algorithm);
+        }
+    }
+
+    static String getSignatureAlgorithmKeyAlgorithm(String algorithm) {
+        String algorithmUpperCase = algorithm.toUpperCase(Locale.US);
+        if (algorithmUpperCase.endsWith("WITHECDSA")) {
+            return KeyProperties.KEY_ALGORITHM_EC;
+        } else if ((algorithmUpperCase.endsWith("WITHRSA"))
+                || (algorithmUpperCase.endsWith("WITHRSA/PSS"))) {
+            return KeyProperties.KEY_ALGORITHM_RSA;
+        } else {
+            throw new IllegalArgumentException("Unsupported algorithm: " + algorithm);
+        }
+    }
+
+    static boolean isKeyLongEnoughForSignatureAlgorithm(String algorithm, Key key) {
+        String keyAlgorithm = key.getAlgorithm();
+        if (KeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(keyAlgorithm)) {
+            // No length restrictions for ECDSA
+            return true;
+        } else if (KeyProperties.KEY_ALGORITHM_RSA.equalsIgnoreCase(keyAlgorithm)) {
+            // No length restrictions for RSA
+            String digest = getSignatureAlgorithmDigest(algorithm);
+            int digestOutputSizeBits = getDigestOutputSizeBits(digest);
+            if (digestOutputSizeBits == -1) {
+                // No digesting -- assume the key is long enough for the message
+                return true;
+            }
+            String paddingScheme = getSignatureAlgorithmPadding(algorithm);
+            int paddingOverheadBytes;
+            if (KeyProperties.SIGNATURE_PADDING_RSA_PKCS1.equalsIgnoreCase(paddingScheme)) {
+                paddingOverheadBytes = 30;
+            } else if (KeyProperties.SIGNATURE_PADDING_RSA_PSS.equalsIgnoreCase(paddingScheme)) {
+                paddingOverheadBytes = 22;
+            } else {
+                throw new IllegalArgumentException(
+                        "Unsupported signature padding scheme: " + paddingScheme);
+            }
+            int minKeySizeBytes = paddingOverheadBytes + (digestOutputSizeBits + 7) / 8 + 1;
+            int keySizeBytes = ((RSAKey) key).getModulus().bitLength() / 8;
+            return keySizeBytes >= minKeySizeBytes;
+        } else {
+            throw new IllegalArgumentException("Unsupported key algorithm: " + keyAlgorithm);
+        }
+    }
+
+    static int getDigestOutputSizeBits(String digest) {
+        if (KeyProperties.DIGEST_NONE.equals(digest)) {
+            return -1;
+        } else if (KeyProperties.DIGEST_MD5.equals(digest)) {
+            return 128;
+        } else if (KeyProperties.DIGEST_SHA1.equals(digest)) {
+            return 160;
+        } else if (KeyProperties.DIGEST_SHA224.equals(digest)) {
+            return 224;
+        } else if (KeyProperties.DIGEST_SHA256.equals(digest)) {
+            return 256;
+        } else if (KeyProperties.DIGEST_SHA384.equals(digest)) {
+            return 384;
+        } else if (KeyProperties.DIGEST_SHA512.equals(digest)) {
+            return 512;
+        } else {
+            throw new IllegalArgumentException("Unsupported digest: " + digest);
+        }
+    }
+
     static byte[] concat(byte[] arr1, byte[] arr2) {
         return concat(arr1, 0, (arr1 != null) ? arr1.length : 0,
                 arr2, 0, (arr2 != null) ? arr2.length : 0);
@@ -621,4 +756,24 @@
         System.arraycopy(arr, offset, result, 0, len);
         return result;
     }
+
+    static KeyProtection getMinimalWorkingImportParametersForSigningingWith(
+            String signatureAlgorithm) {
+        String keyAlgorithm = getSignatureAlgorithmKeyAlgorithm(signatureAlgorithm);
+        String digest = getSignatureAlgorithmDigest(signatureAlgorithm);
+        if (KeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(keyAlgorithm)) {
+            return new KeyProtection.Builder(KeyProperties.PURPOSE_SIGN)
+                    .setDigests(digest)
+                    .build();
+        } else if (KeyProperties.KEY_ALGORITHM_RSA.equalsIgnoreCase(keyAlgorithm)) {
+            String padding = getSignatureAlgorithmPadding(signatureAlgorithm);
+            return new KeyProtection.Builder(KeyProperties.PURPOSE_SIGN)
+                    .setDigests(digest)
+                    .setSignaturePaddings(padding)
+                    .build();
+        } else {
+            throw new IllegalArgumentException(
+                    "Unsupported signature algorithm: " + signatureAlgorithm);
+        }
+    }
 }