4

I am using the new BiometricPrompt API in Android P (API 28) in my application. (I am actually using it inside a wrapper based on this project so that it functions on older devices too, but that is not relevant to the question.) This is working very well on all devices I have tested, except for the Samsung S9 with face unlock.

Even though the stock Android version of BiometricPrompt currently only implements fingerprint authentication, Samsung appears to have extended it to support Face Unlock as well. When I trigger biometric authentication in my app, the "bottom sheet" pops up with a face icon (instead of the fingerprint icon shown on all other devices) and at the top of the screen some text appears that says "no face detected". (Note that the icon shown here is provided by the operating system, not by me, so it is obviously of Samsung's design.)

According to the documentation, the BiometricPrompt is only supposed to close itself and call my onAuthenticationSucceeded method if the authentication has been successful. According to logcat, it looks like it has been successful:

I/IFaceDaemonCallback: BpFaceDaemonCallback onAcquired()
I/SS_3A:  INFO: AEC: TsAec_process_get_aec_info: 650: [Id=132] algo_out g=1.785 e_time=0.025 IsLLS=0x0 Ev=7.422 Bv=2.348 ProEv=7.348 Cvgd=1 lux=261, lls=0x0
E/CHI: [SS_ERR ]: [CHI_FACTORY ]: chxseccamerafactoryusecase.cpp: ExecuteCaptureRequest: 452: pMetaData is NULL
I/FaceHal: face_processFrontImage[614398]
I/FaceServiceWrapper: ss_face_processFrontImage(data_len = 614398, width = 480, height = 640, rotation = 270)
I/NativeFaceService: FaceService::processFrontImage - data_len (614398) width(480) height(640) rotation(270) format(2)
I/NativeFaceService: SEC_FR_SERVICE_AUTHENTICATE
I/sec_fr_engine_qsee: sec_fr_engine_on_authenticate_frame
D/sec_fr_engine_qsee: call QSEECom_send_cmd
I/SS_3A:  INFO: AEC: TsAec_process_get_aec_info: 650: [Id=133] algo_out g=1.785 e_time=0.025 IsLLS=0x0 Ev=7.422 Bv=2.352 ProEv=7.352 Cvgd=1 lux=261, lls=0x0
E/CHI: [SS_ERR ]: [CHI_FACTORY ]: chxseccamerafactoryusecase.cpp: ExecuteCaptureRequest: 452: pMetaData is NULL
I/SS_3A:  INFO: AEC: TsAec_process_get_aec_info: 650: [Id=134] algo_out g=1.864 e_time=0.025 IsLLS=0x0 Ev=7.359 Bv=2.332 ProEv=7.332 Cvgd=0 lux=262, lls=0x0
E/CHI: [SS_ERR ]: [CHI_FACTORY ]: chxseccamerafactoryusecase.cpp: ExecuteCaptureRequest: 452: pMetaData is NULL
I/SS_3A:  INFO: AEC: TsAec_process_get_aec_info: 650: [Id=135] algo_out g=1.910 e_time=0.025 IsLLS=0x0 Ev=7.324 Bv=2.324 ProEv=7.324 Cvgd=0 lux=262, lls=0x0
E/CHI: [SS_ERR ]: [CHI_FACTORY ]: chxseccamerafactoryusecase.cpp: ExecuteCaptureRequest: 452: pMetaData is NULL
I/SS_3A:  INFO: AEC: TsAec_process_get_aec_info: 650: [Id=136] algo_out g=1.920 e_time=0.025 IsLLS=0x0 Ev=7.316 Bv=2.316 ProEv=7.316 Cvgd=0 lux=262, lls=0x0
E/CHI: [SS_ERR ]: [CHI_FACTORY ]: chxseccamerafactoryusecase.cpp: ExecuteCaptureRequest: 452: pMetaData is NULL
I/sec_fr_engine_qsee: [Performance Log] QSEECom_send_cmd (129683) us in sec_fr_engine_on_authenticate_frame
D/sec_fr_engine_qsee: QSEECom_send_cmd Success
D/sec_fr_engine_qsee: return value from qsapp is 0
I/NativeFaceService: sec_fr_engine_on_authenticate_frame - status = [0], identified = [1], keepProcessing = [1]
I/NativeFaceService: identify succeeds
I/FaceServiceStorage: GetFileSize::Size of file: 196 bytes.
I/FaceServiceStorage: file size = 196
I/NativeFaceService: sid file length = 196
I/sec_fr_engine_qsee: sec_fr_engine_authenticated
D/sec_fr_engine_qsee: call QSEECom_send_cmd
I/SS_3A:  INFO: AEC: TsAec_process_get_aec_info: 650: [Id=137] algo_out g=1.936 e_time=0.025 IsLLS=0x0 Ev=7.305 Bv=2.301 ProEv=7.301 Cvgd=0 lux=263, lls=0x0
I/sec_fr_engine_qsee: [Performance Log] QSEECom_send_cmd (12414) us in sec_fr_engine_authenticated
D/sec_fr_engine_qsee: QSEECom_send_cmd Success
D/sec_fr_engine_qsee: return value from qsapp is 0
I/FaceServiceCallback: sendAuthenticated in
I/faced_Proxy: wrapped_object_length = 0
I/IFaceDaemonCallback: BpFaceDaemonCallback onAuthenticated() 
I/FaceServiceCallback: sendAuthenticated out
I/SemBioFaceServiceD: handleAuthenticated : 1
D/keystore: AddAuthenticationToken: timestamp = 168377203, time_received = 16675
I/SemBioFacePrompt: isSuccess = true

However, it then crashes with the following error:

E/keystore: getAuthToken failed: -3
W/System.err: javax.crypto.IllegalBlockSizeException
W/System.err:     at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:519)
W/System.err:     at javax.crypto.Cipher.doFinal(Cipher.java:2055)
W/System.err:     at com.mycompany.myapp.activities.LoginActivity.onAuthenticationSuccessful(LoginActivity.java:560)
W/System.err:     at com.mycompany.common.security.BiometricCallbackV28.onAuthenticationSucceeded(BiometricCallbackV28.kt:18)
W/System.err:     at com.samsung.android.bio.face.SemBioFaceManager.sendAuthenticatedSucceeded(SemBioFaceManager.java:1507)
W/System.err:     at com.samsung.android.bio.face.SemBioFaceManager.access$2400(SemBioFaceManager.java:73)
W/System.err:     at com.samsung.android.bio.face.SemBioFaceManager$3.lambda$onAuthenticationSucceeded$1(SemBioFaceManager.java:1673)
W/System.err:     at com.samsung.android.bio.face.-$$Lambda$SemBioFaceManager$3$GGUPv9osWllaLwJM7Wg6GJEWK8E.run(Unknown Source:6)
W/System.err:     at android.os.Handler.handleCallback(Handler.java:873)
W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:99)
W/System.err:     at android.os.Looper.loop(Looper.java:214)
W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:6981)
W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
W/System.err:     at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1445)
W/System.err: Caused by: android.security.KeyStoreException: Key user not authenticated
W/System.err:     at android.security.KeyStore.getKeyStoreException(KeyStore.java:1168)
W/System.err:     at android.security.keystore.KeyStoreCryptoOperationChunkedStreamer.update(KeyStoreCryptoOperationChunkedStreamer.java:132)
W/System.err:     at android.security.keystore.KeyStoreCryptoOperationChunkedStreamer.doFinal(KeyStoreCryptoOperationChunkedStreamer.java:217)
W/System.err:     at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:506)
W/System.err:   ... 14 more

According to the documentation, the success of the biometric authentication should have unlocked the keystore, but that has clearly not happened as shown by the Key user not authenticated message in the exception.

How can I get this working?

  • Probably it's a Samsung bug. Does the same device work correctly if you switch to fingerprints instead of the face? IOW, is this a Face Unlock bug, or a general S9 biometrics bug? – CommonsWare Apr 11 at 14:28
  • 1
  • keystore.h says 3 means STATE_UNINITIALIZED. possibly related: 25591236. – Martin Zeitler Apr 11 at 16:21
  • @MartinZeitler if that were the reason, I would expect this to happen on all devices, but it works perfectly on all other devices I've tried (including other Samsung devices). – Moshe Katz Apr 14 at 14:03
  • @MosheKatz KeyStoreException: Key user not authenticated generally tells the same. this seems to be a possible solution... because it might have been authenticated at first, but when trying to access it again, it is inaccessible already; timing issue. if that specific implementation uses -1 if user authentication must take place for every use of the key... this might not work out. – Martin Zeitler Apr 14 at 16:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.