U2F Protocol Overview

A Quickstart Guide to Understanding U2F

September 19, 2017
fedora fedora-security

U2F Protocol Overview

This document serves as an overview of the U2F multi-factor authentication specifications as published by the FIDO Alliance. It does not replace the offical specifications but seeks to provide a quick run-through of how the protocol is built. U2F basically works via two main commands: register and authenticate.

When a server wants to use a U2F device for authentication, it asks the host (usually the client computer) to issue a register command to the device. This command creates a new signing key pair and the public key is returned to the server along with an opaque handle (for later reference) and an attestation certifciate (proving trust of the U2F device to the server).

Then, when it wishes to authenticate the user, the server asks the host to issue an authenticate command to the device. The device then signs a nonce from the server and returns the signature. This proves that the user is in posession of the key. It also returns a counter, proving to the server that the device has not been cloned.

U2F provides a high degree of security and a user-friendly workflow. It is supported by Chrome (natively) and Firefox (via an extension).

U2F Layers

The U2F Protocol happens across two layers:

  1. The Transport Layer
  2. The APDU Layer

All multi-byte integers are in network byte order (big endian).

The Transport Layer

The Transport Layer is responsible for breaking up packets into frames for transport from the computer to the U2F device over HID or Bluetooth. U2F-over-NFC does not use a transport layer. A full packet looks like this:

U2F Packet Field Size (Bytes)
Channel Identifier (CID) 4 (HID Only)
Command (CMD) 1
Data Length 2
Data 0+

The Channel Identifier (CID) is only used for the HID transport and is completely omitted over Bluetooth.

The CMD byte always has the first bit set and contains the number assigned to this particular command. Most commonly, this command will be the MSG command.

If the packet size is less than the maximum transmission unit (MTU), then it is sent directly. Otherwise, the packet is broken up into MTU-sized frames. The first frame is just the beginning of the packet truncated to fit in the frame. Subsequent frames are simply the additional fragments of the packet with a prefix SEQ byte (and, over HID, the CID). The SEQ byte always has the first bit unset, which allows you to distinguish continuation frames from the start of a new packet. It begins with a zero value and increments for each frame sent. A subsequent frame looks like this:

U2F Frame Field Size (Bytes)
Channel Identifier (CID) 4 (HID Only)
Sequence (SEQ) 1
Data 1+


Below you will find a survey of the most common Transport Layer commands. For the full details on all available commands, please see the U2F specifications.

MSG (CMD = 0x83)

The MSG command contains an APDU request or reply and represents the next layer in communication. This will be discussed in the APDU Layer section below.

PING (CMD = 0x81)

The PING command simply returns the packet to the sender without modification.

ERROR (CMD = 0x84)

The ERROR command is only ever sent as a response. The data contains a one-byte error code. This is only used to communicate errors at the Transport Layer. The APDU Layer has its own error handling.

INIT (CMD = 0x86, HID Only)

The INIT command is only used for HID. Its purpose is to allow the U2F device to assign a unique CID and to get some information about the hardware device. The request contains an 8-byte nonce. The reply data looks like this (fields are 1 byte unless otherwise noted):

U2F INIT Packet Data Field Size (Bytes)
Nonce 8
Channel Identifier (CID) 4
Protocol Version 1
Major Device Version 1
Minor Device Version 1
Build Device Version 1
Capability Flags 1

The request and reply are sent over the reserved broadcast channel (CID = 0xffffffff).

KEEPALIVE (CMD = 0x82, Bluetooth Only)

The KEEPALIVE command is only ever sent from Bluetooth U2F devices to the host. Its purpose is to identify to the host that the request is still being processed or is waiting for user confirmation. Its data contains a single byte indicating the reason for the delayed response.

The APDU Layer

When a MSG command packet is received by the device, the data contains an APDU request. Likewise, the host expects an APDU reply. I will not describe the APDU format in detail. Let it suffice to say that APDU is similar to the transport layer’s packet. It can represent a command (via the CLA and INS bytes), parameters to that command (the P1 and P2 bytes) and a miscelaneous data payload. Likewise, the APDU Layer has its own error handling for errors that occur within this layer.


VERSION (CLA = 0x00, INS = 0x03)

The VERSION command takes no input parameters and no input data. It simply replies with the version of the U2F Raw Message Format supported. There is currently only one version, which is represented as the UTF-8 encoding of the string U2F_V2 without a NULL terminator.

REGISTER (CLA = 0x00, INS = 0x01)

The REGISTER command takes no input parameters. The input data is in the following format:

U2F REGISTER Request Field Size (Bytes)
Challenge Parameter 32
Application Parameter 32

The U2F device will create a new P-256 signing keypair used for future authentications and will return back the following data:

U2F REGISTER Reply Field Size (Bytes)
Reserved (0x05) 1
Public Key 65
Key Handle Length 1
Key Handle 0-255
Attestation Certificate X.509 (DER)
ECDSA (P-256) Signature 71-73

The Public Key field contains the public key of the newly-created signing key pair. The Key Handle is an opaque field identifying the newly created key pair. The final two fields need some additional explanation.

Remote servers need a way to trust the U2F device. This comes in the form of an attestation key pair which may or may not be different from the newly-created signing key pair. The attestation key pair signs the following payload and inserts the signature into the reply (above):

U2F REGISTER Signature Field Size (Bytes)
Reserved (0x00) 1
Application Parameter 32
Challenge Parameter 32
Key Handle 0-255
Public Key 65

If the remote server trusts the attestation certifciate, then it can also trust the newly-generated signing key pair and key handle by validating the attestation signature. Usually, the server will trust the attestation certificate via an intermediary certification authority.

AUTHENTICATE (CLA = 0x00, INS = 0x02)

The AUTHENTICATE command takes a parameter (in P1) and input data in the following format:

U2F AUTHENTICATE Request Field Size (Bytes)
Challenge Parameter 32
Application Parameter 32
Key Handle Length 1
Key Handle 0-255

If P1 == 0x07 (check only), the device only verifies if the Application Parameter and Key Handle are valid for this U2F device. Otherwise, if P1 == 0x03 (enforce user presence and sign) or P1 == 0x08 (don’t enforce user presence and sign), the U2F device then signs a payload in the following format:

U2F AUTHENTICATE Signature Field Size (Bytes)
Application Parameter 32
User Presence Flags 1
Counter 4
Challenge Parameter 32

The counter is used to detect key theft from the U2F device. It may be global or per key handle. This payload is signed by the signing key pair.

Then a response is returned in the following format:

U2F AUTHENTICATE Reply Field Size (Bytes)
User Presence Flags 1
Counter 4
ECDSA (P-256) Signature 71-73

The User Presence field contains flags identifying the level of user presence testing.

comments powered by Disqus