Skip to content

Commit

Permalink
Merge branch 'master' into g_master
Browse files Browse the repository at this point in the history
qingcuilu committed Sep 1, 2022
2 parents 7c0ef5a + 2bc77e6 commit 49440b0
Showing 23 changed files with 427 additions and 72 deletions.
4 changes: 2 additions & 2 deletions soter-client-sdk/build.gradle
Original file line number Diff line number Diff line change
@@ -32,8 +32,8 @@ subprojects {

ext {
minSdkVersion = 14
targetSdkVersion = 29
compileSdkVersion = 29
targetSdkVersion = 31
compileSdkVersion = 31
buildToolsVersion = '30.0.3'

javaVersion = JavaVersion.VERSION_1_7
3 changes: 2 additions & 1 deletion soter-client-sdk/gradle.properties
Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
#Tue May 09 20:42:37 CST 2017
VERSION_NAME_PREFIX=2.0.11
org.gradle.internal.publish.checksums.insecure=true
VERSION_NAME_PREFIX=2.1.8
VERSION_NAME_SUFFIX=
#VERSION_NAME_SUFFIX=-SNAPSHOT
12 changes: 11 additions & 1 deletion soter-client-sdk/gradle/android-artifacts.gradle
Original file line number Diff line number Diff line change
@@ -41,12 +41,22 @@ group = GROUP
// }
//}

def isReleaseBuild() {
return version.contains("SNAPSHOT") == false
}

def getReleaseRepositoryUrl() {
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
return properties.getProperty('RELEASE_REPOSITORY_URL')
}

def getSnapshotRepositoryUrl() {
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
return properties.getProperty('SNAPSHOT_REPOSITORY_URL')
}

def getRepositoryUsername() {
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
@@ -84,7 +94,7 @@ afterEvaluate {
publishing {
repositories {
maven {
url = getReleaseRepositoryUrl()
url = isReleaseBuild() ? getReleaseRepositoryUrl() : getSnapshotRepositoryUrl()
credentials {
username = getRepositoryUsername()
password = getRepositoryPassword()
Original file line number Diff line number Diff line change
@@ -7,6 +7,7 @@ import com.tencent.soter.soterserver.SoterExportResult;
import com.tencent.soter.soterserver.SoterSessionResult;
import com.tencent.soter.soterserver.SoterSignResult;
import com.tencent.soter.soterserver.SoterDeviceResult;
import com.tencent.soter.soterserver.SoterExtraParam;

interface ISoterService {
/**
@@ -38,5 +39,5 @@ interface ISoterService {

int getVersion();


SoterExtraParam getExtraParam(String key);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// SoterExtraParam.aidl
package com.tencent.soter.soterserver;

// Declare any non-default types here with import statements
parcelable SoterExtraParam;

Original file line number Diff line number Diff line change
@@ -58,7 +58,10 @@ public class SoterCore implements ConstantsSoter, SoterErrCode {
IMPL = getProviderSoterCore();
SLogger.i(TAG,"soter: SoterCore is call static block to init SoterCore IMPL, IMPL is null[%b]", (IMPL == null) );
}


public static SoterCoreBase getImpl() {
return IMPL;
}

public static void setUp() {
SoterCoreBeforeTreble.setUp();
Original file line number Diff line number Diff line change
@@ -19,6 +19,7 @@
import android.content.Context;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Build;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.Handler;

@@ -151,13 +152,13 @@ public boolean isCurrentTweenTimeAvailable(Context context) {
*/
public void authenticate(CryptoObject crypto, int flags,
CancellationSignal cancel, AuthenticationCallback callback,
Handler handler) {
Handler handler, Bundle extra) {
IBiometricManager IMPL = IMPL_PROVIDER.get(mBiometricType);
if (IMPL == null){
SLogger.i(TAG, "soter: Biometric provider not initialized type["+ mBiometricType +"]");
callback.onAuthenticationCancelled();
}
IMPL.authenticate(mContext, crypto, flags, cancel, callback, handler);
IMPL.authenticate(mContext, crypto, flags, cancel, callback, handler, extra);
}

/**
@@ -284,7 +285,7 @@ private interface IBiometricManager {
void authenticate(Context context,
CryptoObject crypto, int flags,
CancellationSignal cancel,
AuthenticationCallback callback, Handler handler);
AuthenticationCallback callback, Handler handler, Bundle extra);
}

private static class LegacyFingerprintManagerImpl implements IBiometricManager {
@@ -311,7 +312,7 @@ public String getBiometricName(Context context) {
public void authenticate(Context context,
CryptoObject crypto, int flags,
CancellationSignal cancel,
AuthenticationCallback callback, Handler handler) {
AuthenticationCallback callback, Handler handler, Bundle extra) {
}

}
@@ -343,13 +344,13 @@ public String getBiometricName(Context context) {
public void authenticate(Context context,
CryptoObject crypto, int flags,
CancellationSignal cancel,
AuthenticationCallback callback, Handler handler) {
AuthenticationCallback callback, Handler handler, Bundle extra) {

FingerprintManagerProxy.authenticate(
context,
wrapCryptoObject(crypto), flags,
cancel,
wrapCallback(context, callback), handler);
wrapCallback(context, callback), handler, extra);
}

private static FingerprintManagerProxy.CryptoObject wrapCryptoObject(CryptoObject cryptoObject) {
@@ -527,7 +528,7 @@ public void authenticate(Context context,
CryptoObject crypto,
int flags,
CancellationSignal cancel,
AuthenticationCallback callback, Handler handler) {
AuthenticationCallback callback, Handler handler, Bundle extra) {

FaceidManagerProxy.authenticate(
context,
Original file line number Diff line number Diff line change
@@ -19,11 +19,17 @@
import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricPrompt;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.text.TextUtils;

import com.tencent.soter.core.model.ConstantsSoter;
import com.tencent.soter.core.model.SLogger;
import com.tencent.soter.core.model.SoterCoreUtil;

@@ -44,6 +50,8 @@ final class FingerprintManagerProxy {

public static final String FINGERPRINT_SERVICE = "fingerprint";

public static boolean sCLOSE_API31 = false;

private static FingerprintManager getFingerprintManager(Context ctx) {
return (FingerprintManager) ctx.getSystemService(FINGERPRINT_SERVICE);
}
@@ -109,7 +117,19 @@ public static boolean isHardwareDetected(Context context) {
}

public static void authenticate(Context context, CryptoObject crypto, int flags, Object cancel,
AuthenticationCallback callback, Handler handler) {
AuthenticationCallback callback, Handler handler, Bundle extra) {
boolean useBiometricPrompt = extra.getBoolean("use_biometric_prompt");
SLogger.i(TAG, "use_biometric_prompt: %s, sdk_version: %s", useBiometricPrompt, Build.VERSION.SDK_INT);
if (useBiometricPrompt && Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
authenticateApi28(context, crypto, flags, cancel, callback, handler, extra);
} else {
authenticateLegacy(context, crypto, flags, cancel, callback, handler);
}
}

@SuppressLint("MissingPermission")
private static void authenticateLegacy(Context context, CryptoObject crypto, int flags, Object cancel,
AuthenticationCallback callback, Handler handler) {
if (checkSelfPermission(context, Manifest.permission.USE_FINGERPRINT) != PackageManager.PERMISSION_GRANTED) {
SLogger.e(TAG, "soter: permission check failed: authenticate");
return;
@@ -127,6 +147,34 @@ public static void authenticate(Context context, CryptoObject crypto, int flags,
SLogger.e(TAG, "soter: triggered SecurityException in authenticate! Make sure you declared USE_FINGERPRINT in AndroidManifest.xml");
}
}
@SuppressLint("MissingPermission")
private static void authenticateApi28(Context context, CryptoObject crypto, int flags, Object cancel,
final AuthenticationCallback callback, Handler handler, Bundle extra) {
if (checkSelfPermission(context, Manifest.permission.USE_BIOMETRIC) != PackageManager.PERMISSION_GRANTED) {
SLogger.e(TAG, "soter: permission check failed: authenticate");
return;
}

BiometricPrompt.Builder builder = new BiometricPrompt.Builder(context);
builder.setDeviceCredentialAllowed(false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
builder.setAllowedAuthenticators(BiometricManager.Authenticators.BIOMETRIC_STRONG);
}
builder.setTitle(extra.getString("prompt_title"));
builder.setSubtitle(extra.getString("prompt_subtitle"));
builder.setDescription(extra.getString("prompt_description"));
String promptButton = extra.getString("prompt_button");
if (TextUtils.isEmpty(promptButton)) {
promptButton = context.getString(android.R.string.cancel);
}
builder.setNegativeButton(promptButton, context.getMainExecutor(), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
callback.onAuthenticationError(ConstantsSoter.ERR_NEGATIVE_BUTTON, "click negative button");
}
});
builder.build().authenticate((android.os.CancellationSignal) cancel, context.getMainExecutor(), wrapCallback2(callback));
}

private static FingerprintManager.CryptoObject wrapCryptoObject(CryptoObject cryptoObject) {
if (cryptoObject == null) {
@@ -156,6 +204,20 @@ private static CryptoObject unwrapCryptoObject(FingerprintManager.CryptoObject c
}
}

private static CryptoObject unwrapCryptoObject(BiometricPrompt.CryptoObject cryptoObject) {
if (cryptoObject == null) {
return null;
} else if (cryptoObject.getCipher() != null) {
return new CryptoObject(cryptoObject.getCipher());
} else if (cryptoObject.getSignature() != null) {
return new CryptoObject(cryptoObject.getSignature());
} else if (cryptoObject.getMac() != null) {
return new CryptoObject(cryptoObject.getMac());
} else {
return null;
}
}

private static FingerprintManager.AuthenticationCallback wrapCallback(
final AuthenticationCallback callback) {
return new FingerprintManager.AuthenticationCallback() {
@@ -186,6 +248,30 @@ public void onAuthenticationFailed() {
};
}

private static BiometricPrompt.AuthenticationCallback wrapCallback2(final AuthenticationCallback callback) {
return new BiometricPrompt.AuthenticationCallback() {
@Override
public void onAuthenticationError(int errorCode, CharSequence errString) {
callback.onAuthenticationError(errorCode, errString);
}

@Override
public void onAuthenticationHelp(int helpCode, CharSequence helpString) {
callback.onAuthenticationHelp(helpCode, helpString);
}

@Override
public void onAuthenticationSucceeded(BiometricPrompt.AuthenticationResult result) {
callback.onAuthenticationSucceeded(new AuthenticationResultInternal(unwrapCryptoObject(result.getCryptoObject())));
}

@Override
public void onAuthenticationFailed() {
callback.onAuthenticationFailed();
}
};
}

public static class CryptoObject {

private final Signature mSignature;
Original file line number Diff line number Diff line change
@@ -31,6 +31,7 @@ public interface ConstantsSoter {
int ERR_BIOMETRIC_FAIL_MAX = 10308; //FingerprintManager.FINGERPRINT_ERROR_LOCKOUT = 7;
int ERR_BIOMETRIC_FAIL_MAX_PERMANENT = 10309; //FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT = 9;
int ERR_BIOMETRIC_WAIT_TIMEOUT = 10309;
int ERR_NEGATIVE_BUTTON = 10310;

/**biometric auth type, ths first bit means fingerprint, the second bit for faceid, and go on*/
int FINGERPRINT_AUTH = 0x1;
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package com.tencent.soter.core.model;

import android.support.annotation.NonNull;

/**
* An interface that defines biometric parameters. The vendor implements this interface to provide biometrics parameters
*/
interface ISoterExParameters {
public interface ISoterExParameters {

/**
* The type of fingerprint, will return an int.
@@ -31,6 +33,6 @@ interface ISoterExParameters {
*/
int FINGERPRINT_TYPE_UNDER_SCREEN = 2;

Object getParam(String key, Object defVal);
Object getParam(@NonNull String key, Object defVal);

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.tencent.soter.core.model;

import com.tencent.soter.core.SoterCore;

/**
* Device settings about biometrics.
*/
@@ -16,8 +18,13 @@ private SoterExParameters() {
try {
impl = (ISoterExParameters) Class.forName(SOTEREX_PROVIDER_CLASS_NAME).getDeclaredMethod("getInstance").invoke(null);
} catch (Exception e) {
e.printStackTrace();
SLogger.printErrStackTrace(TAG, e, "soter: init ext param failed.");
SLogger.e(TAG, "soter: init ext param failed.");
if (SoterCore.getSoterCoreType() == SoterCore.IS_TREBLE) {
impl = new SoterExParametersTrebleImpl();
if (SoterCore.getImpl() != null) {
SoterCore.getImpl().updateExtraParam();
}
}
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.tencent.soter.core.model;

import android.support.annotation.NonNull;

import com.tencent.soter.core.model.ISoterExParameters;

public class SoterExParametersTrebleImpl implements ISoterExParameters {

private static int fingerprintType = FINGERPRINT_TYPE_UNDEFINE;

private static int[] fingerprintPosition = null;

@Override
public Object getParam(@NonNull String key, Object defVal) {
synchronized (SoterExParametersTrebleImpl.class) {
if (FINGERPRINT_TYPE.equals(key)) {
return fingerprintType != FINGERPRINT_TYPE_UNDEFINE ? fingerprintType : defVal;
} else if (FINGERPRINT_HARDWARE_POSITION.equals(key)) {
return fingerprintPosition != null ? fingerprintPosition : defVal;
}
return null;
}
}

public static void setParam(@NonNull String key, Object value) {
synchronized (SoterExParametersTrebleImpl.class) {
if (FINGERPRINT_TYPE.equals(key)) {
fingerprintType = (int) value;
} else if (FINGERPRINT_HARDWARE_POSITION.equals(key)) {
fingerprintPosition = (int[]) value;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -144,6 +144,13 @@ public void releaseTrebleServiceConnection() {

public void setTrebleServiceListener(SoterCoreTrebleServiceListener listener) {

}

/**
* update system extra param(such as FingerType, FingerIconPosition) by SoterService
*/
public void updateExtraParam() {

}

public abstract Signature initAuthKeySignature(String useKeyAlias) throws InvalidKeyException, NoSuchProviderException,
Original file line number Diff line number Diff line change
@@ -11,8 +11,11 @@
import android.os.RemoteException;
import android.os.SystemClock;

import com.tencent.soter.core.model.ISoterExParameters;
import com.tencent.soter.core.model.SoterExParametersTrebleImpl;
import com.tencent.soter.soterserver.ISoterService;
import com.tencent.soter.soterserver.SoterExportResult;
import com.tencent.soter.soterserver.SoterExtraParam;
import com.tencent.soter.soterserver.SoterSessionResult;
import com.tencent.soter.soterserver.SoterSignResult;
import com.tencent.soter.core.model.ConstantsSoter;
@@ -50,7 +53,10 @@ public class SoterCoreTreble extends SoterCoreBase implements ConstantsSoter, So

private int disconnectCount = 0;

private int noResponseCount = 0;
private static final int DELAY_THRESHOLD = 30;
//Fib(3)=2
private static final int INITIAL_FIB_VALUE = 3;
private int noResponseCount = INITIAL_FIB_VALUE;

private long lastBindTime = 0L;

@@ -80,8 +86,9 @@ public class SoterCoreTreble extends SoterCoreBase implements ConstantsSoter, So
public void binderDied() {
// TODO Auto-generated method stub
SLogger.i(TAG, "soter: binder died");
if (mSoterService == null)
if (mSoterService == null || mSoterService.asBinder() == null) {
return;
}

mSoterService.asBinder().unlinkToDeath(mDeathRecipient, 0);
mSoterService = null;
@@ -104,7 +111,9 @@ public void onServiceConnected(
synchronized (lock) {
connectState = CONNECTED;
}
noResponseCount = 0;
// when connected, reset fib and cancel retryFunc.
noResponseCount = INITIAL_FIB_VALUE;
mMainLooperHandler.removeCallbacks(retryFunc);
try {
service.linkToDeath(mDeathRecipient, 0);
mSoterService = ISoterService.Stub.asInterface(service);
@@ -123,15 +132,19 @@ public void onServiceConnected(

public void onServiceDisconnected(ComponentName className) {
synchronized (lock) {
SLogger.i(TAG, "soter: unBinding is done - Service disconnected");
connectState = DISCONNECT;
mSoterService = null;
noResponseCount = 0;
if (getFib(noResponseCount) > DELAY_THRESHOLD) {
//when delay time large than DELAY_THRESHOLD second, reset fib value
SLogger.i(TAG, "soter: rest fib, now is delay %dS", getFib(noResponseCount));
noResponseCount = INITIAL_FIB_VALUE;
mMainLooperHandler.removeCallbacks(retryFunc);
}
if (serviceListener != null) {
serviceListener.onServiceDisconnected();
}

SLogger.i(TAG, "soter: unBinding is done - Service disconnected");

rebindService();

syncJob.countDown();
@@ -143,7 +156,12 @@ public void onBindingDied(ComponentName name) {
SLogger.i(TAG, "soter: binding died");
connectState = DISCONNECT;
mSoterService = null;
noResponseCount = 0;
if (getFib(noResponseCount) > DELAY_THRESHOLD) {
//when delay time large than DELAY_THRESHOLD second, reset fib value
SLogger.i(TAG, "soter: rest fib, now is delay %dS", getFib(noResponseCount));
noResponseCount = INITIAL_FIB_VALUE;
mMainLooperHandler.removeCallbacks(retryFunc);
}
unbindService();
rebindService();
}
@@ -157,7 +175,7 @@ private void rebindService() {
long duration = (SystemClock.elapsedRealtime() - lastBindTime) / 1000;
long fib = getFib(disconnectCount);
long delay = fib - duration;
SLogger.d(TAG, "fib: %s, rebind delay: %sS", fib, delay);
SLogger.i(TAG, "fib: %s, rebind delay: %sS", fib, delay);
if (delay <= 0) {
bindService();
} else {
@@ -227,15 +245,23 @@ public void setTrebleServiceListener(SoterCoreTrebleServiceListener listener) {
}

public void bindServiceIfNeeded() {
if (connectState != CONNECTED || mSoterService == null || !mSoterService.asBinder().isBinderAlive() || !mSoterService.asBinder().pingBinder()) {
SLogger.i(TAG, "soter: bindServiceIfNeeded try to bind");
bindService();
} else {
SLogger.d(TAG, "no need rebind");
try {
if (connectState != CONNECTED || mSoterService == null || mSoterService.asBinder() == null || !mSoterService.asBinder().isBinderAlive() || !mSoterService.asBinder().pingBinder()) {
SLogger.i(TAG, "soter: bindServiceIfNeeded try to bind");
bindService();
} else {
SLogger.i(TAG, "no need rebind");
}
} catch (Exception e) {
SLogger.printErrStackTrace(TAG, e, "soter: bindServiceIfNeeded fail: ");
}
}

public void bindService() {
bindService(false);
}

private void bindService(boolean isCycle) {
Intent intent = new Intent();
intent.setAction("com.tencent.soter.soterserver.ISoterService");
intent.setPackage("com.tencent.soter.soterserver");
@@ -249,31 +275,38 @@ public void bindService() {
if (serviceListener != null) {
serviceListener.onStartServiceConnecting();
}


SLogger.i(TAG, "soter: bindService binding is start ");
lastBindTime = SystemClock.elapsedRealtime();

hasBind = mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);

scheduleTimeoutTask();

SLogger.i(TAG, "soter: bindService binding is start ");
scheduleTimeoutTask(isCycle);
}

private void scheduleTimeoutTask() {
final long checkDelay = getFib(noResponseCount + 3);
mMainLooperHandler.postDelayed(new Runnable() {
@Override
public void run() {
if (!canRetry || !isInitializeSuccessed) {
return;
}
noResponseCount++;
if (connectState != CONNECTED) {
SLogger.i(TAG, "soter: bindservice no response: %s", checkDelay);
bindService();
}

private Runnable retryFunc = new Runnable() {
@Override
public void run() {
if (!canRetry || !isInitializeSuccessed) {
SLogger.i(TAG, "soter: retryFunc stop, canRetry:%b isInitializeSuccessed:%b", canRetry, isInitializeSuccessed);
return;
}
}, checkDelay * 1000);

noResponseCount++;
if (connectState != CONNECTED) {
SLogger.i(TAG, "soter: retryFunc bindservice no response: %d delay: %d", noResponseCount, getFib(noResponseCount));
bindService(true);
} else {
SLogger.i(TAG, "soter: retryFunc stop, CONNECTED");
}
}
};

private void scheduleTimeoutTask(boolean isCycle) {
final long checkDelay = getFib(noResponseCount);
SLogger.i(TAG, "soter: scheduleTimeoutTask isCycle:%b noResponseCount:%d checkDelay:%d ", isCycle, noResponseCount, checkDelay);
if (isCycle || noResponseCount <= INITIAL_FIB_VALUE) {
mMainLooperHandler.postDelayed(retryFunc, checkDelay * 1000);
}
}

public void unbindService(){
@@ -333,7 +366,7 @@ public SoterCoreResult generateAppGlobalSecureKey() {
if(mSoterService.generateAppSecureKey(uid) == ERR_OK) {
return new SoterCoreResult(ERR_OK);
}
} catch (RemoteException e) {
} catch (Exception e) {
SLogger.printErrStackTrace(TAG, e, "soter: generateAppSecureKey fail: ");
}
return new SoterCoreResult(ERR_ASK_GEN_FAILED);
@@ -363,7 +396,7 @@ public SoterCoreResult removeAppGlobalSecureKey() {
if(mSoterService.removeAllAuthKey(uid) == ERR_OK) {
return new SoterCoreResult(ERR_OK);
}
} catch (RemoteException e) {
} catch (Exception e) {
SLogger.printErrStackTrace(TAG, e, "soter: removeAppGlobalSecureKey fail: ");
}
return new SoterCoreResult(ERR_REMOVE_ASK);
@@ -392,7 +425,7 @@ public boolean hasAppGlobalSecureKey() {

try {
return mSoterService.hasAskAlready(uid);
} catch (RemoteException e) {
} catch (Exception e) {
SLogger.printErrStackTrace(TAG, e, "soter: hasAppGlobalSecureKey fail: ");
return false;
}
@@ -439,7 +472,7 @@ public SoterPubKeyModel getAppGlobalSecureKeyModel() {
SLogger.e(TAG, "soter: soter: key can not be retrieved");
return null;
}
} catch (RemoteException e) {
} catch (Exception e) {
SLogger.printErrStackTrace(TAG, e, "soter: getAppGlobalSecureKeyModel fail: ");
}
return null;
@@ -470,7 +503,7 @@ public SoterCoreResult generateAuthKey(String authKeyName) {
if(mSoterService.generateAuthKey(uid, authKeyName) == ERR_OK) {
return new SoterCoreResult(ERR_OK);
}
} catch (RemoteException e) {
} catch (Exception e) {
SLogger.printErrStackTrace(TAG, e, "soter: generateAuthKey fail: ");
}

@@ -508,7 +541,7 @@ public SoterCoreResult removeAuthKey(String authKeyName, boolean isAutoDeleteASK
}
return new SoterCoreResult(ERR_OK);
}
} catch (RemoteException e) {
} catch (Exception e) {
SLogger.printErrStackTrace(TAG, e, "soter: removeAuthKey fail: ");
}
return new SoterCoreResult(ERR_REMOVE_AUTH_KEY);
@@ -559,7 +592,7 @@ public SoterPubKeyModel getAuthKeyModel(String authKeyName) {
SLogger.e(TAG, "soter: key can not be retrieved");
return null;
}
} catch (RemoteException e) {
} catch (Exception e) {
SLogger.printErrStackTrace(TAG, e, "soter: getAuthKeyModel fail: ");
}
return null;
@@ -594,7 +627,7 @@ public boolean hasAuthKey(String authKeyName) {

try {
return mSoterService.hasAuthKey(uid,authKeyName);
} catch (RemoteException e) {
} catch (Exception e) {
SLogger.printErrStackTrace(TAG, e, "soter: hasAuthKey fail: ");
return false;
}
@@ -627,7 +660,7 @@ public SoterSessionResult initSigh(String kname, String challenge) {
try {
result = mSoterService.initSigh(uid, kname, challenge);
return result;
} catch (RemoteException e) {
} catch (Exception e) {
SLogger.printErrStackTrace(TAG, e, "soter: initSigh fail: ");
}
return null;
@@ -664,7 +697,7 @@ public byte[] finishSign(long signSession) throws Exception{
throw new Exception("finishSign error");
}

} catch (RemoteException e) {
} catch (Exception e) {
SLogger.printErrStackTrace(TAG, e, "soter: finishSign fail: ");
}
return rawBytes;
@@ -692,12 +725,42 @@ public int getVersion() {

try {
return mSoterService.getVersion() ;
} catch (RemoteException e) {
} catch (Exception e) {
SLogger.printErrStackTrace(TAG, e, "soter: getVersion fail: ");
}
return 0;
}

@Override
public void updateExtraParam() {
try {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
if (mSoterService == null) {
SLogger.w(TAG, "soter: mSoterService is null");
return;
}
SoterExtraParam typeResult = mSoterService.getExtraParam(ISoterExParameters.FINGERPRINT_TYPE);
if (typeResult != null && typeResult.result instanceof Integer) {
SoterExParametersTrebleImpl.setParam(ISoterExParameters.FINGERPRINT_TYPE, typeResult.result);
}
SoterExtraParam posResult = mSoterService.getExtraParam(ISoterExParameters.FINGERPRINT_HARDWARE_POSITION);
if (posResult != null && posResult.result instanceof Integer[]) {
SoterExParametersTrebleImpl.setParam(ISoterExParameters.FINGERPRINT_HARDWARE_POSITION, posResult.result);
}
} catch (Exception e) {
SLogger.printErrStackTrace(TAG, e, "soter: getExtraParam fail");
}
}
});
thread.start();
} catch (Exception e) {
SLogger.printErrStackTrace(TAG, e, "soter: getExtraParam fail");
}
}

private static long getFib(long n){
if(n < 0){
return -1;
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.tencent.soter.soterserver;

import android.os.Parcel;
import android.os.Parcelable;

public class SoterExtraParam implements Parcelable {
public Object result;

protected SoterExtraParam(Parcel in) {
result = in.readValue(getClass().getClassLoader());
}

public static final Creator<SoterExtraParam> CREATOR = new Creator<SoterExtraParam>() {
@Override
public SoterExtraParam createFromParcel(Parcel in) {
return new SoterExtraParam(in);
}

@Override
public SoterExtraParam[] newArray(int size) {
return new SoterExtraParam[size];
}
};

@Override
public int describeContents() {
return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeValue(result);
}
}
Original file line number Diff line number Diff line change
@@ -148,4 +148,9 @@ public interface SoterProcessErrCode extends SoterErrCode {
* Equals to {@link android.hardware.fingerprint.FingerprintManager#FINGERPRINT_ERROR_LOCKOUT_PERMANENT}
*/
int ERR_BIOMETRIC_LOCKED_PERMENANT = 1022;

/**
* Clicked negative button, use above 31
*/
int ERR_CLICK_NEGATIVE_BUTTON = 1029;
}
Original file line number Diff line number Diff line change
@@ -34,7 +34,11 @@ public class AuthenticationParam {
private IWrapUploadSignature mIWrapUploadSignature;
private Context mContext;
private int mBiometricType;

private String mPromptTitle; //used for BiometricPrompt
private String mPromptSubTitle; //used for BiometricPrompt
private String mPromptDescription; //used for BiometricPrompt
private String mPromptButton; //used for BiometricPrompt
private boolean mUseBiometricPrompt; // force use BiometricPrompt when api>=31
private SoterFingerprintCanceller mFingerprintCanceller;
private SoterFingerprintStateCallback mSoterFingerprintStateCallback;

@@ -85,6 +89,26 @@ public SoterBiometricStateCallback getSoterBiometricStateCallback() {
return mSoterBiometricStateCallback;
}

public String getPromptTitle() {
return mPromptTitle;
}

public String getPromptSubTitle() {
return mPromptSubTitle;
}

public String getPromptDescription() {
return mPromptDescription;
}

public String getPromptButton() {
return mPromptButton;
}

public boolean getUseBiometricPrompt() {
return mUseBiometricPrompt;
}

@SuppressWarnings({"unused", "WeakerAccess"})
public static class AuthenticationParamBuilder {

@@ -199,6 +223,56 @@ public AuthenticationParamBuilder setBiometricType(int biometricType){
return this;
}

/**
* used for the BiometricPrompt,will use BiometricPrompt when api>31
* @param title
* @return
*/
public AuthenticationParamBuilder setPromptTitle(String title) {
mParam.mPromptTitle = title;
return this;
}

/**
* used for the BiometricPrompt
* @param subTitle
* @return
*/
public AuthenticationParamBuilder setPromptSubTitle(String subTitle) {
mParam.mPromptSubTitle = subTitle;
return this;
}

/**
* used for the BiometricPrompt
* @param description
* @return
*/
public AuthenticationParamBuilder setPromptDescription(String description) {
mParam.mPromptDescription = description;
return this;
}

/**
* used for the BiometricPrompt
* @param button
* @return
*/
public AuthenticationParamBuilder setPromptButton(String button) {
mParam.mPromptButton = button;
return this;
}

/**
* On Android S, the system will force to invoke BiometricPrompt when using FingerprintManager
* @param useBiometricPrompt
* @return
*/
public AuthenticationParamBuilder setUseBiometricPrompt(boolean useBiometricPrompt) {
mParam.mUseBiometricPrompt = useBiometricPrompt;
return this;
}

public AuthenticationParam build() {
return mParam;
}
Original file line number Diff line number Diff line change
@@ -12,6 +12,7 @@
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.RequiresApi;

@@ -61,6 +62,13 @@ public class TaskBiometricAuthentication extends BaseSoterTask implements AuthCa
private SoterBiometricCanceller mBiometricCancelSignal = null;
private SoterBiometricStateCallback mBiometricStateCallback = null;

// used for biometric prompt
private String mPromptTitle;
private String mPromptSubTitle;
private String mPromptDescription;
private String mPromptButton;
private boolean mUseBiometricPrompt;

private SoterSignatureResult mFinalResult = null;

private AuthenticationCallbackImpl mAuthenticationCallbackIml = null;
@@ -83,6 +91,11 @@ public TaskBiometricAuthentication(AuthenticationParam param) {
this.mBiometricCancelSignal = param.getSoterBiometricCanceller();
this.mBiometricType = param.getBiometricType();
this.mChallenge = param.getChallenge();
this.mPromptTitle = param.getPromptTitle();
this.mPromptSubTitle = param.getPromptSubTitle();
this.mPromptDescription = param.getPromptDescription();
this.mPromptButton = param.getPromptButton();
this.mUseBiometricPrompt = param.getUseBiometricPrompt();
}


@@ -280,9 +293,15 @@ private void performStartBiometricLogic(Signature signatureToAuth) {
}
try {
SLogger.v(TAG, "soter: performing start");
Bundle extra = new Bundle();
extra.putString("prompt_title", mPromptTitle);
extra.putString("prompt_subtitle", mPromptSubTitle);
extra.putString("prompt_description", mPromptDescription);
extra.putString("prompt_button", mPromptButton);
extra.putBoolean("use_biometric_prompt", mUseBiometricPrompt);
BiometricManagerCompat.from(context, mBiometricType).authenticate(new BiometricManagerCompat.CryptoObject(signatureToAuth), 0,
mBiometricCancelSignal != null ? mBiometricCancelSignal.getSignalObj() : null,
mAuthenticationCallbackIml, null);
mAuthenticationCallbackIml, null, extra);
} catch (Exception e) {
String cause = e.getMessage();
SLogger.e(TAG, "soter: caused exception when authenticating: %s", cause);
@@ -397,6 +416,8 @@ public void run() {
callback(new SoterProcessAuthenticationResult(SoterProcessErrCode.ERR_BIOMETRIC_LOCKED, charSequenceToStringNullAsNil(errString)));
} else if (errMsgId == ConstantsSoter.ERR_BIOMETRIC_FAIL_MAX_PERMANENT) {
callback(new SoterProcessAuthenticationResult(SoterProcessErrCode.ERR_BIOMETRIC_LOCKED_PERMENANT, charSequenceToStringNullAsNil(errString)));
} else if (errMsgId == ConstantsSoter.ERR_NEGATIVE_BUTTON) {
callback(new SoterProcessAuthenticationResult(SoterProcessErrCode.ERR_CLICK_NEGATIVE_BUTTON, charSequenceToStringNullAsNil(errString)));
} else {
callback(new SoterProcessAuthenticationResult(SoterProcessErrCode.ERR_BIOMETRIC_AUTHENTICATION_FAILED, charSequenceToStringNullAsNil(errString)));
}
9 changes: 4 additions & 5 deletions soter-samples/client-sample/app/build.gradle
Original file line number Diff line number Diff line change
@@ -2,7 +2,6 @@ apply plugin: 'com.android.application'

android {
compileSdkVersion 24
buildToolsVersion '26.0.2'

defaultConfig {
applicationId "com.tencent.soter.demo"
@@ -21,8 +20,8 @@ android {
}

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.github.Tencent.soter:soter-wrapper:2.0.9'
compile 'com.android.support:appcompat-v7:24.2.1'
compile 'commons-io:commons-io:1.4'
implementation fileTree(dir: 'libs', include: ['*.aar'])
//implementation 'com.github.Tencent.soter:soter-wrapper:2.0.9'
implementation 'com.android.support:appcompat-v7:24.2.1'
implementation 'commons-io:commons-io:1.4'
}
Binary file not shown.
Binary file not shown.
2 changes: 1 addition & 1 deletion soter-samples/client-sample/build.gradle
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.4'
classpath 'com.android.tools.build:gradle:7.2.1'
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.6'
classpath "com.github.dcendents:android-maven-gradle-plugin:1.5"
}
Original file line number Diff line number Diff line change
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip

0 comments on commit 49440b0

Please sign in to comment.