-
Notifications
You must be signed in to change notification settings - Fork 0
Extension Support
- Introduction
- Extension Negotiation and Enablement
- Biometric Enrollment Extension
- PIN/UV Authentication Extension
- Large Blob Storage Extension
- Authenticator Configuration Extension
- Relationship with Core CTAP2 Command Set
- Security Considerations
- Practical Usage Examples
This document provides comprehensive documentation for the CTAP2 extensions implemented in the FIDO2 WebAuthn platform. The extensions covered include biometric enrollment, PIN/UV authentication, large blob storage, and authenticator configuration. Each extension extends the core CTAP2 functionality to provide additional capabilities for authenticators and clients. The implementation follows the FIDO2 specifications and provides a robust framework for secure authentication operations.
CTAP2 extensions are negotiated and enabled through the Info object, which is retrieved using the CTAP2 GET_INFO command. The Info object contains metadata about the authenticator's capabilities, including supported extensions.
The negotiation process follows these steps:
- The client sends a GET_INFO command to retrieve the authenticator's capabilities
- The authenticator responds with an Info object containing the list of supported extensions
- The client checks for required extensions in the
extensionsfield of the Info object - If the required extensions are supported, the client can proceed with extension-specific commands
sequenceDiagram
participant Client
participant Authenticator
Client->>Authenticator : GET_INFO()
Authenticator-->>Client : Info object with extensions list
Client->>Client : Check for required extensions
alt Extensions supported
Client->>Authenticator : Use extension commands
else Extensions not supported
Client->>Client : Handle fallback or error
end
Diagram sources
- base.py
Section sources
- base.py
- extensions.py
The biometric enrollment extension provides functionality for managing biometric templates on the authenticator. It supports fingerprint enrollment and management through a set of commands that allow for template creation, enumeration, renaming, and removal.
The biometric enrollment extension uses the following commands:
| Command | Code | Parameters | Description |
|---|---|---|---|
| ENROLL_BEGIN | 0x01 | TIMEOUT_MS | Starts fingerprint enrollment and captures the first sample |
| ENROLL_CAPTURE_NEXT | 0x02 | TEMPLATE_ID, TIMEOUT_MS | Captures subsequent fingerprint samples |
| ENROLL_CANCEL | 0x03 | None | Cancels ongoing enrollment |
| ENUMERATE_ENROLLMENTS | 0x04 | None | Lists all enrolled fingerprint templates |
| SET_NAME | 0x05 | TEMPLATE_ID, NAME | Sets or changes the friendly name of a template |
| REMOVE_ENROLLMENT | 0x06 | TEMPLATE_ID | Removes a previously enrolled template |
| GET_SENSOR_INFO | 0x07 | None | Retrieves fingerprint sensor information |
The extension returns responses with the following result codes:
| Result Code | Value | Description |
|---|---|---|
| MODALITY | 0x01 | Type of biometric modality supported |
| FINGERPRINT_KIND | 0x02 | Type of fingerprint sensor |
| MAX_SAMPLES_REQUIRED | 0x03 | Maximum samples needed for enrollment |
| TEMPLATE_ID | 0x04 | ID of the newly created template |
| LAST_SAMPLE_STATUS | 0x05 | Feedback on the last captured sample |
| REMAINING_SAMPLES | 0x06 | Number of samples remaining for completion |
| TEMPLATE_INFOS | 0x07 | List of enrolled templates with their information |
| MAX_TEMPLATE_FRIENDLY_NAME | 0x08 | Maximum length of template friendly name |
The biometric enrollment is implemented through the FPBioEnrollment class, which provides a high-level interface for fingerprint management. The class uses PIN/UV authentication to secure enrollment operations and provides feedback through the FEEDBACK enum, which includes status codes like FP_GOOD, FP_TOO_HIGH, FP_TOO_LOW, and various quality indicators.
classDiagram
class FPBioEnrollment {
+CMD : IntEnum
+PARAM : IntEnum
+FEEDBACK : IntEnum
+__init__(ctap, pin_uv_protocol, pin_uv_token)
+get_fingerprint_sensor_info() Mapping[int, Any]
+enroll_begin(timeout, event, on_keepalive) tuple[bytes, FEEDBACK, int]
+enroll_capture_next(template_id, timeout, event, on_keepalive) tuple[FEEDBACK, int]
+enroll_cancel() None
+enroll(timeout) FPEnrollmentContext
+enumerate_enrollments() Mapping[bytes, str | None]
+set_name(template_id, name) None
+remove_enrollment(template_id) None
}
class FPEnrollmentContext {
+__init__(bio, timeout)
+capture(event, on_keepalive) bytes | None
+cancel() None
}
FPEnrollmentContext --> FPBioEnrollment : "uses"
Diagram sources
- bio.py
Section sources
- bio.py
The PIN/UV authentication extension provides secure authentication mechanisms for CTAP2 commands. It implements the PIN/UV protocol for secure communication between the client and authenticator.
The PIN/UV authentication extension uses the following commands:
| Command | Code | Parameters | Description |
|---|---|---|---|
| GET_PIN_RETRIES | 0x01 | None | Gets the number of PIN retries remaining |
| GET_KEY_AGREEMENT | 0x02 | None | Gets the key agreement for secure communication |
| SET_PIN | 0x03 | KEY_AGREEMENT, NEW_PIN_ENC, PIN_UV_PARAM | Sets a new PIN |
| CHANGE_PIN | 0x04 | KEY_AGREEMENT, PIN_HASH_ENC, NEW_PIN_ENC, PIN_UV_PARAM | Changes an existing PIN |
| GET_TOKEN_USING_PIN | 0x09 | KEY_AGREEMENT, PIN_HASH_ENC, PERMISSIONS, PERMISSIONS_RPID | Gets a PIN/UV token using PIN |
The extension returns responses with the following result codes:
| Result Code | Value | Description |
|---|---|---|
| KEY_AGREEMENT | 0x01 | ECDH key agreement for secure communication |
| PIN_UV_TOKEN | 0x02 | Encrypted PIN/UV authentication token |
| PIN_RETRIES | 0x03 | Number of PIN attempts remaining |
| POWER_CYCLE_STATE | 0x04 | Power cycle state of the authenticator |
| UV_RETRIES | 0x05 | Number of UV attempts remaining |
The PIN/UV authentication is implemented through the ClientPin class, which supports both protocol versions 1 and 2. The implementation uses ECDH key agreement for secure communication and provides token-based authentication for subsequent commands.
classDiagram
class PinProtocol {
<<abstract>>
+VERSION : ClassVar[int]
+encapsulate(peer_cose_key) tuple[Mapping[int, Any], bytes]
+encrypt(key, plaintext) bytes
+decrypt(key, ciphertext) bytes
+authenticate(key, message) bytes
+validate_token(token) bytes
}
class PinProtocolV1 {
+VERSION = 1
+IV = b"\x00" * 16
+kdf(z) bytes
+encapsulate(peer_cose_key) tuple[Mapping[int, Any], bytes]
+encrypt(key, plaintext) bytes
+decrypt(key, ciphertext) bytes
+authenticate(key, message) bytes
+validate_token(token) bytes
}
class PinProtocolV2 {
+VERSION = 2
+HKDF_SALT = b"\x00" * 32
+HKDF_INFO_HMAC = b"CTAP2 HMAC key"
+HKDF_INFO_AES = b"CTAP2 AES key"
+kdf(z) bytes
+encrypt(key, plaintext) bytes
+decrypt(key, ciphertext) bytes
+authenticate(key, message) bytes
+validate_token(token) bytes
}
class ClientPin {
+PROTOCOLS = [PinProtocolV2, PinProtocolV1]
+CMD : IntEnum
+RESULT : IntEnum
+PERMISSION : IntFlag
+__init__(ctap, protocol)
+get_pin_token(pin, permissions, permissions_rpid) bytes
+get_uv_token(permissions, permissions_rpid, event, on_keepalive) bytes
+get_pin_retries() tuple[int, int | None]
+get_uv_retries() int
+set_pin(pin) None
+change_pin(old_pin, new_pin) None
}
PinProtocolV1 --|> PinProtocol
PinProtocolV2 --|> PinProtocolV1
ClientPin --> PinProtocol : "uses"
Diagram sources
- pin.py
Section sources
- pin.py
The large blob storage extension provides functionality for storing and retrieving large amounts of data associated with credentials. It uses encryption and compression to securely store data on the authenticator.
The large blob storage extension uses the following commands:
| Command | Code | Parameters | Description |
|---|---|---|---|
| GET | None | OFFSET, GET_LENGTH | Gets a fragment of the large blob array |
| SET | None | OFFSET, SET_DATA, LENGTH | Sets a fragment of the large blob array |
The extension returns responses containing fragments of the large blob array. The complete array is reconstructed by the client by combining multiple fragments.
The large blob storage is implemented through the LargeBlobs class, which provides methods for reading and writing the entire blob array as well as individual blobs. The implementation uses AES-GCM encryption with a unique nonce for each blob and zlib compression to reduce storage requirements.
classDiagram
class LargeBlobs {
+is_supported(info) bool
+__init__(ctap, pin_uv_protocol, pin_uv_token)
+read_blob_array() Sequence[Mapping[int, Any]]
+write_blob_array(blob_array) None
+get_blob(large_blob_key) bytes | None
+put_blob(large_blob_key, data) None
+delete_blob(large_blob_key) None
}
class _lb_pack {
+_lb_pack(key, data) Mapping[int, Any]
}
class _lb_unpack {
+_lb_unpack(key, entry) tuple[bytes, int]
}
LargeBlobs --> _lb_pack : "uses"
LargeBlobs --> _lb_unpack : "uses"
Diagram sources
- blob.py
Section sources
- blob.py
The authenticator configuration extension provides functionality for configuring various authenticator features. It allows for enterprise attestation, PIN length management, and other configuration options.
The authenticator configuration extension uses the following commands:
| Command | Code | Parameters | Description |
|---|---|---|---|
| ENABLE_ENTERPRISE_ATT | 0x01 | None | Enables enterprise attestation |
| TOGGLE_ALWAYS_UV | 0x02 | None | Toggles the alwaysUV setting |
| SET_MIN_PIN_LENGTH | 0x03 | NEW_MIN_PIN_LENGTH, MIN_PIN_LENGTH_RPIDS, FORCE_CHANGE_PIN | Sets the minimum PIN length |
The extension returns responses with no specific result codes, as the commands are designed to modify the authenticator's configuration state.
The authenticator configuration is implemented through the Config class, which provides methods for enabling enterprise attestation, toggling the alwaysUV setting, and setting the minimum PIN length. The implementation uses PIN/UV authentication to secure configuration operations.
classDiagram
class Config {
+CMD : IntEnum
+PARAM : IntEnum
+is_supported(info) bool
+__init__(ctap, pin_uv_protocol, pin_uv_token)
+enable_enterprise_attestation() None
+toggle_always_uv() None
+set_min_pin_length(min_pin_length, rp_ids, force_change_pin) None
}
Diagram sources
- config.py
Section sources
- config.py
The CTAP2 extensions are integrated with the core CTAP2 command set through the Info object and specific extension commands. The extensions build upon the core functionality to provide additional capabilities while maintaining compatibility with the base protocol.
The core CTAP2 commands that interact with extensions include:
-
GET_INFO: Returns the list of supported extensions in the
extensionsfield -
MAKE_CREDENTIAL: Can include extension inputs in the
extensionsparameter -
GET_ASSERTION: Can include extension inputs in the
extensionsparameter - CLIENT_PIN: Used for PIN/UV authentication required by many extensions
- BIO_ENROLL: Dedicated command for biometric enrollment operations
- LARGE_BLOBS: Dedicated command for large blob storage operations
- CONFIG: Dedicated command for authenticator configuration operations
graph TD
Core[Core CTAP2 Commands] --> GET_INFO
Core --> MAKE_CREDENTIAL
Core --> GET_ASSERTION
Core --> CLIENT_PIN
Extensions[CTAP2 Extensions] --> BIO_ENROLL
Extensions --> LARGE_BLOBS
Extensions --> CONFIG
GET_INFO --> Info[Info Object]
Info --> ExtensionsList[extensions list]
MAKE_CREDENTIAL --> ExtensionsInput[extensions input]
GET_ASSERTION --> ExtensionsInput
CLIENT_PIN --> PIN_UV_TOKEN[PIN/UV Token]
PIN_UV_TOKEN --> ExtensionsAuth[Extension Authentication]
BIO_ENROLL --> Biometric[Biometric Enrollment]
LARGE_BLOBS --> BlobStorage[Large Blob Storage]
CONFIG --> Configuration[Authenticator Configuration]
Biometric --> ExtensionsAuth
BlobStorage --> ExtensionsAuth
Configuration --> ExtensionsAuth
Diagram sources
- base.py
- extensions.py
Section sources
- base.py
- base.py
Each CTAP2 extension has specific security considerations that must be addressed to ensure secure operation:
- All enrollment operations require PIN/UV authentication
- Template IDs are cryptographically secure random values
- Feedback codes provide guidance without revealing sensitive information
- The enrollment process is designed to prevent brute force attacks
- Protocol version 2 uses HKDF for key derivation with separate HMAC and AES keys
- Protocol version 1 uses simpler key derivation but is still secure
- PINs are padded to a fixed length to prevent length-based attacks
- PIN/UV tokens are encrypted and authenticated using secure cryptographic primitives
- Each blob is encrypted with AES-GCM using a unique nonce
- Compression is applied before encryption to reduce storage requirements
- The large blob key is derived from the credential and is unique per credential
- Integrity is verified using SHA-256 of the entire blob array
- All configuration operations require PIN/UV authentication
- Enterprise attestation can only be enabled, not disabled
- Minimum PIN length can only be increased, not decreased
- Configuration changes are persistent across power cycles
The CTAP2 extensions are used in various scenarios to enhance the functionality of authenticators. The following examples demonstrate practical usage patterns:
sequenceDiagram
participant Client
participant Authenticator
Client->>Authenticator : GET_INFO()
Authenticator-->>Client : Info with bioEnroll option
alt bioEnroll supported
Client->>Client : Initialize FPBioEnrollment
Client->>Authenticator : BIO_ENROLL(ENROLL_BEGIN)
Authenticator-->>Client : Template ID, feedback, remaining samples
loop For remaining samples
Client->>Authenticator : BIO_ENROLL(ENROLL_CAPTURE_NEXT)
Authenticator-->>Client : Feedback, remaining samples
end
Client->>Client : Enrollment complete
else bioEnroll not supported
Client->>Client : Handle error
end
Diagram sources
- bio.py
sequenceDiagram
participant Client
participant Authenticator
Client->>Authenticator : MAKE_CREDENTIAL with largeBlobKey extension
Authenticator-->>Client : Attestation with largeBlobKey
Client->>Client : Store largeBlobKey
Client->>Authenticator : GET_ASSERTION with largeBlob extension
Authenticator-->>Client : Assertion with largeBlobKey
Client->>Authenticator : LARGE_BLOBS(GET) with PIN/UV authentication
Authenticator-->>Client : Blob data fragment
Client->>Client : Reconstruct and decrypt blob
Diagram sources
- blob.py
- extensions.py
sequenceDiagram
participant Client
participant Authenticator
Client->>Authenticator : GET_INFO()
Authenticator-->>Client : Info with clientPin option
alt clientPin supported
Client->>Authenticator : CLIENT_PIN(GET_KEY_AGREEMENT)
Authenticator-->>Client : Key agreement
Client->>Client : Generate shared secret
Client->>Authenticator : CLIENT_PIN(GET_TOKEN_USING_PIN)
Authenticator-->>Client : Encrypted PIN/UV token
Client->>Client : Decrypt and validate token
Client->>Authenticator : Subsequent commands with PIN/UV token
else clientPin not supported
Client->>Client : Handle error
end
Diagram sources
- pin.py