Fobnail API
Fobnail Token exposes API over CoAP server exposed over UDP.
General considerations
This document describes API (major) version 1, and all API endpoint addresses
are relative to (starting with) /api/v1
. The version will be increased only
when backward-incompatible changes are done.
General request handling rules
Some APIs create temporary objects that live at most as long as the client is connected. To check connection status, the server issues CoAP Ping requests, which clients must respond to in order to avoid losing their objects.
When an object is created, the server responds with 2.01, Location-Path
specifying the resource's path (a numeric object ID). Object IDs are specific to
a client - a client cannot access object IDs of other clients. Location-Path
is a string option, whereas object ID is an integer, so it must be encoded as a
string. Object IDs may be passed as part of the CBOR payload (as an integer) or
in URI (as a string).
If the Content-Format
option is not present, Fobnail Token assumes that
Content-Format
is application/octet-stream
. All requests which pass
CBOR-encoded data must set Content-Format
option to application/cbor
for
Fobnail Token to interpret the payload as CBOR. The server responds with
4.00 (Bad Request) if unknown or invalid Content-Format
is given. If
passing CBOR-encoded data which is improperly encoded or not valid (e.g.,
required fields missing) server responds with 4.00. Passing
application/cbor
to an endpoint that expects application/octet-stream
is
invalid and will result in a 4.00 response.
The client may send one or more Accept
options which must be handled by
the server. If the server can not respond in the format requested by the
Accept
options, it must respond with 4.06 (Not Acceptable).
Conditional Request Options are not supported and will result in 4.02 (Bad Option). The payload should contain a human-readable message describing what options are not supported. See RFC7252 section 5.4.1 for details.
Each response from the Fobnail Token must contain the Content-Format
option unless it is an error response with a diagnostic payload. See
RFC7252 for
details.
Error responses
Fobnail Token may return error codes as defined by the CoAP specification. An
error response may contain an additional context sent as a payload. All
cacheable error responses must have Max-Age
set to 0.
Error response must not contain the Content-Format
option. Message (if present)
must be passed as a raw UTF-8 string.
Fobnail Data format
Fobnail uses CBOR (with a few exceptions) to transmit structured data from Fobnail to Attester and from Attester to Fobnail. We use a subset of RFC7049 (no tagging and no extensions).
Clients are required to set Content-Format
to application/cbor
when
transmitting CBOR-encoded data.
Data signing
A signature is generated by taking an already CBOR-encoded object, a nonce (generated by Fobnail), and signing the hash of both of them. The nonce is appended to the CBOR blob as plain bytes. The resulting signature and original data (without nonce) are wrapped into another CBOR object:
{
// The data we signed (nested CBOR, without nonce)
// major 2 (byte array)
"data": [0x42, ...],
// The signature we just computed (major 2, byte array)
"signature": [0x20, ...]
}
To obtain nonce for data signing, please use the /nonce endpoint.
Exception
Request for /attest/{id}
command has nonce explicitly included in sent structure.
No additional data is appended before signing. Sent CBOR object has the same
format as above. This (along with other mechanisms) ensures freshness of Claims,
in addition to freshness of Evidence (see RATS architecture for description of
those artifacts).
API endpoints
Please note that all addresses listed below are relative to /api/v1
, except
the /api/version
endpoint which is used to query supported API versions. To
query supported API versions, please issue GET request to /api/v1
. Server
responds with 2.05 code and CoAP payload contains CBOR-encoded message:
{
// Array of supported API versions (major 4)
"versions": [
// API version 1 (major 0)
1,
// API version 2 (major 0)
2,
// API version 3 (major 0)
3,
],
}
Uncategorized endpoints
Endpoint Name | Method | Arguments |
---|---|---|
/nonce | GET | None |
/nonce
This endpoint is used to receive the nonce to be used for data signing. When called, Fobnail Token generates new nonce and responds with 2.05. Payload contains nonce as a raw byte array (currently 32 bytes).
Nonce is bound to each client and is valid until it is used. When used, the
client must call /nonce
again to obtain a new nonce.
Some requests return a new nonce as part of their response That's the case with
the /attest
endpoint and client must use nonce from /attest
response in call
to /attest/{id}
. Attempt to call /nonce
endpoint will invalidate
Attestation Context.
Fobnail Token provisioning
Endpoint Name | Method | Arguments |
---|---|---|
/admin/token_provision | POST | PO certificate chain |
/admin/provision_complete | POST | Fobnail Identity/Encryption certificate |
These APIs may only be executed when Fobnail Token is in an unprovisioned state. Fobnail Token must respond with 4.03 if these APIs are called after provisioning is complete.
/admin/token_provision
PO certificate chain is transferred as an ordered array of raw DER certificates, starting with the certificate directly after the root certificate (the Fobnail Token already knows the root).
{
// Array of certificates in DER format (major 4)
"certs": [
// CA immediately under root (major 2)
[ 0x30, 0x82, 0x03, 0x8b, ... ],
// Intermediate CAs, if any
...
// PO certificate for certificate signing (major 2)
[ 0x30, 0x82, 0x04, 0x8f, ... ]
],
}
Fobnail Token verifies certificate the chain against the trust anchor embedded into its firmware. If verification fails, 4.03 is returned.
On success, Fobnail generates an Identity/Encryption key, prepares a Certificate
Signing Request, and responds with a 2.01 status code, response must
contain CSR as a payload. CSR is sent in DER format and Content-Format
must be set to application/octet-stream
.
/admin/provision_complete
The client sends a certificate generated from CSR previously provided by
/admin/token_provision
. Fobnail Token verifies the provided certificat
correctness, such as whether it is properly signed, has correct extensions
defined, etc. On error 4.03 is returned.
On success, 2.01 is returned, and provisioning is complete.
The certificate is sent as a raw DER, and Content-Format
must be set to
application/octet-stream
, or the request will be rejected. Future API versions
may accept application/cbor
.
Platform provisioning
Endpoint Name | Method | Arguments |
---|---|---|
/admin/provision/ek | POST | EK certificate chain |
/admin/provision/aik | POST | AIK public part |
/admin/provision | POST | Credential Activation result |
/admin/provision/{id}/meta | POST | Platform metadata |
/admin/provision/{id}/rim | POST | Reference Integrity Measurements |
/admin/provision/{id} | POST | None |
/admin/provision/ek
EK certificate chain is transferred in the same format as PO certificate chain described above. The certificate directly after the root certificate is the first certificate in the array, while the EK certificate is the last.
Client issues POST request with Content-Format
set to application/cbor
and
payload containing CBOR-encoded certificate array as described above. Fobnail
Token verifies the provided certificate chain against one of the roots embedded
into its firmware. On success 2.01 response is returned, Location-Path
contains EK object ID. If EK certificate chain verification fails, 4.03 is
returned.
/admin/provision/aik
AIK is transferred in TPM format (TPM2B_PUBLIC structure). Re-encoding this into CBOR would strip essential data. Fobnail needs unmodified TPM2B_PUBLIC to successfully perform the "make credential" operation which is needed for credential activation. Unmodified AIK and EK object ID are wrapped into CBOR:
{
// AIK (TPM2B_PUBLIC, major 2)
"aik": [0x20, 0x01, 0x00, ...],
// EK object ID (major 0 - unsigned integer)
"ek": 1
}
Fobnail Token verifies whether AIK is a valid TPM2B_PUBLIC and whether the key's
algorithm is supported. On success, 2.01 response is returned, and
Location-Path
contains AIK object ID. Response payload contains a challenge
(Make Credential) prepared using the provided AIK and EK.
{
"idObject": [0x20, 0x02, 0x10, ...],
"encSecret": [0x20, 0x02, 0x10, ...],
}
If AIK verification fails, 4.03 is returned, and the payload may contain additional context. If provided EK object ID is invalid, 4.04 is returned.
/admin/provision
This endpoint is used to create a Provisioning Context. The client provides the result of Credential Activation as a payload:
{
// EK object ID of the EK used to make the challenge (major 0)
"ek": 1,
// AIK object ID of the AIK used to make the challenge (major 0)
"aik": 2,
// Decrypted secret - output of TPM Credential Activation (major 2)
"secret": [0x00, 0x01, 0x02, 0x03, ...]
}
Fobnail Token verifies whether the decrypted secret matches the secret kept in
Fobnail Token's memory. If verification is successful, Fobnail Token creates a
Provisioning Context and responds with a 2.01 response (Location-Path
contains Provisioning Context ID).
If the secret does not match, 4.03 is returned. If either EK object ID or AIK object ID is invalid, 4.04 is returned.
/admin/provision/{id}/meta
This method is used to upload platform metadata. After upload, the platform
metadata is bound to the provisioning context specified by {id}
.
Metadata is sent in CBOR-encoded format (also described here in more detail). Example metadata looks like this
{
// metadata version, used to detect backward-incompatible changes
// (major 0, unsigned integer)
"version": 1,
// device manufacturer extracted from SMBIOS tables (major 3, UTF-8 string)
"manufacturer": "Gigabyte",
// device model extracted from SMBIOS tables (major 3, UTF-8 string)
"model": "Gigabyte A520 AORUS ELITE",
// MAC address of primary network card (major 2, byte string)
"mac": [0xea, 0x96, 0x91, 0x87, 0x26, 0x8d],
// device serial number extracted from SMBIOS tables (major 3, UTF-8 string)
"sn": "S21N559B431",
}
Client must sign metadata with AIK (see the Data signing section above).
Fobnail Token verifies the provided metadata against AIK bound to the
Provisioning Context. If signature verification fails, 4.03 is returned. If
the metadata format is invalid, 4.00 is returned. On success, either
2.01 or 2.04 are returned. On the first successful call, 2.01 is
returned (Location-Path
must not be present), and on subsequent calls,
2.04 is returned to signify that metadata has been replaced.
/admin/provision/{id}/rim
RIM holds PCR registers (from TPM) which are used for attestation. It doesn't
contain information about the Attester since these are part of the metadata. RIM
may contain multiple PCR banks (depending on the hash algorithm: SHA-1, SHA-256,
others). Each PCR bank contains a bitmap of present PCRs (pcrs
field) and an
array of PCR itself. The LSB of bitmap corresponds to PCR0. RIMs are sent in
CBOR:
{
// PCR update counter, incremented every time when some PCR gets updated.
"update_ctr": 0,
// Array of PCR banks (major 4)
"banks": [
// First PCR bank
{
// Algorithm ID as used by TPMs (TPM2_ALG_* constants from libtss)
// (major 0, unsigned integer)
"algo_id": 0xb,
// Bitmap of present PCRs (major 0, unsigned integer)
"pcrs": 0xffffffff,
// Array of PCR registers, each register holds hash corresponding to the
// type of bank.
// There must be as many hashes as set bits in "pcrs" field. If
// these don't match then RIM is considered invalid.
"pcr": [
// Size of hash is verified, whether all hashes in a bank have
// the same size, if these don't match then entire RIM is
// considered invalid
[ 0x00, 0x00, 0x00, 0x00, ... ],
...
]
},
// Another PCR bank (major 5, map)
{
"algo_id": 0xb,
"pcrs": 0x000000ff,
// major 4 (array)
"pcr": [
// major 2 (byte string)
[ 0x00, 0x00, 0x00, 0x00, ... ],
...
]
}
],
}
Client must sign RIM with AIK (see the Data signing section above).
Fobnail Token verifies RIM signature and format. If signature verification
fails, 4.03 is returned. If RIM has an invalid format, 4.00 is returned.
On success 2.01 or 2.04 is returned. On the first successful call,
2.01 is returned (Location-Path
must not be present); on subsequent calls,
2.04 is returned to signify that the previous RIM has been replaced with the
new RIM.
/admin/provision/{id}
POST request to this endpoint results in writing data attached to the Provisioning Context into persistent storage. Currently, this request does not contain any data, and payload must be empty or 4.00 response will be returned.
Fobnail Token verifies whether all required data has been provided (metadata and RIM is mandatory). On error, 4.03 response is returned. If verification is successful, Fobnail Token writes all required data into persistent storage, completing the provisioning process. If an error occurs while writing into persistent storage, 5.00 is returned (the payload may contain additional context). On success, 2.04 response is returned to signify provisioning is complete. At this point, the Provisioning Context becomes invalid, and all subsequent requests to the Provisioning Context will return 4.04.
Attestation
Endpoint Name | Method | Arguments |
---|---|---|
/attest | POST | Platform metadata |
/attest/{id} | POST | Output of TPM quote |
/attest
The client sends platform metadata in the same format as when calling
/admin/provision/{id}/meta
. Metadata must be signed by the same AIK that
was used during platform provisioning. If verification is successful 2.01 is
returned (otherwise 4.04) and Location-Path
contains Attestation Context
ID. The response's payload contains PCR selection and nonce:
{
// Array of PCR banks (major 4)
"banks": [
// First PCR bank
{
// ID of algorithm used by PCRs (major 0)
"algo_id": 0x0004,
// Bitmap of present PCRs (major 0, unsigned integer)
"pcrs": 0xffffffff,
},
// Another PCR bank (major 5, map)
{
"algo_id": 0x000b,
"pcrs": 0x000000ff,
}
],
// Nonce to be passed to TPM_Quote() (major 2)
"nonce": [0x00, 0x01, 0x02, 0x03, ...]
}
The PCR selection format is similar to that of RIM but
stripped of unnecessary fields. Due to the nature of PCR selection parsing done
by TPM2_Quote()
, order of PCR banks matters.
/attest/{id}
The client sends the evidence to this endpoint (the result of TPM Quote). Based on the evidence, Fobnail Token decides whether the platform is trustworthy or not. If Fobnail Token decides that the platform is trustworthy, 2.04 response is returned, 4.03 otherwise.
If attestation is successful, Fobnail Token unlocks access to the Fobnail Token Services.
Fobnail Token Services
Fobnail Token Services are available after successful platform attestation. Fobnail Token can store cryptographic keys (or other data) in its internal flash. Depending on the key's type (symmetric or asymmetric) and usage permissions, various operations are available. For symmetric keys, it is encryption and decryption. For asymmetric keys, it is signing, decryption, KDF, and public key read (the client extracts the public key and does encryption on its own).
Key, once created, may not be read (except for the public key). Fobnail Token performs cryptographic operations on behalf of the client, which may be slow. If this behavior is undesired, Secure Storage may be used instead to store the key as a file inside Fobnail Token.
Endpoint Name | Method | Arguments |
---|---|---|
/crypto | POST | Key name, type, etc. |
/crypto/{id}/type | GET | None |
/crypto/{id}/encrypt | POST | Data to encrypt |
/crypto/{id}/decrypt | POST | Data to decrypt |
/crypto/{id}/sign | PUT | Data to sign |
/crypto/{id}/pub | GET | None |
/storage/fs/{name} | GET | File name |
/storage/fs/{name} | PUT | File name and file contents |
/storage/fs/{name} | DELETE | File name |
If the platform has not been attested (or failed attestation), these APIs will return a 4.04 error. If attestation is successful, Fobnail Token checks whether a specified key exists and whether the platform has access to that key. If the key or file does not exist or there is no access 4.04 error is returned.
Note: currently, crypto API is not fully defined. Future versions of this document will address this problem.
GET /storage/fs/{name}
The client sends a request to this endpoint to read a file. The file path is
encoded as part of the URI. If the file exists (and if it's accessible),
2.05 response is sent with the file contents as the payload. Max-Age
option must be set to 0 to prevent caching. ETag option must not be
present in the response, and if present in the request, it must be ignored.
The GET method always returns the full contents of the file. Further versions of this document may define API using the FETCH method from RFC8132.
Fobnail Token attempts to open the requested file and returns 2.05 response with file contents. 4.04 is returned if the file does not exist or there is no access.
PUT /storage/fs/{name}
This endpoint is used to write file contents. Fobnail Token attempts to write the specified file (URI) with the provided payload. If successful, Fobnail Token returns either 2.01 (when the file has been created) or 2.04 (when the file has been updated). Request may fail in the following situations:
- If the name contains invalid characters (name may not contain NULLs and slash, '.' and '..' names are banned), 4.03 error is returned.
- If the platform is not allowed to create a file, 4.03 error is returned.
- If writing the file failed for any reason - 5.00 error (payload may contain additional context).
DELETE /storage/fs/{name}
This endpoint is used to delete a file. The file name is provided in URI, and the payload should be empty. On success, or if the file didn't exist before 2.02 is returned. On error, such as when the file does exist, but there is no permission to remove it, 4.03 is returned.