diff --git a/java/ql/lib/semmle/code/java/security/AndroidLocalAuthQuery.qll b/java/ql/lib/semmle/code/java/security/AndroidLocalAuthQuery.qll index ca725a041d5..4a31dc2568d 100644 --- a/java/ql/lib/semmle/code/java/security/AndroidLocalAuthQuery.qll +++ b/java/ql/lib/semmle/code/java/security/AndroidLocalAuthQuery.qll @@ -1,6 +1,7 @@ /** Definitions for the insecure local authentication query. */ import java +private import semmle.code.java.dataflow.DataFlow /** A base class that is used as a callback for biometric authentication. */ private class AuthenticationCallbackClass extends Class { @@ -40,3 +41,24 @@ class AuthenticationSuccessCallback extends Method { not result = this.getASuperResultUse() } } + +/** A call that sets a parameter for key generation that is insecure for use with biometric authentication. */ +class InsecureBiometricKeyParamCall extends MethodCall { + InsecureBiometricKeyParamCall() { + exists(string name, CompileTimeConstantExpr val | + this.getMethod() + .hasQualifiedName("android.security.keystore", "KeyGenParameterSpec$Builder", name) and + DataFlow::localExprFlow(val, this.getArgument(0)) and + ( + name = ["setUserAuthenticationRequired", "setInvalidatedByBiometricEnrollment"] and + val.getBooleanValue() = false + or + name = "setUserAuthenticationValidityDurationSeconds" and + val.getIntValue() != -1 + ) + ) + } +} + +/** Holds if the application contains an instance of a key being used for local biometric authentication. */ +predicate usesLocalAuth() { exists(AuthenticationSuccessCallback cb | exists(cb.getAResultUse())) } diff --git a/java/ql/src/Security/CWE/CWE-287/AndroidInsecureKeys.qhelp b/java/ql/src/Security/CWE/CWE-287/AndroidInsecureKeys.qhelp new file mode 100644 index 00000000000..6b3546f85f5 --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-287/AndroidInsecureKeys.qhelp @@ -0,0 +1,43 @@ + + + + +

+Biometric authentication, such as fingerprint recognition, can be used alongside cryptographic keys stored in the Android KeyStore to protect sensitive parts of the application. However, +when a key generated for this purpose has certain parameters set insecurely, an attacker with physical access can bypass the +authentication check using application hooking tools such as Frida. +

+
+ + +

+When generating a key for use with biometric authentication, ensure that the following parameters of KeyGenParameterSpec.Builder are set: +

+ + +
+ + +

The following example demonstrates a key that is configured with secure paramaters:

+ + +

In each of the following cases, a parameter is set insecurely:

