Device Access Control
The device access control list (/auth/at) and the certificate trust list
(/auth/crts) control which peers can access device resources. The access
control list stores credentials and permission scopes. The trust list stores
trusted CA certificates for (D)TLS authentication. A Management and
Commissioning Client (MaC) with if.sec scope configures both resources
during commissioning.
Access Token Configuration
The MaC installs access tokens during the PASE handshake and configuration download phases. See Device Bootstrapping for the full commissioning sequence.
Before any access decision, the device authenticates the peer by matching an OSCORE pre-shared key or by validating an X.509 certificate chain with the trust list. The device then checks whether the access token scope covers the requested resource.
Access Token Table (/auth/at)
A MaC writes access tokens during onboarding and configuration download. KNX IoT supports two credential types (X.509 support is optional):
- OSCORE (
cnf→OSCORE key material): pre-shared key context for application-layer encryption. Used for group communication (multicast and unicast S-Mode), datapoint read/write, MaC administrator access, etc. - X.509 (
cnf→ certificate reference in/auth/crts): identity-based access using a peer certificate signed by a trusted CA. Used for the same purposes as OSCORE but authenticated via TLS instead of a pre-shared key.
Each access token entry carries a scope that limits which Group Addresses (GAs) or device interfaces the credentials cover.
The at field in /fp/r and /fp/p references an access token by its id.
Both at and access token id are text strings (for example at='1a' in /fp/r
pairs with the access token whose id is '1a').
Access Token CBOR Keys
| CBOR Key | Name | Type | M/O | Description |
|---|---|---|---|---|
| 0 | id |
text string | [m] | Access token ID (ASCII, numbers and lowercase letters, max 32 bytes). Unique on a device, should be unique in an installation. |
| 4 | exp |
unsigned | [o] | Expiration time (epoch-based NumericDate, RFC 8392). If missing, the token does not expire. |
| 5 | nbf |
unsigned | [o] | Not-before time (epoch-based NumericDate, RFC 8392). If missing, the token is valid immediately. |
| 8 | cnf |
map | [m] | Confirmation claim containing either osc (key 4) or kid (key 3). See cnf tables below. |
| 9 | scope |
string array or unsigned array | [m] | Interface-name strings (e.g, tool keys) or GA integers (group tokens) |
| 38 | profile |
unsigned | [m] | 2 = coap_oscore, 254 = coap_tls, 255 = coap_pase. |
OSCORE cnf CBOR Keys (cnf → osc = 4)
The cnf map contains a single osc entry with key 4. Its value is a map with the following fields:
| CBOR Key | Name | Type | M/O | Description |
|---|---|---|---|---|
| 0 | id (osc-id) |
byte string | [m] | OSCORE input material ID, 1–7 bytes. Request sender/recipient ID, placed in the kid header field. |
| 1 | version |
unsigned | [o] | OSCORE version. Default: 1. Counting starts at 1. |
| 2 | ms (master secret) |
byte string | [m] | OSCORE master secret (16-32 bytes). Shared by all peers as HKDF input; default algorithms require at least 16 bytes of entropy. |
| 4 | alg |
unsigned | [o] | AEAD algorithm. Default: AES-CCM-16-64-128 (10). |
| 5 | hkdf |
negative / unsigned | [o] | HKDF algorithm. Default: HKDF-SHA-256 (-10). |
| 6 | contextId |
byte string | [m]* | OSCORE ID Context, a sender-specific salt. *Mandatory for every device that sends with this token. |
| 35 | salt |
byte string | [o] | OSCORE master salt. Default: empty. |
The osc-id names one direction only. The client uses it as its request sender ID, the server as its request recipient ID. For responses the roles reverse and the server's sender ID is always the empty byte string (h''), which is why osc-id must not be empty.
The contextId is unique per sending device, so several devices can share one master secret and salt and still derive distinct sender keys. It applies to the device's own request sender context only. For incoming requests the device derives the recipient context from the kid_context of the received message, which carries the peer's contextId. Group access tokens are typically used in both directions, so a device both sends with its own contextId and maintains recipient contexts for its peers. Reconfiguring a device with the same keying material but a new contextId produces different AEAD keys, which lets the device restart its sequence number at 0. Peers treat it as a new sender: they build a fresh recipient context and re-establish the replay window with an Echo challenge.
X.509 Access Token
For X.509 access tokens the device authenticates the peer via (D)TLS
instead of OSCORE. X.509 access tokens share the id, cnf, and scope
fields with OSCORE tokens. The structure differs in two ways: the cnf
map carries a certificate reference instead of key material, and the
access token adds a sub claim and a different profile value.
The table below lists only the changed and added fields.
| CBOR Key | Name | Type | M/O | Description |
|---|---|---|---|---|
| 2 | sub |
text string | [m] | Client certificate SAN (URI knx://…) the device authorises. |
| 38 | profile |
unsigned | [m] | ACE profile. 254 = coap_tls. |
X.509 cnf CBOR Keys (cnf → kid = 3)
The cnf map has a kid value (RFC 8747, CWT Confirmation
Method key 3) set to the certificate thumbprint of a CA entry in
/auth/crts. The kid matches the thumbprint to find the trust
anchor for certificate-chain validation and SAN matching.
| CBOR Key | Name | Type | M/O | Description |
|---|---|---|---|---|
| 3 | kid |
byte string | [m] | References a X.509 certificate in /auth/crts (trust anchor). |
Scope Values
| Scope type | Value example | Use |
|---|---|---|
| Group access token | [2304, 2305, 2306, 2307] |
Covers all listed GAs (multicast or unicast group). |
| Single-GA access token | [2305] |
Covers one GA only (cross-device unicast). |
| Tool-key access token | ["if.c","if.p","if.d","if.sec","if.swu","if.g.s"] |
Full device access (onboarding tool key). |
| Config-admin access token | ["if.sec"] |
Security scope only (PASE rkey, or restricted MaC). |
Multicast Group Access Token Example
Shared credentials for all devices in a multicast group. Both the sender
(publisher, fp/p) and all receivers (fp/r) hold the same access token.
Each publisher adds its own unique contextId so that every sender derives a different AEAD key. Two senders sharing a contextId would derive the same key and lose confidentiality protection.
# POST to /auth/at — group access token covering GAs 2304-2307 (sender side, with contextId)
[{0: h'3', # id: access token identifier
8: {4: {0: h'0c00fa10020700', # sender_id (7 bytes)
2: h'ff112233445566778899aabbccddeeff', # master_secret (16 bytes)
6: h'55cf25777e'}}, # contextId (publisher-unique)
9: [2304, 2305, 2306, 2307], # scope (Group Addresses)
38: 2} # profile = OSCORE
]
For matching /fp/r and /fp/p multicast entries, see
Function Point Tables
(no at field—the kid in the OSCORE header identifies the token).
Unicast Access Token Example
Pairwise credentials for direct unicast or endpoint subscription.
Each recipient pair has a unique master secret. The at field in /fp/r or /fp/p
references this access token by its id. This unicast token covers one exchanged Group Address only.
# POST to /auth/at — unicast access token for status to light switch (GA 2305)
[{0: h'1a', # id: access token identifier
8: {4: {0: h'0101', # sender_id (2 bytes)
2: h'fc0cde2339cdeaee109129ef0852de91', # master_secret (16 bytes)
6: h'20000633ce07'}}, # contextId (publisher-unique)
9: [2305], # scope (single GA)
38: 2} # profile = OSCORE
]
For the fp/r entry that references this token via at='1a', see
Unicast Example.
For a subscription fp/p entry, see
Endpoint Subscription Example.
Tool Key Access Token Example
The MaC installs this token during IA configuration (PASE flow). It grants
full device access to the MaC. A MaC can use the sender ID bytes as the
access token id. Only the PASE-generated token requires this convention.
# POST to /auth/at — tool key with full interface scope
[{0: '0c00fa10h0207', # id: sender_id text string
8: {4: {0: h'0c00fa100207', # sender_id (6 bytes)
2: h'a1b2c3d4e5f60718293a4b5c6d7e8f90'}}, # master_secret (16 bytes)
9: ["if.c", "if.p", "if.d", "if.sec", "if.swu", "if.g.s"], # full scope
38: 2} # profile = OSCORE
]
Certificate Trust List (/auth/crts)
Each entry is an X.509 v3 DER-encoded certificate. The MaC writes entries
here before (or together with) any X.509 access tokens that reference them
via kid. A device shall support at least three CA certificates (for example,
MaC, Registrar, and KDC). For the (D)TLS onboarding flow and LDevID
enrollment, see
Device Bootstrapping with TLS.
Certificate Entry CBOR Keys
Each item in /auth/crts/<cert-id> represents an X.509 certificate:
| CBOR Key | Name | Type | M/O | Description |
|---|---|---|---|---|
| 0 | id |
text string | [m] | X.509 certificate thumbprint. Used as the kid value in the corresponding /auth/at access token entry. |
Trust Anchor Selection
When a peer presents its certificate during the TLS handshake the device:
- Looks up the access token in
/auth/atwhosecnf.kidmatches a value in/auth/crts. - Uses the certificate stored at that
/auth/crtsentry as the trust anchor to validate the peer's certificate chain, or the peer certificate itself when the entry contains the peer's self-signed certificate. - Checks that the peer certificate Subject Alternative Name matches the
subclaim of the access token. - Grants access only if all three checks pass and the access token scope covers the requested resource.
X.509 Access Token Example
The corresponding X.509 access token in /auth/at:
# POST to /auth/at — X.509 tool key (coap_tls profile)
[{0: h'tool-ca', # id: access token identifier
2: "knx://security-zone-1/tool", # sub: authorised certificate SAN
8: {3: h'b52e8fa1c3d4e607192a3b4c5d6e7f8091a2b3c4d5e6f708192a3b4c5d6e7f80'}, # cnf.kid: CA thumbprint → /auth/crts
9: ["if.c", "if.p", "if.d",
"if.sec", "if.swu", "if.g.s"], # scope: full device access
38: 254} # profile = coap_tls
]