<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>FIDO2 on ph03n1x's blog</title><link>https://darkphoenix42.github.io/tags/fido2/</link><description>Recent content in FIDO2 on ph03n1x's blog</description><generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Tue, 08 Jul 2025 15:10:40 +0530</lastBuildDate><atom:link href="https://darkphoenix42.github.io/tags/fido2/index.xml" rel="self" type="application/rss+xml"/><item><title>GSoC 2025</title><link>https://darkphoenix42.github.io/posts/gsoc-2025/</link><pubDate>Tue, 08 Jul 2025 15:10:40 +0530</pubDate><guid>https://darkphoenix42.github.io/posts/gsoc-2025/</guid><description>&lt;h2 id="introduction">Introduction&lt;/h2>
&lt;p>This summer, I had the incredible opportunity of contributing to &lt;a href="https://libssh.org">libssh&lt;/a>, an open-source C library for the SSHv2 protocol, as part of &lt;strong>Google Summer of Code 2025&lt;/strong>. My project focuses on &lt;a href="https://summerofcode.withgoogle.com/programs/2025/projects/ziHCZkB4">adding client-side support for FIDO2/U2F keys&lt;/a>, under the mentorship of Eshan Kelkar, Jakub Jelen, and Sahana Prasad.&lt;/p>
&lt;p>In this blog post, I&amp;rsquo;ll try to explain my project in detail, and what I&amp;rsquo;ve worked on until now. But first, we need to discuss some background information required to better understand the project.&lt;/p></description><content>&lt;h2 id="introduction">Introduction&lt;/h2>
&lt;p>This summer, I had the incredible opportunity of contributing to &lt;a href="https://libssh.org">libssh&lt;/a>, an open-source C library for the SSHv2 protocol, as part of &lt;strong>Google Summer of Code 2025&lt;/strong>. My project focuses on &lt;a href="https://summerofcode.withgoogle.com/programs/2025/projects/ziHCZkB4">adding client-side support for FIDO2/U2F keys&lt;/a>, under the mentorship of Eshan Kelkar, Jakub Jelen, and Sahana Prasad.&lt;/p>
&lt;p>In this blog post, I&amp;rsquo;ll try to explain my project in detail, and what I&amp;rsquo;ve worked on until now. But first, we need to discuss some background information required to better understand the project.&lt;/p>
&lt;h2 id="background">Background&lt;/h2>
&lt;h3 id="how-traditional-ssh-keys-work">How Traditional SSH Keys Work&lt;/h3>
&lt;p>To understand why FIDO2/U2F keys are special, we need to first understand how SSH public key authentication works.&lt;/p>
&lt;p>The following is the authentication flow with a regular public key:&lt;/p>
&lt;ol>
&lt;li>You generate a key pair on your computer (like &lt;code>ssh-keygen -t ecdsa&lt;/code>)&lt;/li>
&lt;li>The private key stays on your computer (usually in &lt;code>~/.ssh/id_ecdsa&lt;/code>)&lt;/li>
&lt;li>You copy the public key to servers you want to access (stored in &lt;code>~/.ssh/authorized_keys&lt;/code>)&lt;/li>
&lt;li>When you connect to the server, it requires the client to send a valid signature&lt;/li>
&lt;li>Your computer uses the private key file (i.e., &lt;code>~/.ssh/id_ecdsa&lt;/code>) to generate a valid signature and sends it to the server&lt;/li>
&lt;li>The server verifies the signature using the stored public key&lt;/li>
&lt;/ol>
&lt;p>The problem with this is that the &lt;strong>private key is just a file&lt;/strong> on your computer. If someone gains access to your computer or steals this file, they can impersonate you on any server that trusts your public key. Even if the private key is password-protected, a determined attacker with enough time and resources might crack it.&lt;/p>
&lt;h3 id="enter-fido2u2f-keys-hardware-backed-security">Enter FIDO2/U2F Keys: Hardware-Backed Security&lt;/h3>
&lt;p>FIDO2 (Fast Identity Online) and U2F (Universal 2nd Factor) security keys/authenticators are small devices, like USBs, that revolutionize this security model. Instead of storing your private key as a file on your computer, the FIDO2/U2F either uses a master key to deterministically derive private keys or stores the private key on the device itself (See &lt;a href="https://darkphoenix42.github.io/posts/gsoc-2025/#resident-keys">Resident Keys&lt;/a>).&lt;/p>
&lt;p>The following are a few reasons why security keys are fundamentally more secure:&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>Hardware Protection&lt;/strong>: All private data is stored inside a tamper-resistant hardware security module within the chip. The private key derivation process also happens entirely within the security chip, making it impossible for malware or hackers to obtain any key material remotely.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Physical Presence Required&lt;/strong>: Most security keys require you to physically touch or interact with the device to authorize each authentication (see &lt;a href="https://darkphoenix42.github.io/posts/gsoc-2025/#user-presence-and-user-verification">this&lt;/a> section). This means even if someone compromises your computer, they can&amp;rsquo;t authenticate without physically accessing your security key.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>No Shared Secrets&lt;/strong>: Security keys use a challenge-response protocol where no secret information like a password is ever transmitted over the network. Each authentication is unique and cannot be replayed by an attacker.&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>So, security keys are much safer than passwords, or even traditional SSH keys, as they require an attacker to have both remote access to your computer and physical access to your FIDO2/U2F device - a significantly higher bar for compromise.&lt;/p>
&lt;p>I highly recommend you check out &lt;a href="https://webauthn.me">this&lt;/a> cool demonstration of the authentication flow using a security key.&lt;/p>
&lt;p>Now that the basics of security keys have been covered, let&amp;rsquo;s discuss some of the their key concepts that are relevant to my project.&lt;/p>
&lt;h3 id="resident-keys">Resident Keys&lt;/h3>
&lt;p>FIDO2 devices can store credentials in two fundamentally different ways: &lt;strong>non-resident keys&lt;/strong> and &lt;strong>resident keys&lt;/strong> (also called discoverable credentials). In the context of SSH authentication:&lt;/p>
&lt;p>&lt;strong>Non-Resident Keys&lt;/strong>: With regular FIDO2 credentials, a credential ID (also known as a key handle) and associated metadata are stored in a file on the client side. When authentication is needed, the client provides the credential ID to the FIDO2 device, which then derives the corresponding private key from its master key to authenticate.&lt;/p>
&lt;p>&lt;strong>Resident Keys (Discoverable Credentials)&lt;/strong>: With resident keys, the private key and associated metadata are stored directly in persistent memory on the FIDO2 device itself and nothing is stored on the client side. During authentication, the device can present all available credentials without needing to know any credential ID.&lt;/p>
&lt;p>Advantages of resident keys include portability (using the same FIDO2 device across hosts) and resilience (no loss if the local machine is destroyed). Although, they may be limited by the storage of the authenticator.&lt;/p>
&lt;p>You can read more about resident keys &lt;a href="https://developers.yubico.com/WebAuthn/WebAuthn_Developer_Guide/Resident_Keys.html">here&lt;/a>.&lt;/p>
&lt;h3 id="user-presence-and-user-verification">User Presence and User Verification&lt;/h3>
&lt;p>FIDO2/U2F authentication incorporates two important security concepts that provide different levels of assurance and user experience. A relying party (like an SSH server) can require either or both of these features during authentication to ensure additional security:&lt;/p>
&lt;p>&lt;strong>User Presence (UP)&lt;/strong>: Confirms that a human is physically interacting with the security key, typically by touching a button or sensor. This doesn&amp;rsquo;t identify &lt;em>who&lt;/em> the user is, but ensures &lt;em>someone&lt;/em> is physically controlling the device, preventing remote attacks and automated abuse.&lt;/p>
&lt;p>&lt;strong>User Verification (UV)&lt;/strong>: Actually verifies the user&amp;rsquo;s identity through biometric authentication (fingerprint, face recognition) or a PIN entered on the device. This provides stronger security by ensuring that even if someone steals your FIDO2/U2F device, they can&amp;rsquo;t use it without your biometric or PIN. This enables passwordless authentication where the FIDO2 key serves as the sole authentication factor.&lt;/p>
&lt;p>You can read more about UP and UV &lt;a href="https://developers.yubico.com/WebAuthn/WebAuthn_Developer_Guide/User_Presence_vs_User_Verification.html">here&lt;/a>.&lt;/p>
&lt;p>Now that we have a good understanding of what FIDO2/U2F keys are, and their key security features, let&amp;rsquo;s understand how my GSoC project brings this technology to libssh.&lt;/p>
&lt;h2 id="about-the-project">About the Project&lt;/h2>
&lt;p>While libssh already supports server-side authentication using security keys, it currently does not have support for interacting with FIDO2/U2F devices on the client side. This means that users can&amp;rsquo;t use their security keys to authenticate to SSH servers when using libssh-based clients, which forces them to compromise on security.&lt;/p>
&lt;p>My GSoC project is about solving this problem by implementing client-side FIDO2/U2F key support in libssh. This involves:&lt;/p>
&lt;p>&lt;strong>1. Device Communication&lt;/strong>: Building the infrastructure for libssh to interact with FIDO2/U2F devices through various communication protocols&lt;/p>
&lt;p>&lt;strong>2. Key Management Operations&lt;/strong>: Implementing the ability for libssh to:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Generate new keys&lt;/strong>: Create new cryptographic credentials on a FIDO2/U2F device&lt;/li>
&lt;li>&lt;strong>Load resident keys&lt;/strong>: Discover and retrieve keys that are stored on the device itself&lt;/li>
&lt;li>&lt;strong>Import/Export keys&lt;/strong>: Support storing and loading key files containing credential IDs and metadata&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>3. Authentication Operations&lt;/strong>: Using the FIDO2/U2F keys to create cryptographic signatures that prove your identity&lt;/p>
&lt;p>&lt;strong>4. Developer-Friendly API&lt;/strong>: Creating clean, easy-to-use functions that application developers can integrate into their SSH clients without needing to understand the complex underlying FIDO2/U2F specifications.&lt;/p>
&lt;p>Now that we&amp;rsquo;ve outlined what the project aims to achieve, let&amp;rsquo;s understand the technical approach and architecture that makes this possible.&lt;/p>
&lt;h2 id="implementation-details">Implementation details&lt;/h2>
&lt;h3 id="callback-based-architecture">Callback-based Architecture&lt;/h3>
&lt;p>FIDO2/U2F keys support a wide range of communication protocols including USB HID, NFC, and potentially other protocols in the future. To effectively handle this diversity and ensure extensibility, after discussing with my mentors, I decided to adopt the following approach, which is inspired by &lt;a href="https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.u2f">OpenSSH&amp;rsquo;s approach&lt;/a>:&lt;/p>
&lt;p>We mainly need to interact with FIDO2/U2F devices to perform the following core operations:&lt;/p>
&lt;ol>
&lt;li>Enrolling new keys&lt;/li>
&lt;li>Creating signatures using an existing key&lt;/li>
&lt;li>Loading all the resident keys&lt;/li>
&lt;/ol>
&lt;p>So, to allow libssh to support different communication methods without tying the library to any specific protocol implementation, I&amp;rsquo;ve defined a &lt;strong>Security Key API&lt;/strong> (&lt;code>sk_api.h&lt;/code>) that contains the various parameters that these operations can take, and the structs that they must return. We then model these operations as &lt;strong>function callbacks&lt;/strong> - essentially pluggable functions that can be swapped out by the user depending on the communication protocol that is needed.&lt;/p>
&lt;p>I also had to implement defaults for these callbacks (&lt;code>sk_usbhid.c&lt;/code>) which interact with FIDO2/U2F devices over the &lt;strong>USB HID&lt;/strong> protocol, which is by far the most common one, via the libfido2 library. Also, the parameters and return types of the callbacks defined in &lt;code>sk_api.h&lt;/code> are consistent with OpenSSH&amp;rsquo;s, so that any middleware developed for OpenSSH which implements the above core operations can also be used with libssh.&lt;/p>
&lt;p>Once we have these callbacks in place, we also need to integrate security key support into libssh&amp;rsquo;s existing key management infrastructure.&lt;/p>
&lt;h3 id="pki-integration">PKI Integration&lt;/h3>
&lt;p>libssh currently has many functions as part of its internal PKI (Public Key Infrastructure) which support various operations for dealing with traditional RSA, ECDSA, Ed25519, etc., keys. To deal with the new security key types, I extended the the existing PKI functions where possible, or created entirely new functions (&lt;code>pki_sk.c&lt;/code>) for operations which require considerably different handling from traditional keys. The PKI functions internally use the SK API callbacks, as discussed above, to perform the actual communication with the FIDO2/U2F devices.&lt;/p>
&lt;h3 id="client-api-integration">Client API Integration&lt;/h3>
&lt;p>To complete support for FIDO2/U2F keys on the client side, intuitive public-facing APIs must be provided so that users may configure the key operations and perform them. This was something that I really struggled with initially, but after a lot of discussions with my mentors, we were able to finalize a decent API design, that is both easy to use and flexible enough to cover various use cases.&lt;/p>
&lt;h3 id="overall-architecture">Overall Architecture&lt;/h3>
&lt;p>The overall architecture of the project is as follows:&lt;/p>
&lt;pre tabindex="0">&lt;code>┌─────────────────────────────────────┐
│ libssh Client API │ ← User-facing SSH client functions
├─────────────────────────────────────┤
│ PKI SK Integration │ ← pki_sk.c - adds SK capabilities to libssh&amp;#39;s existing PKI
├─────────────────────────────────────┤
│ Security Key API Layer │ ← sk_api.h - abstract callback interface
├─────────────────────────────────────┤
│ Protocol Implementations │ ← sk_usbhid.c - USB HID via libfido2
├─────────────────────────────────────┤
│ Hardware Communication │ ← libfido2, future NFC/BLE libraries
└─────────────────────────────────────┘
&lt;/code>&lt;/pre>&lt;p>This architecture ensures that adding support for new protocols (like NFC or Bluetooth) only requires implementing the SK API callbacks for that specific protocol, without modifying the core libssh codebase.&lt;/p>
&lt;h3 id="comprehensive-testing">Comprehensive Testing&lt;/h3>
&lt;p>To allow for testing the security key functionality in the CI environment, where a physical FIDO2/U2F device is not available, I made use of the openssh-sk-dummy library, to define dummy callbacks that can be used for testing purposes. I then worked on creating unit tests for various components of the implementation, as well as extending existing integration tests to cover the new security key authentication flow.&lt;/p>
&lt;h3 id="documentation">Documentation&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>API Documentation&lt;/strong>: I made sure to properly document most of the new functions using Doxygen comments.&lt;/li>
&lt;li>&lt;strong>FIDO2 key Tutorial&lt;/strong>: I also worked on adding a dedicated documentation chapter similar to libssh&amp;rsquo;s existing authentication guide to help new users adopt FIDO2/U2F support.&lt;/li>
&lt;/ul>
&lt;h2 id="the-code">The Code&lt;/h2>
&lt;p>All of the work done over the course of this project has been done as part of GitLab merge requests. The following is a list of the MRs (ordered chronologically):&lt;/p>
&lt;ol>
&lt;li>&lt;a href="https://gitlab.com/libssh/libssh-mirror/-/merge_requests/617">Add client-side FIDO2/U2F support&lt;/a> &lt;span style="color: orange;">[Open]&lt;/span>&lt;/li>
&lt;li>&lt;a href="https://gitlab.com/libssh/libssh-mirror/-/merge_requests/618">tests: remove unsupported SHA1 HMAC tests for compatibility with latest dropbear version&lt;/a> &lt;span style="color: green;">[Merged]&lt;/span>&lt;/li>
&lt;li>&lt;a href="https://gitlab.com/libssh/libssh-mirror/-/merge_requests/627">fix(string): handle empty string case in ssh_string_copy&lt;/a> &lt;span style="color: green;">[Merged]&lt;/span>&lt;/li>
&lt;li>&lt;a href="https://gitlab.com/libssh/libssh-mirror/-/merge_requests/629">fix(callbacks): rewrite callback validation logic and reformat&lt;/a> &lt;span style="color: green;">[Merged]&lt;/span>&lt;/li>
&lt;li>&lt;a href="https://gitlab.com/libssh/libssh-mirror/-/merge_requests/630">feat(misc): add burn_free function and BURN_FREE macro for secure memory deallocation&lt;/a> &lt;span style="color: green;">[Merged]&lt;/span>&lt;/li>
&lt;li>&lt;a href="https://gitlab.com/libssh/libssh-mirror/-/merge_requests/631">feat(string): add ssh_string_cmp function for comparing ssh_strings&lt;/a> &lt;span style="color: green;">[Merged]&lt;/span>&lt;/li>
&lt;li>&lt;a href="https://gitlab.com/libssh/libssh-mirror/-/merge_requests/641">fix(pki): remove redundant key type_c assignment in pki build and import functions&lt;/a> &lt;span style="color: green;">[Merged]&lt;/span>&lt;/li>
&lt;li>&lt;a href="https://gitlab.com/libssh/libssh-mirror/-/merge_requests/648">feat(pki): improve security key type support&lt;/a> &lt;span style="color: green;">[Merged]&lt;/span>&lt;/li>
&lt;li>&lt;a href="https://gitlab.com/libssh/libssh-mirror/-/merge_requests/659">refactor(pki): Define RSA_MIN_KEY_SIZE and update related checks&lt;/a> &lt;span style="color: green;">[Merged]&lt;/span>&lt;/li>
&lt;/ol>
&lt;h2 id="conclusion">Conclusion&lt;/h2>
&lt;p>I&amp;rsquo;m incredibly grateful to my mentors for their constant guidance in shaping the direction of my project. Their advice has been invaluable. They have been very patient in reviewing my work, catching any mistakes, and providing suggestions to improve it. My journey so far has been an amazing learning experience, and I&amp;rsquo;m looking forward to finishing my project and seeing it become a part of libssh, and I&amp;rsquo;d love to continue contributing to libssh in the future.&lt;/p>
&lt;p>Thanks for reading my blog :)&lt;/p>
&lt;h2 id="references">References&lt;/h2>
&lt;ol>
&lt;li>&lt;a href="https://libssh.org">libssh - Open Source SSHv2 Library&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://summerofcode.withgoogle.com/programs/2025/projects/ziHCZkB4">Google Summer of Code 2025 Project Page&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://webauthn.me">WebAuthn.me - Interactive WebAuthn Demo&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://developers.yubico.com/WebAuthn/WebAuthn_Developer_Guide/Resident_Keys.html">Yubico WebAuthn Developer Guide - Resident Keys&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://developers.yubico.com/WebAuthn/WebAuthn_Developer_Guide/User_Presence_vs_User_Verification.html">Yubico WebAuthn Developer Guide - User Presence vs User Verification&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.u2f">OpenSSH PROTOCOL.u2f Specification&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.w3.org/TR/webauthn-2/">W3C WebAuthn Standard&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://developers.yubico.com/libfido2/">libfido2 Library&lt;/a>&lt;/li>
&lt;/ol></content></item></channel></rss>