Add unit tests

This commit is contained in:
Joe Farebrother
2024-02-08 11:11:48 +00:00
parent d8985f9f5b
commit 2eb93b7a3b
12 changed files with 214 additions and 6 deletions

View File

@@ -43,8 +43,8 @@ class AuthenticationSuccessCallback extends Method {
}
/** A call that sets a parameter for key generation that is insecure for use with biometric authentication. */
class InsecureBiometricKeyParam extends MethodCall {
InsecureBiometricKeyParam() {
class InsecureBiometricKeyParamCall extends MethodCall {
InsecureBiometricKeyParamCall() {
exists(string name, CompileTimeConstantExpr val |
this.getMethod()
.hasQualifiedName("android.security.keystore", "KeyGenParameterSpec$Builder", name) and
@@ -59,3 +59,6 @@ class InsecureBiometricKeyParam extends MethodCall {
)
}
}
/** Holds if the application contains an instance of a key being used for local biometric authentication. */
predicate usesLocalAuth() { exists(AuthenticationSuccessCallback cb | exists(cb.getAResultUse())) }

View File

@@ -13,9 +13,6 @@
import java
import semmle.code.java.security.AndroidLocalAuthQuery
/** Holds if the application contains an instance of a key being used for local biometric authentication. */
predicate usesLocalAuth() { exists(AuthenticationSuccessCallback cb | exists(cb.getAResultUse())) }
from InsecureBiometricKeyParam call
from InsecureBiometricKeyParamCall call
where usesLocalAuth()
select call, "This key is not secure for biometric authentication."

View File

@@ -0,0 +1,2 @@
testFailures
failures

View File

@@ -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<InsecureKeysTest>

View File

@@ -0,0 +1,21 @@
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);
builder.setUserAuthenticationRequired(false); // $insecure-key
builder.setInvalidatedByBiometricEnrollment(false); // $insecure-key
builder.setUserAuthenticationValidityDurationSeconds(30); // $insecure-key
}
}
class Callback extends BiometricPrompt.AuthenticationCallback {
public static void useKey(BiometricPrompt.CryptoObject key) {}
@Override
public void onAuthenticationSucceeded(BiometricPrompt.AuthenticationResult result) {
useKey(result.getCryptoObject());
}
}

View File

@@ -0,0 +1 @@
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../../stubs/google-android-9.0.0

View File

@@ -0,0 +1,2 @@
testFailures
failures

View File

@@ -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<InsecureKeysTest>

View File

@@ -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);
}
}

View File

@@ -0,0 +1 @@
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../../stubs/google-android-9.0.0

View File

@@ -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; }
}
}

View File

@@ -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;
}