Host Interfaces Bluetooth Secure CCID
April 13, 2023 at 2:39 AMSecure CCID (PC/SC) over Bluetooth
The Secure BLE CCID host interface is an extension of the BLE CCID (PC/SC) implementation. It uses the same characteristics, with the same constraints and restrictions, yet, when secure communication is enabled, the CCID over CCID frames are ciphered and authenticated.
Secure communication starts when the host initiate a mutual authentication sequence with the SpringCore device. The secure communication may be enforced in the configuration of the device. In this case, the device does not accept any command before the mutual authentication sequence takes place.
During the mutual authentication sequence, at set of session keys are generated from the nonces exchanged between the host and the device (one key for ciphering the payloads, two keys to compute the CMAC).
After the mutual authentication sequence, all the exchanges over the CCID_PC_To_RDR and CCID_RDR_To_PC characteristics must use secure communication.
The host may initiate a new mutual authentication sequence at any time, if the synchronization has been lost or to prevent using the session keys for a too long period.
Format of the messages with secure communication
CCID_Status
The specification of the CCID Status characteristic is not modified when secure communication is enabled.
CCID_PC_To_RDR
When secure communication is enabled, the payload is padded and ciphered (not the header), and a cryptographic message authentication code (CMAC) is added after the payload.
Format of the message (secure communication)
Bytes | Content |
---|---|
0-9 | Header |
10-N | Ciphered Payload = AES128-CBC ( Payload || Padding ) |
N+1 - N+4 | Authentication code = AES128-CMAC ( Header || Ciphered Payload ) |
Header
Byte | Content |
---|---|
0 | Command code, see table below |
1-4 | Length of payload, LSB-first. The highest-level bit (bit 31) is set to denote that the payload is ciphered and that the length includes the padding and the CMAC. |
5 | Slot number |
6 | Sequence number |
7-9 | Command parameters |
CCID_RDR_To_PC
When secure communication is enabled, the payload is padded and ciphered (not the header), and a cryptographic message authentication code (CMAC) is added after the payload.
Format of the message (secure communication)
Bytes | Content |
---|---|
0-9 | Header |
10-N | Ciphered Payload = AES128-CBC ( Payload || Padding ) |
N+1 - N+4 | Authentication code = AES128-CMAC ( Header || Ciphered Payload ) |
Header
Byte | Content |
---|---|
0 | Response code, see table below |
1-4 | Length of payload, LSB-first. The highest-level bit (bit 31) is set to denote that the payload is ciphered and that the length includes the padding and the CMAC. |
5 | Slot number |
6 | Sequence number |
7 | Slot status |
8 | Slot error |
9 | RFU |
Mutual authentication
The mutual authentication is initiated by the host in a RDR_To_PC_Escape command, the payload of the command being a PROTOCOL : AUTHENTICATE instruction.
Notation
In the following paragraphs,
- EECB (K, x) is the AES128-ECB Encrypt (one-block encipher) function, using key K over plain block x,
- E-1ECB (K, y) is the AES128-ECB Decrypt (one-block decipher) function, using key K over ciphered block y,
- ECBC (K, x, iv) is the AES128-CBC Encrypt (cipher block chaining mode, encipher) function, using key K and initialization vector iv over plain message x,
- E-1CBC (K, y, iv) is the AES128-CBC Decrypt (cipher block chaining mode, decipher) function, using key K and initialization vector iv over ciphered message y.
Host AUTHENTICATE command
Bytes | Value | Explanations |
---|---|---|
0 | 6B |
PC_To_RDR_Escape |
1-4 | 04000000 |
Plain communication, length of payload = 4 bytes |
5 | 00 |
Slot number (don’t care) |
6 | xx |
Current sequence number |
7-9 | 000000 |
RFU |
10 | 00 |
Class = PROTOCOL |
11 | 0A |
Instruction = AUTHENTICATE |
12 | 01 |
Authentication method = AES |
13 | 00 01 |
User access (KAUTH = HostCommUserKey) Admin access (KAUTH = HostCommAdminKey) |
Device response - Authentication Step 1
The device
- Generates a 16-byte nonce RndB,
- Sends E ( K, RndB ) where KAUTH is the authentication key selected by the host, as it is known by the device (HostCommUserKey or HostCommAdminKey).
Bytes | Value | Explanations |
---|---|---|
0 | 83 |
RDR_To_PC_Escape |
1-4 | 11000000 |
Plain communication, length of payload = 17 bytes |
5 | 00 |
Slot number (same as host’s) |
6 | xx |
Sequence number (same as host’s) |
7-9 | 000000 |
RFU |
10 | FF |
Status = FOLLOWING (see PROTOCOL : Status) |
11-26 | EECB ( KAUTH , RndB ) | First device cryptogram |
Host command - Authentication Step 2
The host
- Generates a 16-byte nonce RndA,
- Retrieves RndB by deciphering the response,
- Computes RndB’ = RndB << 8 (rotate one byte to the left, with carry),
- Sends EECB ( KAUTH , RndA ) || EECB ( KAUTH , RndB’ ) where KAUTH is the authentication key as it is known by the host.
Bytes | Value | Explanations |
---|---|---|
0 | 6B |
PC_To_RDR_Escape |
1-4 | 22000000 |
Plain communication, length of payload = 34 bytes |
5 | 00 |
Slot number (don’t care) |
6 | xx |
Current sequence number (+1 since last exchange) |
7-9 | 000000 |
RFU |
10 | 00 |
Class = PROTOCOL |
11 | FF |
Instruction = FOLLOWING |
12-43 | EECB ( KAUTH , RndA ) || EECB ( KAUTH , RndB’ ) | Host cryptogram |
The device deciphers the host cryptogram. If the decrypted RndB’ matches with RndB, the device knows that it can trust the host.
Device response - Authentication Step 3
The device
-
Retrieves RndA from the command,
-
Computes RndA’ = RndA << 8 (rotate one byte to the left, with carry),
-
Sends EECB ( KAUTH , RndA’ ).
Bytes | Value | Explanations |
---|---|---|
0 | 83 |
RDR_To_PC_Escape |
1-4 | 11000000 |
Plain communication, length of payload = 17 bytes |
5 | 00 |
Slot number (same as host’s) |
6 | xx |
Sequence number (same as host’s) |
7-9 | 000000 |
RFU |
10 | 00 |
Status = SUCCESS (see PROTOCOL : Status) |
11-26 | EECB ( KAUTH , RndA’ ) | Second device cryptogram |
The host deciphers the device cryptogram. If the decrypted RndA’ matches with RndA, the host knows that it can trust the device.
From now on, secure communication shall be used.
Session keys and first init vector
Both the host and the device generate the same session keys as follow:
- Assemble SV1 = RndA[0..3] || RndB[0..3] || RndA[8..11] || RndB[8..11]
- Assemble SV2 = RndA[4..7] || RndB[4..7] || RndA[12..15] || RndB[12..15]
- Compute the session encryption key KENC = EECB ( KAUTH , SV1 ),
- Compute the session authentication key KMAC = EECB ( KAUTH , SV2 ).
- Assemble SVMAC = RndA XOR RndB
- Compute the first initialization vector IV0 = EECB ( KMAC , SVMAC )
Ciphering and CMACing
Ciphering and CMACing is implemented only over the CCID_PC_TO_RDR and CCID_RDR_TO_PC characteristics. CCID_STATUS uses plain communication only.
Init vectors
The subsequent exchanges will use CBC (cipher block chaining). Both peers have to maintain two init vectors for the CBCs:
- The IVSEND is used to cipher and MAC the outgoing messages,
- The IVRECV is used to cipher and MAC the ingoing messages.
Both evolve independently, message after message.
For the first message, they are inited to the same value: IV0.
Frames without a payload
Only a 8-B CMAC is added after the 10-B CCID header.
Sender rules:
-
Create the 10-B message, containing only the CCID header, with Length equal to
00000000
, -
Compute CMAC = ECBC ( KMAC , Header ||
8000..00
, IVSEND,N )where
- Header ||
8000..00
is the Header followed by80
and padded with00
’s to reach 16 bytes, - IVSEND,N is the current init vector for sending. Keep the complete CMAC as IVSEND,N+1 for the next transmission.
- Header ||
-
Adjust the Length field in the Header to
08000080
(8-B of CMAC “in the payload”, highest-level bit set to denote secure communication, transmitted LSB-first), -
Transmit the 8 first bytes of the CMAC at the end of the message.
Receiver rules:
-
Recognize a secure, CMAC only message from its Length field equal to
08000080
, -
Adjust the Length field to
00000000
, -
Compute CMAC = ECBC ( KMAC , Header ||
8000..00
, IVRECV )where
- Header ||
8000..00
is the Header followed by80
and padded with00
’s to reach 16 bytes, - IVRECV,N is the current init vector for receiving. Keep the complete CMAC as IVRECV,N+1 for the next reception.
- Header ||
-
Verify that the 8 first bytes of the computed CMAC match with the ones received.
Frames with a payload
The CMAC is computed over the plain message, then the payload is padded and ciphered, and the 8-B CMAC is appended at the end of the message.
Sender rules:
-
Create the message with a 10-B Header and PayloadPLAIN. The value of field Lengh is between 1 (
0100000
) and 64kB (000010000
), -
Compute CMAC = ECBC ( KMAC , Header || PayloadPLAIN ||
8000..00
, IVSEND,N )where
- Header || PayloadPLAIN ||
8000..00
is the message padded to reach a multiple of 16 bytes (if the original message length is already 16 bytes, 16 padding bytes are added), - IVSEND,N is the current init vector for sending. Keep the complete CMAC as IVSEND,N+1 for the next transmission.
- Header || PayloadPLAIN ||
-
Add
80
at the end of the Payload and add as many00
’s as needed to reach a multiple of 16 bytes; store the new length of the Payload in the Length field in the header, -
Cipher the Payload (not the Header!): PayloadCIPHER = ECBC ( KENC , PayloadPLAIN || Padding , IVSEND,N )
(note that IVSEND,N is used, not IVSEND,N+1 that is the current CMAC but the next IV)
-
Increase the Length field in the Header by 8 bytes (8-B of CMAC are to be added “in the payload”), and set the highest-level bit to denote secure communication,
-
Transmit the 8 first bytes of the CMAC at the end of the message.
Receiver rules:
-
Recognize a secure message from the highest-level bit set in Length,
-
Reset the highest-level bit of Length and decrease the value of Length by 8,
-
Decipher the Payload: PayloadPLAIN || Padding = E-1CBC ( KENC , PayloadCIPHER , IVRECV,N )
-
Verify that the Padding is OK, decrease the value of Length to drop the Padding bytes,
-
Compute CMAC = ECBC ( KMAC , Header || PayloadPLAIN ||
8000..00
, IVRECV,N )where
- Header || PayloadPLAIN ||
8000..00
is the message padded to reach a multiple of 16 bytes (if the original message length is already 16 bytes, 16 padding bytes are added), - IVRECV,N is the current init vector for receiving. Keep the complete CMAC as IVRECV,N+1 for the next reception.
- Header || PayloadPLAIN ||
-
Verify that the 8 first bytes of the computed CMAC match with the ones received.
Exception handling
If an error occurs during the mutual authentication process (typically because the host does not know the right KAUTH…), the ERR_AUTHENTICATION status is returned (see PROTOCOL : Status) but the BLE communication channel is kept open.
After the mutual authentication has been successfully performed, if the device
- Receives a plain message instead of a secure message,
- Receives a message with a wrong CMAC,
- Receives a message which deciphers to a wrong Padding,
it does send the ERR_AUTHENTICATION error, and then closes the BLE link (disconnect).
The host has to connect again and start a new mutual authentication.