I implemented this specification from scratch for years. I loved it and after leaving the job, I felt sorrow for my knowledge and effort, so I wanted to write something down as a work history and would be happy if someone found it helpful.
Link to the specification: https://fidoalliance.org/specs/FDO/FIDO-Device-Onboard-PS-v1.1-20220419/FIDO-Device-Onboard-PS-v1.1-20220419.html
Rethink how I approached this specification, it was big and overwhelming at first glance, I didn’t have prior experience with something like that before. So, to make things easier at first and please, forgive my bad english, I’ll try my best to keep this blog post an “overview” as concise and informative as possible, by answering the following questions:
- What is it?
- What is in it?
- How does it work?
- Resources.
From a developer’s perspective, I would avoid the business of this protocol.
- What is it?
FDO is a secure automatic onboarding protocol for IoT devices. It defines how to tie the device’s ownership with a list of information called Device Credential (sec. 2.1) into a digital document called Ownership Voucher (sec.2.1) and use these data with FDO components (sec.2.2) for onboarding the devices securely with e2e encryption by FDO protocols (sec.3) at any time later with any different FDO IoT platforms, they called it “late binding”.
2. What is in it?
2.1. Device Credential and Ownership Voucher
Device Credential: a list of values which must be persisted in the Device, its structure is not normative, but requires the presence of the following values:
DeviceCredential = [
DCActive: bool,
DCProtVer: protver,
DCHmacSecret: bstr, ;; confidentiality required
DCDeviceInfo: tstr,
DCGuid: Guid, ;; modified in TO2
DCRVInfo: RendezvousInfo, ;; modified in TO2
DCPubKeyHash: Hash ;; modified in TO2
]
The explanations of those values and more details are in the Device Credential section of the specification.
Example:
[
true, // DCActive
101, // DCProtVer
h'9C73028748C1D46FCC2CD00A16717B12B3AFAC1FA172B6DEC46BFFCE7FF8CA5B569E5D4DC4B498421FFF67019B1155ADAC9AB1DC0B7D3B77BE6106CB7056208C', //DCHmacSecret
"SampleDevice", // DCDeviceInfo
h'9B581992B215E44460F82AB81DF3CA33', // DCGuid
[ // DCRVInfo
[[2, h'4401020304'], [4, h'191F68'], [3, h'191F68'], [12, h'01']],
[[2, h'4401020304'], [4, h'1920F8'], [3, h'1920F8'], [12, h'02']]
],
[ // DCPublicKeyHash
-43,
h'B443240B9618CADC2807F300F25B111503D311CB37242F94F5D35D6A17E391096EA9D53490FFBD78901B2FE5C7D79729'
]
]
Ownership Voucher: a normative structure digital document. Its detailed format is defined in the Ownership Voucher section.
I’ll briefly explain its top-level structure:
OwnershipVoucher = [
OVProtVer: protver, ;; protocol version
OVHeaderTag: bstr .cbor OVHeader,
OVHeaderHMac: HMac, ;; hmac[DCHmacSecret, OVHeader]
OVDevCertChain: OVDevCertChainOrNull,
OVEntryArray: OVEntries
]
- OVProtVer: FDO protocol version, the value equals DCProtVer in the corresponding Device.
- OVHeaderTag: a normative structure, which contains all the information used to identify the device.
- OVHeaderHMac: this value is computed by device with device’s hmac secret, so only the device with that secret can verify this value.
- OVDevCertChain: a chain of certificates, in which, the leaf cert is the device’s public key certificate signed by the manufacturer to ensure the device’s private key can’t be tampered with and to verify the device’s signature.
- OVEntryArray: an array of structure values called OVEntry, each entry indicates the permission to onboard the device of an owner who own the private key corresponding to public key, which is signed in that entry. A public key in an OVEntry is signed by the private key of the public key, which is signed in the previous OVEntry, which means, only an authorized owner can extend the ownership for another. Again, more details are in the specification.
Example:
[
101,
h’8618655095F829927472E2DA378FE44121684CAC82848202454401020304820443191F68820343191F68820C41018482024544010203048204431920F88203431920F8820C41026C53616D706C65446576696365830B0158783076301006072A8648CE3D020106052B81040022036200044F1C26EA9196192B455A369D198BAE6D7B608975B6A68AA404D10282939C8B9C6A475E151AF690F6082CDE96D213B17FA2406F865A0DD000076CAC0F80ACB980642AE5702F488D2C8B9B7A5F1B38FBB2006BA0D324BAB1AD80623C366A5A5A5082382A583044608FBB5776C7F4A42A3BFAEF7E1BFDAA286FCE219EAA4349B5691289AED66E371E2B2E1A5C95939606BB324763C2FE’,
[
6,
h’622B956A8CA74CFA10358D60F34EB7D45FB2DA71121BE8101745DE45BD163AAA6719BE9FEA848790BCBCAD67CB1D0C99'
],
[
h’3082021B308201A0A003020102028180C7308ABD2B8E3C8120518F9DC2946BD964115DB51A5F535CC94B160D28AE83A975B0AF3EC6A355EB368F83A8C64930A48D330E39ECF372AA2E836AE075C01F794231A8CC3A2EBCEE09AB69A7C505FC62B7D4C807B746B2D56FFD78C6C1A139F61B5954A9F567566CC047E36ED4175C116DF4D253148DCCF863B973A57ED9BFAD300A06082A8648CE3D0403033014311230100603550403130946646F456E74697479301E170D3234303432383138313031355A170D3237303132323138313031355A3058310B300906035504061302564E310E300C0603550408130548616E6F69310E300C0603550407130548616E6F6931173015060355040A130E4E6F4F7267616E697A6174696F6E3110300E060355040313076474707468616F3076301006072A8648CE3D020106052B8104002203620004CA1346839956CB123509B2698AAB22449AD5C17D9E79F6EAFFB0513F5CD5C34AD72A64F878FAF028A12BCDBD257093627ACF14123BE3007C3DDA0C1C4B3100389B7CA12F9C09B4AAFF73718C6E9C28278FA31DD16288BAA63E3883F07A13C587A3023000300A06082A8648CE3D0403030369003066023100850DED6347D24A1F10B577DEBC123F8C0E78987CAA1806C8D80CBE5F6DFF5DD85CB4850718522EF043DF47AED202F089023100B06A45610952EBEEDB32BA7B01BD1DC98F4DA329CAC843C70D645CC911B5C7265C8B3DCEDF0408B9472AF52F3F2B6ACE’,
h’308201F930820180A0030201020281804BB12E693E6D8A4399C80B1F4815A751D1FFC30507F2B9E13856A67379ECCF17F4AE14BD8D2488C4D65EAB3A27D54F44C3BB0A2891A8AE6AFB5AC193F4D024CD5B55B1D77C12C5D243459F9560DB88AF887922DFC23B6BA671C8FD450B5BBD57C485C518D7492096FF78B7F2D4F2F7983E58E509224BAB5E479C95A71115B1A5300A06082A8648CE3D0403033014311230100603550403130946646F456E74697479301E170D3234303432383138313031355A170D3237303132323138313031355A3014311230100603550403130946646F456E746974793076301006072A8648CE3D020106052B81040022036200044F1C26EA9196192B455A369D198BAE6D7B608975B6A68AA404D10282939C8B9C6A475E151AF690F6082CDE96D213B17FA2406F865A0DD000076CAC0F80ACB980642AE5702F488D2C8B9B7A5F1B38FBB2006BA0D324BAB1AD80623C366A5A5A50A326302430120603551D130101FF040830060101FF020102300E0603551D0F0101FF040403020284300A06082A8648CE3D040303036700306402301FA48E84941BDC6F718DEA946C81166AC96605F0CC4A9D08B2655DDE9D391E8F1313E10477DBFCFF1F646917E4FA160D0230101DFEDD30CE244B36B2F28086C59CB0E3373CD60578FF981409EAA1825B8DCBDFD54346C176376493C415216ACAF8E5'
],
[
18([
h’A1013822',
{},
h’8482382A58305C38979CED10DDE4C8E5438749C569F5955EC800C68F84DDBC77C7AF29589B771137EB397CAE7F46B1E38BADA05D7BF782382A5830B171B7C9705F4ADA93C7586D7BEACAE369EC0DF6ACE4411F0FB094B01504164C61D37F346B8756C08458D105D7EA97F7F6830B0158783076301006072A8648CE3D020106052B81040022036200043F4ADA39DEC58B23963AEAB1EFB2CB69E18BD0A1341C9F01F789A5C1F55E7D6D91C94810F358360BCE08CE965740811C7E4054E301CF5BED5CC1EF1A78BA981348E942BF552D6352A3235E7BD68FF899E579FF557A3E3457E2F8F2B7AD1840F2',
h’2CA63E0BC2B15CA960D9A3EA5C61750FF58BD6858EDD414C07F7021876A2EBE3F5865B635D7F9B4807DEA16BAC1459F781D0ABEBFE5BD3E67F7742CD810B5245D32C277FFE0B858B5859F6555EFF6E08791B021CEC42343417A7DC6DCCFD1EE3'
]),
18([
h’A1013822',
{},
h’8482382A5830AE74E1FDB3535F09666288C0C4174B679FFD6189195431C752D8CC1D6D55F5C2BA18964B5CF0269D1B6F91F3AC0A246A82382A5830B171B7C9705F4ADA93C7586D7BEACAE369EC0DF6ACE4411F0FB094B01504164C61D37F346B8756C08458D105D7EA97F7F6830B0158783076301006072A8648CE3D020106052B8104002203620004669C3DB7886A582EB7E0CBA44D155A884B120014DE0A87B1B7CADFC62B6B4D10EEADA2ADC7425546AFC868300F1FC24D1DDE0741BA1E23F13126D452DAE701D2EE090B51D6D608E82B46A16BDD5D893EA4947981EFC447092AF42C013FDA3E24',
h’135EB108B2CC89ED78C15559A3FF78982FDB782A90CE3C5041E2D54D5DCDB61E629E5317B31DC9778097565D352ACC406FDF314A94C8746757F259799C7C9FF4ED5E226257F7401B26706D60CC767713EBD28CA99AED8929B5E053CEA6BE9F09'
])
]
]
2.2. FDO Core Components
This section answers for what to develop. FDO has 4 main components:
Manufacturing (DI server): since DI protocol is non-normative and performed at the manufacture state, this component implements the server-side and possibly also the client-side (DI-client) of the DI protocol.
Device (DI, TO1 & TO2 client): a physical device, this component implements the client-side of DI, TO1 and TO2 protocols. If the DI-client is already implemented in the manufacturing component or separately, then Device Credentials must be imported into the device before running TO1 and TO2.
Rendezvous (RV) server (TO0 & TO1 server): this component implements server-side of TO0 and TO1 protocol. It acts as a rendezvous point between a newly powered-on device and the Owner Onboarding Service.
Owner or Owner Onboarding Service (TO0 client & TO2 server): this component implements the client-side of TO0 protocol and the server-side of TO2 protocol.
Note: all above FDO components use common encoding formats and primitives. These encoding formats and primitives can be implemented separately as a library and would be the most powerful component.
3. How does it work?