+ +
+ + +
  • +WithSecure: How Secure is your Android Keystore Authentication?. +
  • +
  • +Android Developers: KeyGenParameterSpec.Builder. +
  • + +
    +
    diff --git a/java/ql/src/Security/CWE/CWE-287/AndroidInsecureKeys.ql b/java/ql/src/Security/CWE/CWE-287/AndroidInsecureKeys.ql new file mode 100644 index 00000000000..52aaf8d885d --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-287/AndroidInsecureKeys.ql @@ -0,0 +1,18 @@ +/** + * @name Insecurely generated keys for local authentication + * @description Generation of keys with insecure parameters for local biometric authentication can allow attackers with physical access to bypass authentication checks. + * @kind problem + * @problem.severity warning + * @security-severity 4.4 + * @precision medium + * @id java/android/insecure-local-key-gen + * @tags security + * external/cwe/cwe-287 + */ + +import java +import semmle.code.java.security.AndroidLocalAuthQuery + +from InsecureBiometricKeyParamCall call +where usesLocalAuth() +select call, "This key is not secure for biometric authentication." diff --git a/java/ql/src/Security/CWE/CWE-287/AndroidInsecureKeysBad.java b/java/ql/src/Security/CWE/CWE-287/AndroidInsecureKeysBad.java new file mode 100644 index 00000000000..deb14d7a5e7 --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-287/AndroidInsecureKeysBad.java @@ -0,0 +1,47 @@ +private void generateSecretKey() { + KeyGenParameterSpec keyGenParameterSpec = new KeyGenParameterSpec.Builder( + "MySecretKey", + KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) + .setBlockModes(KeyProperties.BLOCK_MODE_CBC) + .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7) + // BAD: User authentication is not required to use this key. + .setUserAuthenticationRequired(false) + .build(); + KeyGenerator keyGenerator = KeyGenerator.getInstance( + KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore"); + keyGenerator.init(keyGenParameterSpec); + keyGenerator.generateKey(); +} + +private void generateSecretKey() { + KeyGenParameterSpec keyGenParameterSpec = new KeyGenParameterSpec.Builder( + "MySecretKey", + KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) + .setBlockModes(KeyProperties.BLOCK_MODE_CBC) + .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7) + .setUserAuthenticationRequired(true) + // BAD: An attacker can access this key by enrolling additional biometrics. + .setInvalidatedByBiometricEnrollment(false) + .build(); + KeyGenerator keyGenerator = KeyGenerator.getInstance( + KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore"); + keyGenerator.init(keyGenParameterSpec); + keyGenerator.generateKey(); +} + +private void generateSecretKey() { + KeyGenParameterSpec keyGenParameterSpec = new KeyGenParameterSpec.Builder( + "MySecretKey", + KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) + .setBlockModes(KeyProperties.BLOCK_MODE_CBC) + .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7) + .setUserAuthenticationRequired(true) + .setInvalidatedByBiometricEnrollment(true) + // BAD: This key can be accessed using non-biometric credentials. + .setUserAuthenticationValidityDurationSeconds(30) + .build(); + KeyGenerator keyGenerator = KeyGenerator.getInstance( + KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore"); + keyGenerator.init(keyGenParameterSpec); + keyGenerator.generateKey(); +} \ No newline at end of file diff --git a/java/ql/src/Security/CWE/CWE-287/AndroidInsecureKeysGood.java b/java/ql/src/Security/CWE/CWE-287/AndroidInsecureKeysGood.java new file mode 100644 index 00000000000..64f9c94f9ee --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-287/AndroidInsecureKeysGood.java @@ -0,0 +1,16 @@ +private void generateSecretKey() { + KeyGenParameterSpec keyGenParameterSpec = new KeyGenParameterSpec.Builder( + "MySecretKey", + KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) + .setBlockModes(KeyProperties.BLOCK_MODE_CBC) + .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7) + // GOOD: Secure parameters are used to generate a key for biometric authentication. + .setUserAuthenticationRequired(true) + .setInvalidatedByBiometricEnrollment(true) + .setUserAuthenticationParameters(0, KeyProperties.AUTH_BIOMETRIC_STRONG) + .build(); + KeyGenerator keyGenerator = KeyGenerator.getInstance( + KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore"); + keyGenerator.init(keyGenParameterSpec); + keyGenerator.generateKey(); +} \ No newline at end of file diff --git a/java/ql/src/change-notes/2024-02-12-android-insecure-keys.md b/java/ql/src/change-notes/2024-02-12-android-insecure-keys.md new file mode 100644 index 00000000000..1de07727796 --- /dev/null +++ b/java/ql/src/change-notes/2024-02-12-android-insecure-keys.md @@ -0,0 +1,4 @@ +--- +category: newQuery +--- +* Added a new query `java/android/insecure-local-key-gen` for finding instances of keys generated for biometric authentication in an insecure way. \ No newline at end of file diff --git a/java/ql/test/query-tests/security/CWE-287/InsecureLocalAuth.expected b/java/ql/test/query-tests/security/CWE-287/InsecureKeys/Test1/InsecureKeys.expected similarity index 100% rename from java/ql/test/query-tests/security/CWE-287/InsecureLocalAuth.expected rename to java/ql/test/query-tests/security/CWE-287/InsecureKeys/Test1/InsecureKeys.expected diff --git a/java/ql/test/query-tests/security/CWE-287/InsecureKeys/Test1/InsecureKeys.ql b/java/ql/test/query-tests/security/CWE-287/InsecureKeys/Test1/InsecureKeys.ql new file mode 100644 index 00000000000..eec3b62dfc2 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-287/InsecureKeys/Test1/InsecureKeys.ql @@ -0,0 +1,19 @@ +import java +import TestUtilities.InlineExpectationsTest +import semmle.code.java.dataflow.DataFlow +import semmle.code.java.security.AndroidLocalAuthQuery + +module InsecureKeysTest implements TestSig { + string getARelevantTag() { result = "insecure-key" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "insecure-key" and + exists(InsecureBiometricKeyParamCall call | usesLocalAuth() | + call.getLocation() = location and + element = call.toString() and + value = "" + ) + } +} + +import MakeTest diff --git a/java/ql/test/query-tests/security/CWE-287/InsecureKeys/Test1/Test.java b/java/ql/test/query-tests/security/CWE-287/InsecureKeys/Test1/Test.java new file mode 100644 index 00000000000..87e973ab774 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-287/InsecureKeys/Test1/Test.java @@ -0,0 +1,39 @@ +import android.security.keystore.KeyGenParameterSpec; +import android.hardware.biometrics.BiometricPrompt; +import android.security.keystore.KeyProperties; +import javax.crypto.KeyGenerator; + +class Test { + void test() { + KeyGenParameterSpec.Builder builder = new KeyGenParameterSpec.Builder("MySecretKey", KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT); + builder.setUserAuthenticationRequired(false); // $insecure-key + builder.setInvalidatedByBiometricEnrollment(false); // $insecure-key + builder.setUserAuthenticationValidityDurationSeconds(30); // $insecure-key + } + + private void generateSecretKey() throws Exception { + KeyGenParameterSpec keyGenParameterSpec = new KeyGenParameterSpec.Builder( + "MySecretKey", + KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) + .setBlockModes(KeyProperties.BLOCK_MODE_CBC) + .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7) + // GOOD: Secure parameters are used to generate a key for biometric authentication. + .setUserAuthenticationRequired(true) + .setInvalidatedByBiometricEnrollment(true) + .setUserAuthenticationParameters(0, KeyProperties.AUTH_BIOMETRIC_STRONG) + .build(); + KeyGenerator keyGenerator = KeyGenerator.getInstance( + KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore"); + keyGenerator.init(keyGenParameterSpec); + keyGenerator.generateKey(); + } +} + +class Callback extends BiometricPrompt.AuthenticationCallback { + public static void useKey(BiometricPrompt.CryptoObject key) {} + + @Override + public void onAuthenticationSucceeded(BiometricPrompt.AuthenticationResult result) { + useKey(result.getCryptoObject()); + } +} \ No newline at end of file diff --git a/java/ql/test/query-tests/security/CWE-287/InsecureKeys/Test1/options b/java/ql/test/query-tests/security/CWE-287/InsecureKeys/Test1/options new file mode 100644 index 00000000000..7039c596a23 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-287/InsecureKeys/Test1/options @@ -0,0 +1 @@ +//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../../stubs/google-android-9.0.0 diff --git a/java/ql/test/query-tests/security/CWE-287/InsecureKeys/Test2/InsecureKeys.expected b/java/ql/test/query-tests/security/CWE-287/InsecureKeys/Test2/InsecureKeys.expected new file mode 100644 index 00000000000..8ec8033d086 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-287/InsecureKeys/Test2/InsecureKeys.expected @@ -0,0 +1,2 @@ +testFailures +failures diff --git a/java/ql/test/query-tests/security/CWE-287/InsecureKeys/Test2/InsecureKeys.ql b/java/ql/test/query-tests/security/CWE-287/InsecureKeys/Test2/InsecureKeys.ql new file mode 100644 index 00000000000..eec3b62dfc2 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-287/InsecureKeys/Test2/InsecureKeys.ql @@ -0,0 +1,19 @@ +import java +import TestUtilities.InlineExpectationsTest +import semmle.code.java.dataflow.DataFlow +import semmle.code.java.security.AndroidLocalAuthQuery + +module InsecureKeysTest implements TestSig { + string getARelevantTag() { result = "insecure-key" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "insecure-key" and + exists(InsecureBiometricKeyParamCall call | usesLocalAuth() | + call.getLocation() = location and + element = call.toString() and + value = "" + ) + } +} + +import MakeTest diff --git a/java/ql/test/query-tests/security/CWE-287/InsecureKeys/Test2/Test.java b/java/ql/test/query-tests/security/CWE-287/InsecureKeys/Test2/Test.java new file mode 100644 index 00000000000..e65b50da888 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-287/InsecureKeys/Test2/Test.java @@ -0,0 +1,13 @@ +import android.security.keystore.KeyGenParameterSpec; +import android.hardware.biometrics.BiometricPrompt; +import android.security.keystore.KeyProperties; + +class Test { + void test() { + KeyGenParameterSpec.Builder builder = new KeyGenParameterSpec.Builder("MySecretKey", KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT); + // No alert as there is no use of biometric authentication in this application. + builder.setUserAuthenticationRequired(false); + builder.setInvalidatedByBiometricEnrollment(false); + builder.setUserAuthenticationValidityDurationSeconds(30); + } +} \ No newline at end of file diff --git a/java/ql/test/query-tests/security/CWE-287/InsecureKeys/Test2/options b/java/ql/test/query-tests/security/CWE-287/InsecureKeys/Test2/options new file mode 100644 index 00000000000..7039c596a23 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-287/InsecureKeys/Test2/options @@ -0,0 +1 @@ +//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../../stubs/google-android-9.0.0 diff --git a/java/ql/test/query-tests/security/CWE-287/InsecureLocalAuth/InsecureLocalAuth.expected b/java/ql/test/query-tests/security/CWE-287/InsecureLocalAuth/InsecureLocalAuth.expected new file mode 100644 index 00000000000..8ec8033d086 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-287/InsecureLocalAuth/InsecureLocalAuth.expected @@ -0,0 +1,2 @@ +testFailures +failures diff --git a/java/ql/test/query-tests/security/CWE-287/InsecureLocalAuth.ql b/java/ql/test/query-tests/security/CWE-287/InsecureLocalAuth/InsecureLocalAuth.ql similarity index 100% rename from java/ql/test/query-tests/security/CWE-287/InsecureLocalAuth.ql rename to java/ql/test/query-tests/security/CWE-287/InsecureLocalAuth/InsecureLocalAuth.ql diff --git a/java/ql/test/query-tests/security/CWE-287/Test.java b/java/ql/test/query-tests/security/CWE-287/InsecureLocalAuth/Test.java similarity index 100% rename from java/ql/test/query-tests/security/CWE-287/Test.java rename to java/ql/test/query-tests/security/CWE-287/InsecureLocalAuth/Test.java diff --git a/java/ql/test/query-tests/security/CWE-287/Test2.java b/java/ql/test/query-tests/security/CWE-287/InsecureLocalAuth/Test2.java similarity index 100% rename from java/ql/test/query-tests/security/CWE-287/Test2.java rename to java/ql/test/query-tests/security/CWE-287/InsecureLocalAuth/Test2.java diff --git a/java/ql/test/query-tests/security/CWE-287/options b/java/ql/test/query-tests/security/CWE-287/InsecureLocalAuth/options similarity index 67% rename from java/ql/test/query-tests/security/CWE-287/options rename to java/ql/test/query-tests/security/CWE-287/InsecureLocalAuth/options index dacd3cb21df..33cdc1ea940 100644 --- a/java/ql/test/query-tests/security/CWE-287/options +++ b/java/ql/test/query-tests/security/CWE-287/InsecureLocalAuth/options @@ -1 +1 @@ -//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/google-android-9.0.0 +//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/google-android-9.0.0 diff --git a/java/ql/test/stubs/google-android-9.0.0/android/security/keystore/KeyGenParameterSpec.java b/java/ql/test/stubs/google-android-9.0.0/android/security/keystore/KeyGenParameterSpec.java new file mode 100644 index 00000000000..7998d48428e --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/security/keystore/KeyGenParameterSpec.java @@ -0,0 +1,76 @@ +// Generated automatically from android.security.keystore.KeyGenParameterSpec for testing purposes + +package android.security.keystore; + +import java.math.BigInteger; +import java.security.spec.AlgorithmParameterSpec; +import java.util.Date; +import javax.security.auth.x500.X500Principal; + +public class KeyGenParameterSpec implements AlgorithmParameterSpec +{ + public AlgorithmParameterSpec getAlgorithmParameterSpec(){ return null; } + public BigInteger getCertificateSerialNumber(){ return null; } + public Date getCertificateNotAfter(){ return null; } + public Date getCertificateNotBefore(){ return null; } + public Date getKeyValidityForConsumptionEnd(){ return null; } + public Date getKeyValidityForOriginationEnd(){ return null; } + public Date getKeyValidityStart(){ return null; } + public String getAttestKeyAlias(){ return null; } + public String getKeystoreAlias(){ return null; } + public String[] getBlockModes(){ return null; } + public String[] getDigests(){ return null; } + public String[] getEncryptionPaddings(){ return null; } + public String[] getSignaturePaddings(){ return null; } + public X500Principal getCertificateSubject(){ return null; } + public boolean isDevicePropertiesAttestationIncluded(){ return false; } + public boolean isDigestsSpecified(){ return false; } + public boolean isInvalidatedByBiometricEnrollment(){ return false; } + public boolean isRandomizedEncryptionRequired(){ return false; } + public boolean isStrongBoxBacked(){ return false; } + public boolean isUnlockedDeviceRequired(){ return false; } + public boolean isUserAuthenticationRequired(){ return false; } + public boolean isUserAuthenticationValidWhileOnBody(){ return false; } + public boolean isUserConfirmationRequired(){ return false; } + public boolean isUserPresenceRequired(){ return false; } + public byte[] getAttestationChallenge(){ return null; } + public int getKeySize(){ return 0; } + public int getMaxUsageCount(){ return 0; } + public int getPurposes(){ return 0; } + public int getUserAuthenticationType(){ return 0; } + public int getUserAuthenticationValidityDurationSeconds(){ return 0; } + static public class Builder + { + protected Builder() {} + public Builder(String p0, int p1){} + public KeyGenParameterSpec build(){ return null; } + public KeyGenParameterSpec.Builder setAlgorithmParameterSpec(AlgorithmParameterSpec p0){ return null; } + public KeyGenParameterSpec.Builder setAttestKeyAlias(String p0){ return null; } + public KeyGenParameterSpec.Builder setAttestationChallenge(byte[] p0){ return null; } + public KeyGenParameterSpec.Builder setBlockModes(String... p0){ return null; } + public KeyGenParameterSpec.Builder setCertificateNotAfter(Date p0){ return null; } + public KeyGenParameterSpec.Builder setCertificateNotBefore(Date p0){ return null; } + public KeyGenParameterSpec.Builder setCertificateSerialNumber(BigInteger p0){ return null; } + public KeyGenParameterSpec.Builder setCertificateSubject(X500Principal p0){ return null; } + public KeyGenParameterSpec.Builder setDevicePropertiesAttestationIncluded(boolean p0){ return null; } + public KeyGenParameterSpec.Builder setDigests(String... p0){ return null; } + public KeyGenParameterSpec.Builder setEncryptionPaddings(String... p0){ return null; } + public KeyGenParameterSpec.Builder setInvalidatedByBiometricEnrollment(boolean p0){ return null; } + public KeyGenParameterSpec.Builder setIsStrongBoxBacked(boolean p0){ return null; } + public KeyGenParameterSpec.Builder setKeySize(int p0){ return null; } + public KeyGenParameterSpec.Builder setKeyValidityEnd(Date p0){ return null; } + public KeyGenParameterSpec.Builder setKeyValidityForConsumptionEnd(Date p0){ return null; } + public KeyGenParameterSpec.Builder setKeyValidityForOriginationEnd(Date p0){ return null; } + public KeyGenParameterSpec.Builder setKeyValidityStart(Date p0){ return null; } + public KeyGenParameterSpec.Builder setMaxUsageCount(int p0){ return null; } + public KeyGenParameterSpec.Builder setRandomizedEncryptionRequired(boolean p0){ return null; } + public KeyGenParameterSpec.Builder setSignaturePaddings(String... p0){ return null; } + public KeyGenParameterSpec.Builder setUnlockedDeviceRequired(boolean p0){ return null; } + public KeyGenParameterSpec.Builder setUserAuthenticationParameters(int p0, int p1){ return null; } + public KeyGenParameterSpec.Builder setUserAuthenticationRequired(boolean p0){ return null; } + public KeyGenParameterSpec.Builder setUserAuthenticationValidWhileOnBody(boolean p0){ return null; } + public KeyGenParameterSpec.Builder setUserAuthenticationValidityDurationSeconds(int p0){ return null; } + public KeyGenParameterSpec.Builder setUserConfirmationRequired(boolean p0){ return null; } + public KeyGenParameterSpec.Builder setUserPresenceRequired(boolean p0){ return null; } + } +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/security/keystore/KeyProperties.java b/java/ql/test/stubs/google-android-9.0.0/android/security/keystore/KeyProperties.java new file mode 100644 index 00000000000..b9e7a912698 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/security/keystore/KeyProperties.java @@ -0,0 +1,54 @@ +// Generated automatically from android.security.keystore.KeyProperties for testing purposes + +package android.security.keystore; + + +abstract public class KeyProperties +{ + protected KeyProperties() {} + public static String BLOCK_MODE_CBC = null; + public static String BLOCK_MODE_CTR = null; + public static String BLOCK_MODE_ECB = null; + public static String BLOCK_MODE_GCM = null; + public static String DIGEST_MD5 = null; + public static String DIGEST_NONE = null; + public static String DIGEST_SHA1 = null; + public static String DIGEST_SHA224 = null; + public static String DIGEST_SHA256 = null; + public static String DIGEST_SHA384 = null; + public static String DIGEST_SHA512 = null; + public static String ENCRYPTION_PADDING_NONE = null; + public static String ENCRYPTION_PADDING_PKCS7 = null; + public static String ENCRYPTION_PADDING_RSA_OAEP = null; + public static String ENCRYPTION_PADDING_RSA_PKCS1 = null; + public static String KEY_ALGORITHM_3DES = null; + public static String KEY_ALGORITHM_AES = null; + public static String KEY_ALGORITHM_EC = null; + public static String KEY_ALGORITHM_HMAC_SHA1 = null; + public static String KEY_ALGORITHM_HMAC_SHA224 = null; + public static String KEY_ALGORITHM_HMAC_SHA256 = null; + public static String KEY_ALGORITHM_HMAC_SHA384 = null; + public static String KEY_ALGORITHM_HMAC_SHA512 = null; + public static String KEY_ALGORITHM_RSA = null; + public static String SIGNATURE_PADDING_RSA_PKCS1 = null; + public static String SIGNATURE_PADDING_RSA_PSS = null; + public static int AUTH_BIOMETRIC_STRONG = 0; + public static int AUTH_DEVICE_CREDENTIAL = 0; + public static int ORIGIN_GENERATED = 0; + public static int ORIGIN_IMPORTED = 0; + public static int ORIGIN_SECURELY_IMPORTED = 0; + public static int ORIGIN_UNKNOWN = 0; + public static int PURPOSE_AGREE_KEY = 0; + public static int PURPOSE_ATTEST_KEY = 0; + public static int PURPOSE_DECRYPT = 0; + public static int PURPOSE_ENCRYPT = 0; + public static int PURPOSE_SIGN = 0; + public static int PURPOSE_VERIFY = 0; + public static int PURPOSE_WRAP_KEY = 0; + public static int SECURITY_LEVEL_SOFTWARE = 0; + public static int SECURITY_LEVEL_STRONGBOX = 0; + public static int SECURITY_LEVEL_TRUSTED_ENVIRONMENT = 0; + public static int SECURITY_LEVEL_UNKNOWN = 0; + public static int SECURITY_LEVEL_UNKNOWN_SECURE = 0; + public static int UNRESTRICTED_USAGE_COUNT = 0; +}