Skip to content

Commit bd93a33

Browse files
committed
v4.2.0
1 parent 6d1261f commit bd93a33

34 files changed

+640
-217
lines changed

hwsecurity/fido/src/main/java/de/cotech/hw/fido/ui/FidoDialogFragment.java

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@
6060
import de.cotech.hw.SecurityKeyCallback;
6161
import de.cotech.hw.SecurityKeyException;
6262
import de.cotech.hw.SecurityKeyManager;
63-
import de.cotech.hw.exceptions.InsNotSupportedException;
6463
import de.cotech.hw.exceptions.SecurityKeyDisconnectedException;
6564
import de.cotech.hw.fido.FidoAuthenticateCallback;
6665
import de.cotech.hw.fido.FidoAuthenticateRequest;
@@ -79,16 +78,18 @@
7978
import de.cotech.hw.ui.internal.NfcFullscreenView;
8079
import de.cotech.hw.ui.internal.SecurityKeyFormFactor;
8180
import de.cotech.hw.ui.internal.SmartcardFormFactor;
81+
import de.cotech.hw.ui.internal.SuccessView;
8282
import de.cotech.hw.util.HwTimber;
8383

8484

8585
public class FidoDialogFragment extends BottomSheetDialogFragment implements SecurityKeyCallback<FidoSecurityKey>, SecurityKeyFormFactor.SelectTransportCallback {
8686
private static final String FRAGMENT_TAG = "hwsecurity-fido-fragment";
8787
private static final String ARG_FIDO_REGISTER_REQUEST = "ARG_FIDO_REGISTER_REQUEST";
8888
private static final String ARG_FIDO_AUTHENTICATE_REQUEST = "ARG_FIDO_AUTHENTICATE_REQUEST";
89-
private static final String ARG_FIDO_OPTIONS = "de.cotech.hw.fido.ARG_FIDO_OPTIONS";
89+
private static final String ARG_FIDO_OPTIONS = "de.cotech.hw.fido.ui.ARG_FIDO_OPTIONS";
9090

9191
private static final long TIME_DELAYED_SCREEN_CHANGE = 3000;
92+
private static final long TIME_DELAYED_SUCCESS_DISMISS = 1600;
9293

9394
static {
9495
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
@@ -112,6 +113,7 @@ public class FidoDialogFragment extends BottomSheetDialogFragment implements Sec
112113
private SmartcardFormFactor smartcardFormFactor;
113114

114115
private ErrorView errorView;
116+
private SuccessView successView;
115117

116118
private FidoDialogOptions options;
117119
private FidoRegisterRequest fidoRegisterRequest;
@@ -126,6 +128,7 @@ private enum Screen {
126128
USB_PRESS_BUTTON,
127129
USB_SELECT_AND_PRESS_BUTTON,
128130
ERROR,
131+
SUCCESS,
129132
}
130133

131134
private Screen currentScreen;
@@ -348,6 +351,7 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat
348351
securityKeyFormFactor = new SecurityKeyFormFactor(view.findViewById(R.id.includeSecurityKeyFormFactor), this, this, innerBottomSheet, options.getShowSdkLogo());
349352

350353
errorView = new ErrorView(view.findViewById(de.cotech.hw.ui.R.id.includeError));
354+
successView = new SuccessView(view.findViewById(de.cotech.hw.ui.R.id.includeSuccess));
351355

352356
nfcFullscreenView = new NfcFullscreenView(view.findViewById(de.cotech.hw.ui.R.id.includeNfcFullscreen), innerBottomSheet);
353357

@@ -402,7 +406,11 @@ private void gotoScreen(Screen newScreen) {
402406
break;
403407
}
404408
case ERROR: {
405-
animateError();
409+
showError();
410+
break;
411+
}
412+
case SUCCESS: {
413+
showSuccess();
406414
break;
407415
}
408416
}
@@ -413,6 +421,7 @@ public void screeFullscreenNfc() {
413421
textTitle.setVisibility(View.GONE);
414422
textDescription.setVisibility(View.GONE);
415423
errorView.setVisibility(View.GONE);
424+
successView.setVisibility(View.GONE);
416425
smartcardFormFactor.setVisibility(View.GONE);
417426
securityKeyFormFactor.setVisibility(View.GONE);
418427

@@ -433,19 +442,32 @@ private void animateStart() {
433442
textTitle.setVisibility(View.VISIBLE);
434443
textDescription.setVisibility(View.VISIBLE);
435444
errorView.setVisibility(View.GONE);
445+
successView.setVisibility(View.GONE);
436446
securityKeyFormFactor.setVisibility(View.VISIBLE);
437447

438448
securityKeyFormFactor.resetAnimation();
439449
}
440450

441-
private void animateError() {
451+
private void showError() {
442452
TransitionManager.beginDelayedTransition(innerBottomSheet);
443453
textTitle.setVisibility(View.GONE);
444454
textDescription.setVisibility(View.GONE);
445455
securityKeyFormFactor.setVisibility(View.GONE);
446456
smartcardFormFactor.setVisibility(View.GONE);
447457
nfcFullscreenView.setVisibility(View.GONE);
448458
errorView.setVisibility(View.VISIBLE);
459+
successView.setVisibility(View.GONE);
460+
}
461+
462+
private void showSuccess() {
463+
TransitionManager.beginDelayedTransition(innerBottomSheet);
464+
textTitle.setVisibility(View.GONE);
465+
textDescription.setVisibility(View.GONE);
466+
securityKeyFormFactor.setVisibility(View.GONE);
467+
smartcardFormFactor.setVisibility(View.GONE);
468+
nfcFullscreenView.setVisibility(View.GONE);
469+
errorView.setVisibility(View.GONE);
470+
successView.setVisibility(View.VISIBLE);
449471
}
450472

451473
@UiThread
@@ -483,7 +505,13 @@ public void onRegisterResponse(FidoRegisterResponse response) {
483505
if (securityKey.isTransportNfc()) {
484506
securityKey.release();
485507
}
486-
dismiss();
508+
gotoScreen(Screen.SUCCESS);
509+
bottomSheet.postDelayed(() -> {
510+
if (!isAdded()) {
511+
return;
512+
}
513+
dismiss();
514+
}, TIME_DELAYED_SUCCESS_DISMISS);
487515
}
488516

489517
@Override
@@ -502,7 +530,13 @@ public void onAuthenticateResponse(FidoAuthenticateResponse response) {
502530
if (securityKey.isTransportNfc()) {
503531
securityKey.release();
504532
}
505-
dismiss();
533+
gotoScreen(Screen.SUCCESS);
534+
bottomSheet.postDelayed(() -> {
535+
if (!isAdded()) {
536+
return;
537+
}
538+
dismiss();
539+
}, TIME_DELAYED_SUCCESS_DISMISS);
506540
}
507541

508542
@Override

hwsecurity/fido/src/main/java/de/cotech/hw/fido/ui/FidoDialogOptions.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ public abstract static class Builder {
9191
* &#60;item name="hwSecurityButtonColor"&#62;@color/hwSecurityDarkBlue&#60;/item&#62;
9292
* &#60;item name="hwSecuritySurfaceColor"&#62;@color/hwSecurityBlue&#60;/item&#62;
9393
* &#60;item name="hwSecurityErrorColor"&#62;@color/hwSecurityRed&#60;/item&#62;
94+
* &#60;item name="hwSecuritySuccessColor"&#62;@color/hwSecurityGreen&#60;/item&#62;
9495
* &#60;/style&#62;
9596
* </pre>
9697
*/

hwsecurity/fido2/src/main/java/de/cotech/hw/fido2/internal/operations/ctap1/AuthenticatorGetAssertionCtap1Operation.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ private PublicKeyCredential ctap1ResponseApduToWebauthnResponse(
108108
U2fAuthenticateResponse u2fResponse = U2fAuthenticateResponse.fromBytes(responseData);
109109

110110
AuthenticatorData authenticatorData =
111-
AuthenticatorData.create(rpIdHash, (byte) 1, u2fResponse.counter(), null, null);
111+
AuthenticatorData.create(rpIdHash, u2fResponse.presence(), u2fResponse.counter(), null, null);
112112
byte[] authenticatorDataBytes = new AuthenticatorDataParser().toBytes(authenticatorData);
113113
AuthenticatorAssertionResponse authenticatorResponse =
114114
AuthenticatorAssertionResponse.create(

hwsecurity/fido2/src/main/java/de/cotech/hw/fido2/internal/operations/ctap1/U2fAuthenticateResponse.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public static U2fAuthenticateResponse fromBytes(byte[] data) throws IOException
4444
int counter = buf.getInt();
4545

4646
int signatureLength = buf.remaining();
47-
if (signatureLength < 70 || signatureLength > 73) {
47+
if (signatureLength < 71 || signatureLength > 73) {
4848
throw new IOException("Signature length must be 71-73 bytes!");
4949
}
5050
byte[] signature = new byte[signatureLength];

hwsecurity/fido2/src/main/java/de/cotech/hw/fido2/internal/utils/PublicSuffixDatabase.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@
3636

3737

3838
class PublicSuffixDatabase {
39-
private static final String PUBLIC_SUFFIX_RESOURCE = "publicsuffixes.gz";
39+
// Must be an absolute path to work after Proguard optimizations!
40+
private static final String PUBLIC_SUFFIX_RESOURCE = "/de/cotech/hw/fido2/internal/utils/publicsuffixes.gz";
4041
private static final byte[] WILDCARD_LABEL = new byte[] { '*' };
4142
private static final char EXCEPTION_MARKER = '!';
4243

hwsecurity/fido2/src/main/java/de/cotech/hw/fido2/ui/GenericFido2SecurityKeyDialogFragment.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
import de.cotech.hw.ui.internal.SecurityKeyDialogPresenter;
4040

4141
public class GenericFido2SecurityKeyDialogFragment extends SecurityKeyDialogFragment<Fido2SecurityKey> {
42-
public static final String ARG_FIDO2_CONFIG = "de.cotech.hw.fido2.ARG_FIDO2_CONFIG";
42+
public static final String ARG_FIDO2_CONFIG = "de.cotech.hw.fido2.ui.ARG_FIDO2_CONFIG";
4343

4444
public static SecurityKeyDialogFragment<Fido2SecurityKey> newInstance() {
4545
return newInstance(SecurityKeyDialogOptions.builder().build(), Fido2SecurityKeyConnectionModeConfig.getDefaultConfig());

hwsecurity/fido2/src/main/java/de/cotech/hw/fido2/ui/WebauthnDialogFragment.java

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,16 +92,18 @@
9292
import de.cotech.hw.ui.internal.PinInput;
9393
import de.cotech.hw.ui.internal.SecurityKeyFormFactor;
9494
import de.cotech.hw.ui.internal.SmartcardFormFactor;
95+
import de.cotech.hw.ui.internal.SuccessView;
9596
import de.cotech.hw.util.HwTimber;
9697

9798

9899
public class WebauthnDialogFragment extends BottomSheetDialogFragment
99100
implements SecurityKeyCallback<Fido2SecurityKey>, SecurityKeyFormFactor.SelectTransportCallback, PinInput.PinInputCallback {
100101
private static final String FRAGMENT_TAG = "hwsecurity-webauthn-fragment";
101102
private static final String ARG_WEBAUTHN_COMMAND = "ARG_WEBAUTHN_COMMAND";
102-
private static final String ARG_WEBAUTHN_OPTIONS = "de.cotech.hw.fido.ARG_WEBAUTHN_OPTIONS";
103+
private static final String ARG_WEBAUTHN_OPTIONS = "de.cotech.hw.fido2.ui.ARG_WEBAUTHN_OPTIONS";
103104

104105
private static final long TIME_DELAYED_SCREEN_CHANGE = 3000;
106+
private static final long TIME_DELAYED_SUCCESS_DISMISS = 1600;
105107

106108
static {
107109
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
@@ -130,6 +132,7 @@ public class WebauthnDialogFragment extends BottomSheetDialogFragment
130132
private TextView textDescription;
131133

132134
private ErrorView errorView;
135+
private SuccessView successView;
133136

134137
private WebauthnDialogOptions options;
135138
private WebauthnCommand webauthnCommand;
@@ -147,6 +150,7 @@ private enum Screen {
147150
USB_PRESS_BUTTON,
148151
USB_SELECT_AND_PRESS_BUTTON,
149152
ERROR,
153+
SUCCESS,
150154
}
151155

152156
private Screen currentScreen;
@@ -362,6 +366,7 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat
362366
securityKeyFormFactor = new SecurityKeyFormFactor(view.findViewById(R.id.includeSecurityKeyFormFactor), this, this, innerBottomSheet, options.getShowSdkLogo());
363367

364368
errorView = new ErrorView(view.findViewById(de.cotech.hw.ui.R.id.includeError));
369+
successView = new SuccessView(view.findViewById(de.cotech.hw.ui.R.id.includeSuccess));
365370

366371
nfcFullscreenView = new NfcFullscreenView(view.findViewById(de.cotech.hw.ui.R.id.includeNfcFullscreen), innerBottomSheet);
367372

@@ -508,6 +513,10 @@ private void gotoScreen(Screen newScreen) {
508513
showError();
509514
break;
510515
}
516+
case SUCCESS: {
517+
showSuccess();
518+
break;
519+
}
511520
}
512521
}
513522

@@ -516,6 +525,7 @@ public void screeFullscreenNfc() {
516525
textTitle.setVisibility(View.GONE);
517526
textDescription.setVisibility(View.GONE);
518527
errorView.setVisibility(View.GONE);
528+
successView.setVisibility(View.GONE);
519529
securityKeyFormFactor.setVisibility(View.GONE);
520530
smartcardFormFactor.setVisibility(View.GONE);
521531
buttonRight.setVisibility(View.GONE);
@@ -550,6 +560,7 @@ private void animateStart() {
550560
textTitle.setVisibility(View.VISIBLE);
551561
textDescription.setVisibility(View.VISIBLE);
552562
errorView.setVisibility(View.GONE);
563+
successView.setVisibility(View.GONE);
553564
keyboardPinInput.setVisibility(View.GONE);
554565
keypadPinInput.setVisibility(View.GONE);
555566
switch (options.getFormFactor()) {
@@ -574,6 +585,7 @@ public void showPinInput(boolean allowSkip) {
574585
textTitle.setVisibility(View.VISIBLE);
575586
textDescription.setVisibility(View.VISIBLE);
576587
errorView.setVisibility(View.GONE);
588+
successView.setVisibility(View.GONE);
577589
securityKeyFormFactor.setVisibility(View.GONE);
578590
smartcardFormFactor.setVisibility(View.GONE);
579591
buttonPinInputSwitch.setVisibility(options.getAllowKeyboard() ? View.VISIBLE : View.INVISIBLE);
@@ -604,6 +616,22 @@ private void showError() {
604616
smartcardFormFactor.setVisibility(View.GONE);
605617
nfcFullscreenView.setVisibility(View.GONE);
606618
errorView.setVisibility(View.VISIBLE);
619+
successView.setVisibility(View.GONE);
620+
buttonRight.setVisibility(View.GONE);
621+
keyboardPinInput.setVisibility(View.GONE);
622+
keypadPinInput.setVisibility(View.GONE);
623+
buttonPinInputSwitch.setVisibility(View.GONE);
624+
}
625+
626+
private void showSuccess() {
627+
TransitionManager.beginDelayedTransition(innerBottomSheet);
628+
textTitle.setVisibility(View.GONE);
629+
textDescription.setVisibility(View.GONE);
630+
securityKeyFormFactor.setVisibility(View.GONE);
631+
smartcardFormFactor.setVisibility(View.GONE);
632+
nfcFullscreenView.setVisibility(View.GONE);
633+
errorView.setVisibility(View.GONE);
634+
successView.setVisibility(View.VISIBLE);
607635
buttonRight.setVisibility(View.GONE);
608636
keyboardPinInput.setVisibility(View.GONE);
609637
keypadPinInput.setVisibility(View.GONE);
@@ -663,7 +691,13 @@ public void onResponse(PublicKeyCredential publicKeyCredential) {
663691
if (securityKey.isTransportNfc()) {
664692
securityKey.release();
665693
}
666-
dismiss();
694+
gotoScreen(Screen.SUCCESS);
695+
bottomSheet.postDelayed(() -> {
696+
if (!isAdded()) {
697+
return;
698+
}
699+
dismiss();
700+
}, TIME_DELAYED_SUCCESS_DISMISS);
667701
}
668702

669703
@Override
@@ -682,7 +716,13 @@ public void onResponse(PublicKeyCredential response) {
682716
if (securityKey.isTransportNfc()) {
683717
securityKey.release();
684718
}
685-
dismiss();
719+
gotoScreen(Screen.SUCCESS);
720+
bottomSheet.postDelayed(() -> {
721+
if (!isAdded()) {
722+
return;
723+
}
724+
dismiss();
725+
}, TIME_DELAYED_SUCCESS_DISMISS);
686726
}
687727

688728
@Override

hwsecurity/fido2/src/main/java/de/cotech/hw/fido2/ui/WebauthnDialogOptions.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ public abstract static class Builder {
108108
* &#60;item name="hwSecurityButtonColor"&#62;@color/hwSecurityDarkBlue&#60;/item&#62;
109109
* &#60;item name="hwSecuritySurfaceColor"&#62;@color/hwSecurityBlue&#60;/item&#62;
110110
* &#60;item name="hwSecurityErrorColor"&#62;@color/hwSecurityRed&#60;/item&#62;
111+
* &#60;item name="hwSecuritySuccessColor"&#62;@color/hwSecurityGreen&#60;/item&#62;
111112
* &#60;/style&#62;
112113
* </pre>
113114
*/

hwsecurity/fido2/src/test/java/de/cotech/hw/fido2/internal/pinauth/PinProtocolV1Test.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ public class PinProtocolV1Test {
3737
static final byte[] PIN_TOKEN_ENC = Hex.decodeHexOrFail("554df3802226935b2bf49f30aae3096f");
3838
static final String CLIENT_PIN_GET_TOKEN = "801000006606a40101020503a501020326200121582099401f6ffa9446585074d1058578f4c68ab46953ccf8cb7910d8b3c9350e1040225820a3c962cddad166b1fdea8a95a377dbf8efbedd82778a8004b884f0009bd6df9506502eb756ae474f7ca032b5111b2eef6959";
3939
static final String CLIENT_PIN_GET_TOKEN_RESPONSE = "00a10250554df3802226935b2bf49f30aae3096f9000";
40-
static final String CLIENT_PIN_GET_TOKEN_RESPONSE_INVALID = "329000";
41-
static final String CLIENT_PIN_GET_TOKEN_RESPONSE_BLOCKED = "319000";
40+
static final String CLIENT_PIN_GET_TOKEN_RESPONSE_INVALID = "319000";
41+
static final String CLIENT_PIN_GET_TOKEN_RESPONSE_BLOCKED = "329000";
4242

4343
static final byte[] SHARED_SECRET = new byte[1];
4444
static final byte[] PIN_TOKEN = new byte[1];
@@ -75,7 +75,7 @@ public void pinAuth_invalid() throws Exception {
7575
pinProtocolV1.clientPinAuthenticate(fakeFidoConnection.connection, "1234", false);
7676
}
7777

78-
@Test(expected = FidoClientPinInvalidException.class)
78+
@Test(expected = FidoClientPinBlockedException.class)
7979
public void pinAuth_invalid_blocked() throws Exception {
8080
PinProtocolV1 pinProtocolV1 = setupPinProtocol();
8181

hwsecurity/openpgp/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ dependencies {
99
compileOnly project(':hwsecurity:ui')
1010
compileOnly 'com.google.android.material:material:1.1.0'
1111

12-
implementation 'org.bouncycastle:bcprov-jdk15on:1.65'
12+
implementation 'org.bouncycastle:bcprov-jdk15on:1.67'
1313

1414
compileOnly 'androidx.annotation:annotation:1.1.0'
1515

0 commit comments

Comments
 (0)