FDO works by 4 main protocols, each protocol defines a communication process between an FDO server and an FDO client component over HTTP-like protocol (I only mention HTTP-like protocol in this blog post):
- Device Initialize Protocol (DI): the 1st step in FDO flow, this is “a non-normative protocol and may be replaced by any protocol that achieves the same end-state of storing the Device Credentials in the device and creating the Ownership Voucher to complement these credentials”. It is assumed to be performed at device manufacture time using a local network within the factory:

Input:
- Client (Device):
— A key pair for Device Attestation,
— A Hmac secret,
— Server’s address
- Server (manufacturing component):
— A key pair for Owner Attestation,
— Manufacturer's certificate chain,
— others (not important for an overview).
Output:
- Device Credential: stored in Device ROE (Restricted Operating Environment)
- Ownership Voucher: created in the server, then delivered to the Owner component through a Supply chain
Note: To match a Device Credential (within a device) with an Ownership Voucher outside, there are many cryptographic values to do the security tasks, but the simplest way is using the unique value GUID.
Note: There is also a section called Extension of the Ownership Voucher.
When the Ownership Voucher is initialized, it has no owner entry and must be extended for at least one owner before processing the next steps.
The key pair used to extend device ownership for the last owner is then used as input in the TO0 protocol.
- Transfer Ownership Protocol 0 (TO0): the 2nd step in FDO flow, in this protocol, Ownership Voucher and Owner Onboarding Service’s address are sent from Owner Onboarding Service to the Rendezvous Server:

