Skip to content

Commit

Permalink
Merge PR #118
Browse files Browse the repository at this point in the history
  • Loading branch information
AdamVe committed Mar 5, 2024
2 parents a891213 + 7069811 commit 6c90354
Show file tree
Hide file tree
Showing 6 changed files with 875 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2020-2023 Yubico.
* Copyright (C) 2020-2024 Yubico.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -40,6 +40,7 @@ public class CtapException extends CommandException {
public static final byte ERR_MISSING_PARAMETER = 0x14;
public static final byte ERR_LIMIT_EXCEEDED = 0x15;
public static final byte ERR_UNSUPPORTED_EXTENSION = 0x16;
public static final byte ERR_FP_DATABASE_FULL = 0x17;
public static final byte ERR_CREDENTIAL_EXCLUDED = 0x19;
public static final byte ERR_PROCESSING = 0x21;
public static final byte ERR_INVALID_CREDENTIAL = 0x22;
Expand Down
78 changes: 78 additions & 0 deletions fido/src/main/java/com/yubico/yubikit/fido/ctap/BioEnrollment.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* Copyright (C) 2024 Yubico.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.yubico.yubikit.fido.ctap;

import com.yubico.yubikit.core.application.CommandException;

import java.io.IOException;
import java.util.Map;
import java.util.Objects;

/**
* Implements Bio enrollment commands.
*
* @see <a href="https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-errata-20220621.html#authenticatorBioEnrollment">authenticatorBioEnrollment</a>
*/
public class BioEnrollment {
protected static final int RESULT_MODALITY = 0x01;
protected static final int MODALITY_FINGERPRINT = 0x01;

protected final Ctap2Session ctap;
protected final int modality;

public BioEnrollment(Ctap2Session ctap, int modality) throws IOException, CommandException {
if (!isSupported(ctap.getCachedInfo())) {
throw new IllegalStateException("Bio enrollment not supported");
}

this.ctap = ctap;
this.modality = getModality(ctap);

if (this.modality != modality) {
throw new IllegalStateException("Device does not support modality " + modality);
}
}

public static boolean isSupported(Ctap2Session.InfoData info) {
final Map<String, ?> options = info.getOptions();
if (options.containsKey("bioEnroll")) {
return true;
} else return info.getVersions().contains("FIDO_2_1_PRE") &&
options.containsKey("userVerificationMgmtPreview");
}

/**
* Get the type of modality the authenticator supports.
*
* @param ctap CTAP2 session
* @return The type of modality authenticator supports. For fingerprint, its value is 1.
* @throws IOException A communication error in the transport layer.
* @throws CommandException A communication in the protocol layer.
* @see <a href="https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-errata-20220621.html#getUserVerificationModality">Get bio modality</a>
*/
public static int getModality(Ctap2Session ctap) throws IOException, CommandException {
final Map<Integer, ?> result = ctap.bioEnrollment(
null,
null,
null,
null,
null,
Boolean.TRUE,
null);
return Objects.requireNonNull((Integer) result.get(RESULT_MODALITY));
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2020-2023 Yubico.
* Copyright (C) 2020-2024 Yubico.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -82,6 +82,8 @@ public class Ctap2Session extends ApplicationSession<Ctap2Session> {
private final InfoData info;
@Nullable
private final Byte credentialManagerCommand;
@Nullable
private final Byte bioEnrollmentCommand;

private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Ctap2Session.class);

Expand Down Expand Up @@ -136,6 +138,15 @@ private Ctap2Session(Version version, Backend<?> backend)
} else {
this.credentialManagerCommand = null;
}

if (options.containsKey("bioEnroll")) {
this.bioEnrollmentCommand = CMD_BIO_ENROLLMENT;
} else if (info.getVersions().contains("FIDO_2_1_PRE") &&
options.containsKey("userVerificationMgmtPreview")) {
this.bioEnrollmentCommand = CMD_BIO_ENROLLMENT_PRE;
} else {
this.bioEnrollmentCommand = null;
}
}

private static Backend<SmartCardProtocol> getSmartCardBackend(SmartCardConnection connection)
Expand Down Expand Up @@ -394,6 +405,45 @@ public void reset(@Nullable CommandState state) throws IOException, CommandExcep
sendCbor(CMD_RESET, null, state);
}

/**
* This command is used by the platform to provision/enumerate/delete bio enrollments in the
* authenticator.
*
* @param modality the user verification modality being requested
* @param subCommand the user verification sub command currently being requested
* @param subCommandParams a map of subCommands parameters
* @param pinUvAuthProtocol PIN/UV protocol version chosen by the platform
* @param pinUvAuthParam first 16 bytes of HMAC-SHA-256 of contents using pinUvAuthToken
* @param getModality get the user verification type modality
* @param state an optional state object to cancel a request and handle
* keepalive signals
* @throws IOException A communication error in the transport layer.
* @throws CommandException A communication in the protocol layer.
* @see <a href="https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-errata-20220621.html#authenticatorBioEnrollment">authenticatorBioEnrollment</a>
*/
Map<Integer, ?> bioEnrollment(
@Nullable Integer modality,
@Nullable Integer subCommand,
@Nullable Map<?, ?> subCommandParams,
@Nullable Integer pinUvAuthProtocol,
@Nullable byte[] pinUvAuthParam,
@Nullable Boolean getModality,
@Nullable CommandState state
) throws IOException, CommandException {
if (bioEnrollmentCommand == null) {
throw new IllegalStateException("Bio enrollment not supported");
}
return sendCbor(
bioEnrollmentCommand, args(
modality,
subCommand,
subCommandParams,
pinUvAuthProtocol,
pinUvAuthParam,
getModality
), state);
}

/**
* This command is used by the platform to manage discoverable credentials on the
* authenticator.
Expand Down
Loading

0 comments on commit 6c90354

Please sign in to comment.