Skip to content

Commit

Permalink
Added support for "dont-enforce-user-presence-and-sign" (0x08)
Browse files Browse the repository at this point in the history
This change adds support for the control byte value 0x08, which is the
value for "dont-enforce-user-presence-and-sign". In this mode, user
presence is not enforced but a signature is still created.
  • Loading branch information
darconeous committed Mar 20, 2020
1 parent c2f223d commit 24b6f13
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 15 deletions.
8 changes: 7 additions & 1 deletion src/main/java/com/ledger/u2f/NullPresence.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@
*/
public class NullPresence implements Presence {
@Override
public void verify_user_presence() {
public byte enforce_user_presence() {
return FLAG_USER_PRESENT;
}

@Override
public byte check_user_presence() {
return 0;
}
}
16 changes: 14 additions & 2 deletions src/main/java/com/ledger/u2f/OneShotPresence.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,22 @@ public class OneShotPresence implements Presence {
}

@Override
public void verify_user_presence() {
if (did_verify_flag[0] != 0) {
public byte enforce_user_presence() {
byte presence = check_user_presence();

if ((presence & FLAG_USER_PRESENT) != FLAG_USER_PRESENT) {
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
}

return presence;
}

@Override
public byte check_user_presence() {
if (did_verify_flag[0] != 0) {
return 0;
}
did_verify_flag[0] = 1;
return FLAG_USER_PRESENT;
}
}
32 changes: 31 additions & 1 deletion src/main/java/com/ledger/u2f/Presence.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,36 @@
package com.ledger.u2f;

public interface Presence {
/** A user is present.
*
* This means that someone interacted with the
* authenticator while performing this operation.
*/
byte FLAG_USER_PRESENT = (byte)0x01;

void verify_user_presence();
/** The user was verified. From webauthn.
*
* This means that the user has verified themselves
* to the authenticator using, for example, their
* fingerprint or a PIN.
*/
byte FLAG_USER_VERIFIED = (byte)0x04;

/**
* Waits for user presence, throwing an exception if that
* is impossible or if there is a timeout.
*
* @return the value of the user presence byte
* in the FIDO U2F signature response.
*/
byte enforce_user_presence();

/**
* Checks user presence. Should not throw an exception.
* Returns immediately.
*
* @return the value of the user presence byte
* in the FIDO U2F signature response.
*/
byte check_user_presence();
}
26 changes: 15 additions & 11 deletions src/main/java/com/ledger/u2f/U2FApplet.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,9 @@ public class U2FApplet extends Applet implements ExtendedLength {
private static final byte TRANSPORT_NOT_EXTENDED_CERT = (byte)3;
private static final byte TRANSPORT_NOT_EXTENDED_SIGNATURE = (byte)4;

private static final byte P1_SIGN_OPERATION = (byte)0x03;
private static final byte P1_ENFORCE_PRESENCE_AND_SIGN = (byte)0x03;
private static final byte P1_SIGN_CHECK_ONLY = (byte)0x07;
private static final byte P1_IGNORE_PRESENCE_AND_SIGN = (byte)0x08;

private static final byte ENROLL_LEGACY_VERSION = (byte)0x05;
private static final byte RFU_ENROLL_SIGNED_VERSION[] = { (byte)0x00 };
Expand All @@ -83,8 +84,6 @@ public class U2FApplet extends Applet implements ExtendedLength {
private static final short APDU_CHALLENGE_OFFSET = (short)0;
private static final short APDU_APPLICATION_PARAMETER_OFFSET = (short)32;

private static final byte FLAG_USER_PRESENCE_VERIFIED = (byte)0x01;

private static final short FIDO_SW_TEST_OF_PRESENCE_REQUIRED = ISO7816.SW_CONDITIONS_NOT_SATISFIED;
private static final short FIDO_SW_INVALID_KEY_HANDLE = ISO7816.SW_WRONG_DATA;

Expand Down Expand Up @@ -163,7 +162,7 @@ private void handleEnroll(APDU apdu) throws ISOException {
}

// Deny if user presence cannot be validated
presence.verify_user_presence();
presence.enforce_user_presence();

// Generate the key pair
if (localPrivateTransient) {
Expand Down Expand Up @@ -208,14 +207,19 @@ private void handleSign(APDU apdu) throws ISOException {
short dataOffset = apdu.getOffsetCdata();
byte p1 = buffer[ISO7816.OFFSET_P1];
boolean sign = false;
boolean enforce_presence = false;
short keyHandleLength;
boolean extendedLength = (dataOffset != ISO7816.OFFSET_CDATA);
short outOffset = SCRATCH_PAD;
if (len < 65) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
}
switch(p1) {
case P1_SIGN_OPERATION:
case P1_ENFORCE_PRESENCE_AND_SIGN:
sign = true;
enforce_presence = true;
break;
case P1_IGNORE_PRESENCE_AND_SIGN:
sign = true;
break;
case P1_SIGN_CHECK_ONLY:
Expand All @@ -237,15 +241,15 @@ private void handleSign(APDU apdu) throws ISOException {
ISOException.throwIt(FIDO_SW_TEST_OF_PRESENCE_REQUIRED);
}

// If signing, only proceed if user presence can be validated
presence.verify_user_presence();
if (enforce_presence) {
scratch[outOffset++] = presence.enforce_user_presence();
} else {
scratch[outOffset++] = presence.check_user_presence();
}

// Increase the counter
// Increase the signature counter
counter.inc();

// Prepare reply
scratch[outOffset++] = FLAG_USER_PRESENCE_VERIFIED;

outOffset = counter.writeValue(scratch, outOffset);

localSignature.init(localPrivateKey, Signature.MODE_SIGN);
Expand Down

0 comments on commit 24b6f13

Please sign in to comment.