Input:
- Client (Owner Onboarding Service):
— Current owner’s private key
— Ownership Voucher
- Server (Rendezvous Server).
Output:
- Server (Rendezvous Server): stored Ownership Voucher and Owner Onboarding Service’s IP address with a signature signed by the current owner).
- Transfer Ownership Protocol 1 (TO1): the 3rd step in FDO flow, the Device connects to the Rendezvous Server to obtain the Owner server’s address:

Input:
- Client (Device with initialized Device Credential)
- Server (Rendezvous Server)
Output:
- Client (Device): obtained Owner Onboarding Service’s IP address from the RV server
- Transfer Ownership Protocol 2 (TO2): the final step, in this protocol, Device communicates with Owner Server using the address obtained from TO1, establishes a secure tunnel to transmit onboarding data and transfers device ownership. When this state is completed, the device is successfully onboarded:

Input:
- Client (Device with initialized Device Credential):
— Owner Onboarding Service’s IP address obtained in TO1 protocol.
— Configured cryptographic params: ciphersuite and kexsuite.
- Server (Owner Onboarding Service):
— Current owner’s private key
— Ownership Voucher
— Onboarding Data (Service Info)
— New owner’s key pair (in case of reuse protocol, which means disabling the “transfer ownership” feature and mostly used for testing purposes, use the current owner’s private key).
Output:
- Client (Device): Onboarded.
- Server (Owner Onboarding Service): if reuse protocol is not used, then the Ownership Voucher is reformed with the new owner’s private key, device’s ownership is transferred to the new owner, otherwise, the ownership voucher remains unchanged.
4. Resources
I can't share my code because it's not public, but these open sources helped me a lot:
- Full components implementation in Java by Intel: https://github.com/fido-device-onboard/pri-fidoiot
- Device implementation in C by Intel: https://github.com/fido-device-onboard/client-sdk-fidoiot
- Full components implementation and test cases in Go by FIDO Alliance: https://github.com/fido-alliance/iot-fdo-conformance-tools
Thank you for reading. If you are new to FDO, I hope you’ve got a good approach to it, leave a comment if you have any questions. If you found any helpful information, please support this post with a clap to encourage my further publications :).