Coder Social home page Coder Social logo

yubikit-ios's Introduction

Yubico Mobile iOS SDK (YubiKit)

YubiKit is an iOS library provided by Yubico to interact with YubiKeys on iOS devices.

The library is provided with a demo application which shows complete examples of how the library can be integrated and demonstrates all the features of this library in an iOS project.

Changes to this library are documented in this Changelog.

About

YubiKit requires a physical key to test its features. Before running the included demo application or integrating YubiKit into your own app, you need an NFC-Enabled YubiKey or a YubiKey 5Ci to test functionality.

The host application can build the library as a dependency of the application target when used inside a Xcode workspace. In addition, the library can be packed using the build.sh script, which is provided in the root folder of this project.

Transitioning to version 4 of the SDK

Read the transitioning document if you already have integrated the previous version of the SDK.

Getting Started

To get started, you can try the demo as part of this library or start integrating the library into your own application.

Try the Demo

The library is provided with a demo application, YubiKitDemo. The application is implemented in Swift and it shows several examples of how to use YubiKit, including WebAuthn/FIDO2 over the accessory or NFC YubiKeys.

The YubiKit Demo application shows how the library is linked with a project so it can be used for a side-by-side comparison when adding the library to your own project.

Integrate the library

YubiKit SDK is available as a library and can be added to any new or existing iOS Xcode project through SPM, Cocoapods, or manual setup.

[SPM Setup]

The YubiKit SDK for iOS is availble Swift Package Manger (SPM). SPM is a dependency manager built into recent versions of Xcode. Go here to learn more.

  1. Open Xcode and click "File" -> "Swift Packages" -> "Add Package Dependency..."

  2. Paste the following URL: https://github.com/Yubico/yubikit-ios

  3. Click "Next" -> "Next" -> "Finish"

  4. If your target project is written in Swift, you need to provide a bridge to the YubiKit library by adding #import <YubiKit.h> to your bridging header. If a bridging header does not exist within your project, you can add one by following this documentation.

[Cocoapods Setup]

The YubiKit SDK for iOS is available through CocoaPods. CocoaPods is a centralized dependency manager for Objective-C and Swift. Go here to learn more.

Add YubiKit to your Podfile.

use_frameworks!

pod 'YubiKit', '~> 4.6.0'

If you want to have latest changes, replace the last line with:

pod 'YubiKit', :git => 'https://github.com/Yubico/yubikit-ios.git'

Once YubiKit is added to your Podfile, run pod install and open the *.xcworkspace with Xcode.

Then import the YubiKit module and you can use its classes and methods.

import YubiKit

Continue SDK setup by skipping over Manual Setup to Enable Custom Lightning Protocol.

Manual Setup

Download or Clone YubiKit SDK source

  1. Download the latest YubiKit SDK (.zip) to your desktop or

    git clone https://github.com/Yubico/yubikit-ios.git

Add YubiKit folder to your Xcode project

  1. Drag the entire /YubiKit[version]/YubiKit folder to your Xcode project. Check the option Copy items if needed. Or add exisiting Yubikit project to your workspace

Linked Frameworks and Libraries

  1. Project Settings > General > Linked Frameworks and Libraries. Click + and add the libYubiKit.a

Header Search Paths

  1. Build Settings > Filter by 'Header Search Path'. Set both Debug & Release to ./YubiKit/** (recursive)

-ObjC flag

  1. Add -ObjC flag Build Settings > Filter by 'Other Linker Flags'. Add the -ObjC flag to Debug and Release.

Bridging-Header

  1. If your target project is written in Swift, you need to provide a bridge to the YubiKit library by adding #import <YubiKit/YubiKit.h> to your bridging header. If a bridging header does not exist within your project, you can add one by following this documentation.

Enable Custom Lightning Protocol

REQUIRED if you are supporting the YubiKey 5Ci over the Lightning connector.

The YubiKey 5Ci is an Apple MFi external accessory and communicates over iAP2. You are telling your app that all communication with the 5Ci as a supported external accessory is via com.yubico.ylp.

Open info.plist and add com.yubico.ylp as a new item under Supported external accessory protocols

Enable TKSmartCard support

To support YubiKeys connected via the USB-C port on a device running iOS 16 or higher, you need to add the com.apple.security.smartcard entitlement to your application. Note that this connection only support the Smart card based applications on the YubiKey and does not support U2F, FIDO2 or OTP.

Grant accesss to NFC

To add support for NFC YubiKeys in your application, follow these steps:

  • Add a NEW entitlement for reading NFC specific tags, available since iOS 13. This new entitlement is added automatically by Xcode when enabling the Near Field Communication Tag Reading capability in the target Signing & Capabilities. After enabling the capability the .entitlements file needs to contain the com.apple.developer.nfc.readersession.formats entitlement:
...
<dict>
    <key>com.apple.developer.nfc.readersession.formats</key>
    <array>
        <string>TAG</string>  // Application specific tag, including ISO 7816 Tags
    </array>
</dict>
...
  • The application needs to define the list of application IDs or AIDs it can connect to, in the Info.plist file. The AID is a way of uniquely identifying an application on a ISO 7816 tag, which is usually defined by a standard. FIDO2 and U2F use the AID A0000006472F0001 on most FIDO compliant NFC keys, including the YubiKey. After adding the list of supported AIDs, the Info.plist entry should look like this:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key>
<array>
    <string>A000000527471117</string> // YubiKey Management Application AID
    <string>A0000006472F0001</string> // FIDO/U2F AID
    <string>A0000005272101</string>   // OATH AID
    <string>A000000308</string>       // PIV AID
    <string>A000000527200101</string> // YubiKey application/OTP AID (for HMAC SHA1 challenge-response)
</array>
</plist>
  • The Info.plist also needs to include a privacy description for NFC usage, using the NFCReaderUsageDescription key:
<key>NFCReaderUsageDescription</key>
<string>The application needs access to NFC reading to communicate with your YubiKey.</string>

Grant accesss to CAMERA

Optional: if you are planning to use the camera to read QR codes for OTP Open info.plist and add the following usage: 'Privacy - Camera Usage Description' - "This application needs access to Camera for reading QR codes."

Documentation

YubiKit headers are documented and the documentation is available either by reading the header file or by using the QuickHelp from Xcode (Option + Click symbol). Use this documentation for a more detailed explanation of all the methods, properties, and parameters from the API. If you are interested in implementation details for a specific category like U2F, FIDO2, or OATH, check out the ./docs section.

Using the Library

YubiKit is exposing a simple and easy to use API for executing operations on the YubiKey. The API is divided into Connections and Sessions. The supported connections are YKFAccessoryConnection, YKFSmartCardConnection and YKFNFCConnection. Each session is started by calling YubiKitManager.shared.startAccessoryConnection(), YubikitManager.shared.startSmartCardConnection() or YubiKitManager.shared.startNFCConnection(). Once a YubiKey connects the SDK delivers the new connection via the YKFManagerDelegate protocol. Disconnects are also signaled through the protocol. For an easier and a more Swift-like experience you can implement something similar to this example: YKFManagerDelegate wrapper.

From a connection you can retrieve any of the sessions currently supported in the SDK. The connections are fetched by calling a method with a callback block. Once the session has been established and the corresponding application on the YubiKey has been selected the callback will return the new session. For e.g a FIDO2 session it would look like this:

Swift
connection.fido2Session { session, error in
    guard let session = session else { /* handle error and return */ }
    session.verifyPin(pin) { error in
        ...
    }
}
Objective-C
#import <YubiKit/YubiKit.h>

[self.connection fido2Session:^(YKFFIDO2Session * _Nullable session, NSError * _Nullable error) {
    if (error) { /* handle error and return */ }
    [session verifyPin:pin completion:^(NSError * _Nullable error) {
        ...
    }];
}];

Before initiating the accessory connection, the application should verify that the device running the app supports connecting to the YubiKey over the Lightning port. This can be done by looking at the supportsMFIAccessoryKey property on YubiKitDeviceCapabilities.

The same goes for the NFC connection and similar to the accessory connection the YubiKitDeviceCapabilities has a property supportsISO7816NFCTags that indicates wether the device supports connecting to the YubiKey over NFC.

Swift
if YubiKitDeviceCapabilities.supportsISO7816NFCTags {
    // Provide additional setup when NFC is available            
    // example
    YubiKitManager.shared.startNFCConnection()
} else {
    // Handle the missing NFC support 
}
Objective-C
#import <YubiKit/YubiKit.h>
...
// NFC scanning is available
if (YubiKitDeviceCapabilities.supportsISO7816NFCTags) {
    // Provide additional setup when NFC is available
} else {
    // Handle the missing NFC support
}

List of sessions is documented below with it's own specifics and samples:

  • FIDO - Provides FIDO2 operations accessible via the YKFFIDO2Session.

  • U2F - Provides U2F operations accessible via the YKFU2FSession.

  • OATH - Allows applications, such as an authenticator app to store OATH TOTP and HOTP secrets on a YubiKey and generate one-time passwords.

  • OTP - Provides implementation classes to obtain YubiKey OTP via accessory (5Ci) or NFC.

  • PIV - Provides PIV operations accessible via the YKFPIVSession.

  • Challenge-response - Provides a method to use HMAC-SHA1 challenge-response.

  • Management - Provides ability to enable or disable available application on YubiKey

  • SmartCardInterface - Provides low level access to the Yubikey with which you can send custom APDUs to the key

Customize the Library

YubiKit allows customizing some of its behavior by using YubiKitConfiguration and YubiKitExternalLocalization.

Customizing YubiKit Behavior

For providing localized strings for the user facing messages shown by the library, YubiKit provides a collection of properties in YubiKitExternalLocalization.

One example of a localized string is the message shown in the NFC scanning UI while the device waits for a YubiKey to be scanned. This message can be localized by setting the value of nfcScanAlertMessage:

Swift
let localizedAlertMessage = NSLocalizedString("NFC_SCAN_MESSAGE", comment: "Scan your YubiKey.")
YubiKitExternalLocalization.nfcScanAlertMessage = localizedAlertMessage
Objective-C
#import <YubiKit/YubiKit.h>
...
NSString *localizedAlertMessage = NSLocalizedString(@"NFC_SCAN_MESSAGE", @"Scan your YubiKey.");
YubiKitExternalLocalization.nfcScanAlertMessage = localizedNfcScanAlertMessage;

For all the available properties and their use look at the code documentation for YubiKitExternalLocalization.


Note: YubiKitExternalLocalization provides default values in English (en-US), which are useful only for debugging and prototyping. For production code always provide localized values.


YubiKit FAQ

Q1. Does YubiKit store any data on the device?

Yubikit doesn't store any data locally on the device. This includes NSUserDefaults, application sandbox folders and Keychain. All the data required to perform an operation is stored in memory for the duration of the operation and then discarded.

Q2. Does YubiKit communicate with any services?

Yubikit doesn't communicate with any services, like web services or other type of network communication. YubiKit is a library for sending, receiving and processing the data from a YubiKey.

Q3. Can I use YubiKit with other devices which are not from Yubico?

YubiKit is a library which should be used only to interact with a device manufactured by Yubico. While some parts of it may work with other devices, the library was developed and tested to work with YubiKeys. When attaching a MFI accessory, YubiKit will always check if the manufacturer of the device is Yubico before connecting to it.

Q4. Is YubiKit compiled with support for Bitcode and Position Independent code?

Yes, YubiKit is compiled to accommodate any modern iOS project. The supplied library is compiled with Position Independent code and Bitcode. The release version of the library is optimized (Fastest, smallest).

Q5. Is YubiKit logging or asserting in release mode?

No, YubiKit is not logging in release mode. The logs from YubiKit will show only in debug builds to help the developer to see what YubiKit does. The same stands for assertions. YubiKit will assert in debug mode to warn the developer when invalid parameters are passed to the library or when something unexpected happened with the key. In release, the library will handle invalid states in different ways (e.g. returning nil if the object was not properly initialized, returning errors, etc.).

Q6. Are there any versions of iOS where YubiKit does not work?

YubiKit should work on any modern version of iOS (10+) with a few exceptions*. It's recommended to always ask the users to upgrade to the latest version of iOS to protect them from known, old iOS issues. Supporting the last 2 version of iOS (n and n-1) is usually a good practice to keep the old versions of iOS out. According to Apple statistics, ~90-95% of all iOS devices run the latest 2 versions of iOS because upgrading the OS is free and Apple usually provides a device with upgrades for 5 years.

* Some versions of iOS had bugs affecting all external accessories. iOS 11.2 was one of them where the applications could not communicate with accessories due to some bugs in the XPC communication. The bug was fixed by Apple in iOS 11.2.6. For these reasons it's recommended to take in consideration rare but possible iOS bugs when designing the application.

Q7. How can I debug the application while using a MFi accessory YubiKey?

Starting from Xcode 9, the IDE provides the ability to debug the application wirelessly. In this way the physical connector is not used for connecting the device to the computer, for debugging the application. This WWDC session explains the wireless debugging functionality in Xcode.

Q8. Are the USB-C type iOS devices supported by the YubiKey 5Ci?

The USB-C type iOS devices, such as the iPad Pro 3rd generation, have limited support when using the YubiKey 5Ci or another type of YubiKey with USB-C connector. The OS is not officially supporting external accessories on these devices. However these devices support external USB keyboards, so the OTP functionality of the key will work and the key can be used to generate Yubico OTPs and HOTPs.

Additional resources

  1. Xcode Help - Add a capability to a target
  2. Xcode Help - Build settings reference
  3. Technical Q&A QA1490 - Building Objective-C static libraries with categories
  4. Apple Developer - Swift and Objective-C in the Same Project
  5. Yubico - Developers website
  6. Yubico - Online Demo for OTP and U2F
  7. Yubico - OTP documentation
  8. Yubico - What is U2F?
  9. Yubico - YKOATH Protocol Specifications
  10. FIDO Alliance - CTAP2 specifications
  11. W3.org - Web Authentication: An API for accessing Public Key Credentials

yubikit-ios's People

Contributors

conradcio avatar fyrbyadditive avatar imakhalova avatar irinarakh avatar jensutbult avatar joeblau avatar mattmaddux avatar motorwolf avatar redetection avatar rudyrichter avatar samngms avatar torokzsolt avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

yubikit-ios's Issues

[Question] Using NFC only option without MFi review

Hello,
Sorry if I missed it somewhere, but I couldn't really get a clear understanding whether is it possible to use this SDK for WebAuthn assertion with NFC only and not doing all that MFi-related review process.
And as a follow-up question: would YubiKey 5Ci work in NFC mode in this case?

Thank you

Cocoapods (and Carthage?) support

I'm currently trying to build my own private Cocoapods wrapper for Yubikit. It would be really nice if Cocoapods were supported by the repo itself. I didn't have any problem integrating the library manually, but I like to keep my dependencies a little cleaner than that, and Cocoapods would go a long way to help with that.

TLS client certificate through PIV over NFC

I'm currently analyzing the possibilities of using Yubikeys for TLS client certificate authentication over NFC on iOS devices as part of a single sign-on process, but from what I have been able to gather only OTP seems to been supported? Are there any plans for supporting PIV over NFC?

Accidental

Accidentally request. Please disregard!

Multi-Facet apps

Hello,

When working with this SDK, we are not seeing a appId or facet check on a multi-facet setup.

In the demos, the appId that is used it "https://demo.yubico.com" - an example of a single facet app.

In this link here: https://developers.yubico.com/U2F/App_ID.html - it is explained about multi-facet apps and the app-id.json file that gets associated with either Android or iOS apps, etc.

We do not see the SDK honoring this multi-facet setup. It does not appear to retrieve the app-id.json file. Maybe I am wrong and doing something incorrectly.

Can you please explain how we should correctly call the SDK with a multi-facet app, with the correct ios:bundle-id: entry in the json file being consumed?

Thanks!

h

h

JSON property name for "signature" vs "signatureData"

We've been implementing Security Key support in our apps and websites. We started with U2F and are also looking at FIDO2, etc.

When using the Yubikit, we've found that it is returning a different payload than Android and browser API's.

Specifically, the "signature" element is named "signature" when using Yubikit, but it is "signatureData" in Android and in Chrome API's.

Examples below for U2F

Android:

{"keyHandle":"bIap1cuTOBhl7VDd4Z56rFPkFJL0ow927f1kWI0SC3_oHjuTFxm7OUcHRrfavcjudIAkyuHiIC_WzKPAYaJPdA","clientData":"eyJ0eXAiOiJuYXZpZ2F0b3IuaWQuZ2V0QXNzZXJ0aW9uIiwiY2hhbGxlbmdlIjoiMWFhNTI2ZmY0NWE1MjYxMTkzMTkyNmI1MTAzY2JhMGFkMDA2ZTU2NjA3NzMwYWQ0NDI0NjgyYTViY2NhMWI5MCIsIm9yaWdpbiI6ImFuZHJvaWQ6YXBrLWtleS1oYXNoOjRqMFpQRFNEMnJSWmlDV0JqR051aFRBNDNCcmZyV0orYitRc2E2aGZkaGsifQ","signatureData":"AQAAABMwRAIgGj4w86tSby8ltv8VfqHpiw1e9zYgi1hL0olPFj-33vkCIFTJuWgBZivOIHoVSd96zZpfyLjoHw-YMR01c5Xiq9zR"}

iOS:

{"clientData":"eyJ0eXAiOiJuYXZpZ2F0b3IuaWQuZ2V0QXNzZXJ0aW9uIiwiY2hhbGxlbmdlIjoiNjMxMjAxMjJkZDdjMzYyNThlZDNmMjJlZDYzODEyYjNiM2EzMGUzZTRkZGEzY2E5MGQ4NzU1OGM2ZDI0NGJjYiIsIm9yaWdpbiI6Imh0dHBzOi8vbG9naW4uYXV0aGFybW9yLmNvbS9hcHAtaWQuanNvbiJ9","keyHandle":"bIap1cuTOBhl7VDd4Z56rFPkFJL0ow927f1kWI0SC3_oHjuTFxm7OUcHRrfavcjudIAkyuHiIC_WzKPAYaJPdA","signature":"AQAAABswRQIgcvZ1HlapFJxqDZY6Qdhjc70mvIL8lZMsUaEp7D/cCF0CIQDmoTFc7939LfCK/j6NuXw9f894mVrV6/+6kqG3gGqj4w=="}

Specifying YKFKeyFIDO2GetAssertionRequestOptionUV results in failure 100% of the time

Steps to Reproduce:

  1. Add a YubiKey to Github account in settings -> security.

  2. Sign out of github.

  3. Go to the login page and enter credentions and hit log in.

  4. Tap "Use Security Key"

  5. a. If we send (login will fail):

assertionRequest.options = [
    YKFKeyFIDO2GetAssertionRequestOptionUP: true,
    YKFKeyFIDO2GetAssertionRequestOptionUV: false
 ]
  1. b. If we send (login will fail):
assertionRequest.options = [
   YKFKeyFIDO2GetAssertionRequestOptionUP: true,
   YKFKeyFIDO2GetAssertionRequestOptionUV: true
]
  1. c. If we send (login will succeed):
assertionRequest.options = [
    YKFKeyFIDO2GetAssertionRequestOptionUP: true
]

Notice that in 5.c. the YKFKeyFIDO2GetAssertionRequestOptionUV option was removed.. However, documentation for this option says the default value is false so 5.a. should have worked..

Documentation below:

/*!
 @discussion
    The options provide a list of properties to influence authenticator operation when signing, as specified
    in in the table below. This parameter is optional.
 
    @code
    Key           | Default value      | Definition
    ----------------------------------------------------------------------------------------
    uv            | false              | user verification: Instructs the authenticator to
                                         require a gesture that verifies the user to complete
                                         the request. Examples of such gestures are fingerprint
                                         scan or a PIN.
    ----------------------------------------------------------------------------------------
    up            | true               | user presence: Instructs the authenticator to require
                                         user consent to complete the operation.
    @endcode
 */
@property (nonatomic, nullable) NSDictionary *options;

Can't sign data using RSA 2048 key in slot 9a using YKFSCardTransmit over Lightning

Hello,

I'm attempting to implement PKCS#11 support on iOS using the PCSC-like interface in YubiKit on iOS, and PCSC.framework on Mac over USB-C. The code is inspired by the PKCS#11 implementation in yubico-piv-tool, and works on Mac.

On iOS, most of the code is working. I'm using YKFSCardConnect, YKFSCardReconnect, YKFSCardDisconnect, YKFSCardStatus, YKFSCardListReaders without issue, and in most cases, YKFSCardTransmit is working properly. However, when I go to sign data using an RSA 2048 key stored in slot 9a, instead of prompting the user to tap the device, the Yubikey 5ci returns 0x6982, authentication fired.

My iOS app contains com.yubico.ylp as a supported external accessory protocol in the app's Info.plist. My code ends up calling YKFSCardTransmit twice, and I've pasted the data sent below (with XX being the data to sign). I confirmed the code sends the same data on macOS to SCardTransmit. On the Mac, on the second call to SCardTransmit, the function blocks until the user taps the device.

10 87 07 9A FF 7C 82 01 06 82 00 81 82 01 00 XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX

00 87 07 9A 0B XX XX XX XX XX XX XX XX XX XX

I understand this is a complicated use-case. Please let me know if I can provide any additional info.

Make Compatible with App Extensions

It would be very useful to include this library in App Extensions (my use case in particular is Password AutoFill extensions).

Currently if you try to build this library in an App Extension context you will get build errors related to the use of NFC (NFC access is not available to App Extensions).

A concrete example looks like this:
image

While there may be no possibility of using a YubiKey over NFC in an App Extension (Password Auto Fill mode), it should in theory be possible to use the new 5Ci over Lightning in this context, so it would be great if this library would compile that functionality while excluding the NFC functionality when built as an App Extension.

Thanks!

Request for Xamarin support

To best integrate with my project, I would need Xamarin.iOS support, or ideally Xamarin Forms support.

Would you kindly put this on the roadmap?

MFI: 5Ci gets stuck in a bad state when used for (HMACSHA1) requiring touch

Hi,

I have an issue with the 5Ci which I'm integrating with at the moment for use in an iOS app of mine (I've already integrated against the NFC side of things and that works well). I'm using the HMACSHA1 Challenge Response feature of these devices to unlock KeePass databases.

The issue only really exhibits itself when the 5Ci has one of it's slots programmed (for HMACSHA1) to require touch.

Here's what can normally happens:

  1. Check accessory state, see it's not OPEN -> call startSession
  2. Display a nice UI popup (using your SharedUI component) telling the user to insert/touch their key (depending on whether key is inserted)
  3. Wait for session to go into OPEN state which it does v quickly
  4. Use YKFKeyChallengeResponseService sendChallenge to request a response from the key
  5. This is blocked until the user touches the key.
  6. User touches key
  7. Receive response and close session with stopSession, dismiss the nice UI popup.

This works well and is repeatable which is great. The problem now comes when I hit the Cancel button on the nice UI Popup while awaiting a user touch...

Problem Reproduction Steps

  1. Check accessory state, see it's not OPEN -> call startSession
  2. Display a nice UI popup (using your SharedUI component) telling the user to insert/touch their key (depending on whether key is inserted)
  3. Wait for session to go into OPEN state which it does v quickly
  4. Use YKFKeyChallengeResponseService sendChallenge to request a response from the key
  5. This is blocked until the user touches the key.
  6. User DOES NOT touch key but taps the Cancel button on the popup.
  7. Close session with stopSession, dismiss the nice UI popup.

From this point out the Key is in a bad state, or my app is or something at least is in a bad state and I can't get the key to go into the OPEN state again without removing the key and reinserting. Here's what happens from this point out:

  1. Check accessory state, see it's not OPEN -> call startSession
  2. Display a nice UI popup (using your SharedUI component) telling the user to insert/touch their key (depending on whether key is inserted)
  3. Wait for session to go into OPEN state which it never does, it remains in an OPENING state.
  4. Call stopSession, cancelCommands etc resets the state to Closed but then we can go back to 1) and never get the state in OPEN.

Note: Touching the key has no effect. A call to startSessionSync instead of startSession will indicate that startSession has failed (returns false eventually).

So 2 questions...

  1. How do I reset the key to a good state when the user taps Cancel, or how to I prevent it from getting into a bad state?
  2. How can I tell if an MFI 5Ci key requires a Touch so I can display a better interface?

Headers missing from target

When building the static library target, it failed to include these required headers:

YKFConnectionProtocol.h
YKFFeature.h
YKFOATHCredentialTemplate.h
YKFOATHCredentialTypes.h
YKFOATHCredentialWithCode.h
YKFPCSCLayer.h
YKFPIVKeyType.h
YKFPIVManagementKeyMetadata.h
YKFPIVManagementKeyType.h
YKFPIVSession.h
YKFPIVSessionFeatures.h
YKFSelectApplicationAPDU.h
YKFSmartCardInterface.h
YKFOATHCredentialUtils.h

YubiKeySessionError - code: 43 "Unsupported option"

Hi, I recently started experimenting with the yubikit-ios sdk and a Yubikey 5Ci with an iPhone XS running iOS 13.4.1.

When I tried to run the following code from the documentation in the repo I get the error mentioned in the title.

Not including YKFKeyFIDO2MakeCredentialRequestOptionUV in makeCredentialOptions fixes the problem but setting it to either true or false causes it to show up.

// Not a resident key and no PIN required.
let makeCredentialOptions = [YKFKeyFIDO2MakeCredentialRequestOptionRK: false, 
								  YKFKeyFIDO2MakeCredentialRequestOptionUV: false]	
let alg = YKFFIDO2PublicKeyAlgorithmES256
	
guard let fido2Service = YubiKitManager.shared.accessorySession.fido2Service else {           
    return
}
            
let makeCredentialRequest = YKFKeyFIDO2MakeCredentialRequest()
    
// Some example data as a hash.	    
let data = Data(repeating: 0, count: 32)
makeCredentialRequest.clientDataHash = data
    
// Set the request rp.
let rp = YKFFIDO2PublicKeyCredentialRpEntity()
rp.rpId = "yubico.com"
rp.rpName = "Yubico"
makeCredentialRequest.rp = rp
  
// Set the request user.  
let user = YKFFIDO2PublicKeyCredentialUserEntity()
user.userId = data
user.userName = "[email protected]"
user.userDisplayName = "John Smith"
makeCredentialRequest.user = user
	
// Set the request pubKeyCredParams.
let param = YKFFIDO2PublicKeyCredentialParam()
param.alg = alg
makeCredentialRequest.pubKeyCredParams = [param]
  
// Set the request options.
makeCredentialRequest.options = makeCredentialOptions
     
fido2Service.execute(makeCredentialRequest) { (response, error) in
    guard error == nil else {
        // Handle the error
        return
    }
    // Handle the response
}

YKNFCSession bubbling up of user cancelled state

In my particular use case i need to know if the session was closed by user error/invalid tag, cancelled by the user hitting the cancel button, or that it was closed normally after having succeeded in processing the read from the tag.

In wiring things up I found that there isn't a separate user cancelled path in the state enumeration or being made use of in:

- (void)tagReaderSession:(NFCTagReaderSession *)session didInvalidateWithError:(NSError *)error API_AVAILABLE(ios(13.0))

As far as I can tell when the user has cancelled the reader session both session and error will be nil in this method so it might be possible to add a cancelled value to the enum.

PGP Support

I didn't see any examples for smart card features here at least. Afaik this is possible on android.

TOTP Support

Am I understanding it correctly that I can currently only read the Yubikey OTPs but not TOTPs with the SDK except with the raw commands? By TOTPs I mean the ones I can use with the Yubikey Authenticator App.

If this is the case I would like to see this feature in the future.

HMAC-SHA1 Challenge-Response mode

YubiKit 2.0.0 supports several modes, but the challenge-response one is not listed (although it is mentioned in the YubiKey 5 Series Technical Manual).

Understandably, there used to be a technical limitation on two-way communication between the key and iOS device. However, now we have Yubikey 5Ci and extended NFC support in iOS 13.

The challenge-response mode is used by offline password managers, in particular KeePass / KeePassXC (details). I would love to add Yubikey support to my iOS port of KeePass, too — this is one of the most requested features.

So, how can we use the challenge-response mode with YubiKit 2.0?

YubiKitDeviceCapabilities returns supportsMFIAcessoryKey on iPad w/ USB-C

On the new iPad Pro devices, apple has swapped out the lightning port for a USB-C connection and (as indicated in the YK docs) only limited support is provided for using the keys. Key reading and decryption appear to work fine, however accessorySession support appears to be non-functional. This is expected as it appears iADP2 is not supported by Apple over USB-C.

When using the iOS library on the iPad w/ USB-C, the call to YubiKitDeviceCapabilities.supportsMFIAccessoryKey returns YES and the call to [YubiKitManager.shared.accessorySession startSession] also works. The problem is that since iADP2 is not supported, the subsequent call to perform KVO on accessorySession fails to notify the app when the session state changes (i.e. connects or disconnects). Again, this is expected as I would imagine the iOS library has no way to know the key is present or not.

What would be more useful is to have the call to YubiKitDeviceCapabilities.supportsMFIAccessoryKey return NO for iPads (and other devices) that do not actually support the MFI protocol. On can then use this to skip over the startSession and closeSession calls to track session state. Without this change, it is necessary to add code in client applications that checks the iPad type...which is less than optimal.

YubiKit 4.2.0 not available via CocoaPods

Running "pod install" or "pod update" with the project podfile containing pod 'YubiKit', '4.2.0' gives this error:

[!] CocoaPods could not find compatible versions for pod "YubiKit":
  In Podfile:
    YubiKit (= 4.2.0)

None of your spec sources contain a spec satisfying the dependency: `YubiKit (= 4.2.0)`.

Searching for "YubiKit" on https://cocoapods.org shows the latest version as 4.1.0.

The podspec for 4.2.0 will need to be submitted to CocoaPods.org
See "How do I update an existing Pod?" in https://guides.cocoapods.org/making/specs-and-specs-repo.html

The version 4.2.0 ReadMe file implies it will be available.

Add YubiKit to your Podfile

use_frameworks!

pod 'YubiKit', '~> 4.2.0'

App Crashes due to null value in _Nonnull parameter in YubiKit 4.2.0

The error argument value can still be nil (null) despite being declared _Nonnull

@optional
- (void)didFailConnectingNFC:(NSError *_Nonnull)error;

Swift version

func didFailConnectingNFC(_ error: Error)

Reproduction:

  • Use YubiKit version 4.2.0 (Did not test version 4.1.0)
  • App starts a connection to both Lightning (MFI) and NFC.
  • When the user connects an MFI key, the app will call YubiKitManager method stopNFCConnection()
  • YubiKitManager calls the delegate method's didFailConnectingNFC() with nil argument.
  • When app tries to use error or its members, the app crashes with EXC_BAD_ACCESS (code=1, address=0x0)

Workaround
Update on workaround: this only works when SWIFT_OPTIMIZATION_LEVEL = "-Onone". The optimizer will remove the code when set to "-O" for release builds.

App must check if error == nil. If it is, then assume that there is no error, just the app calling stopNFCConnection().
However, the Swift compiler gives a warning:

Comparing non-optional value of type 'Error' to 'nil' always returns false

If a developer is treating warnings as errors, then they will need to make exceptions. (And deal with their security departments.)

Recommendation
Specifiy _Nullable for the parameter

Other Notes

The YKFNFCConnection member nfcConnectionErroris declared _Nullable,

@property (nonatomic, readonly, nullable) NSError *nfcConnectionError;

but is passed to the delegate (YubiKitManager)

[self.delegate didFailConnectingNFC:self.nfcConnectionError];

YubiKitManager.m implementation does not declare _Nullable or _Nonnull for error

- (void)didFailConnectingNFC:(NSError *)error {

but YubiKitManager.h interface does declare _Nonnull

@optional
- (void)didFailConnectingNFC:(NSError *_Nonnull)error;

(Adding _Nonnull to the implementation did not cause the compiler to give an error)

- (void)didFailConnectingNFC:(NSError *_Nonnull)error {

Environment
Xcode 13.3
iPhone 13 with iOS 15.4
YubiKit 4.2.0

Silly Question: How do I run the app on my device and insert a yubikey?

Hello
I'm interested in printing to the console while inserting a yubikey. Trouble is, my phone has to be connected to my laptop in order to print to console so I don't know how to insert a yubikey. Is there a way I can have my phone connected to my laptop and insert a yubikey at the same time?

Cocoapods for release 3.2.0 aren't working.

Can you please look into releasing a cocoapod update for release 3.2.0? The latest cocoapod release is 3.1.0.

In my app, if I try to specify it using the specific github url and branch name in PodFile, it dumps a ton of text to the screen and shows:

[!] [Xcodeproj] Generated duplicate UUIDs:

Thanks

Not receiving Pin Verification

When attempting to use security key with pin with login.live.com, I do not receive a YKFKeyFIDO2ErrorCodePIN_REQUIRED.

Steps:

  • Create a login.live.com account.
  • Register a YubiKey with it with a PIN.
  • Log out.
  • Attempt to sign in with the key.
  • Receives an error on the website but nothing in the SDK.

Expected:

  • Should receive YKFKeyFIDO2ErrorCodePIN_REQUIRED

[YKFOTPSession] Crash happens on iOS 15 when entering background

Howdy!

We found a recurring crash coming from the YubiKit Framework. The part what is crashed could be found in YKFOTPSession, where the NFCNDEFReaderSession is used. The problem occurs only on iOS 15, where the didInvalidateWithError delegate method called not only once, and the nfcOTPResponseBlock is set to nil on the first run , but on the second it will crash because of the EXEC_BAD_ADDRESS. Blocks are C level stuff, and don't have the neat objc_message nil checking guard over them.

I could reproduce not only in our project, but on a fresh single view application. I think not only our product is affected by this.

  1. My idea would be, it does not have to be set to nil every time. In theory the object which holds the Block's pointer should dealloc on its destruction. So could leave on.
  2. Or the delegate mechanism would be very nice, and convenient in this situation. It would not harm the pattern.

I can do any direction:

WDYT?

@jensutbult Thanks for your attention.

NFC unavailable iOS

It randomly occurs when scanning the Yubico 5C NFC tag to iOS it returns the error NFC not available.

macOS usage?

Ive got this library working great in a Mac catalyst project, however it only seems to work on iPhone and not on a Mac. Any idea why that may be?

modification to the NFC acceptance flow?

I was taking a look at the NFC flow and it currently leaves us in a bad state if the user has supplied a key that isn't an allowed key. It accepts any read key as a signal to dismiss the apple NFC reader sheet, when that sheet could be used to present error messages back to the user, such as ("please try a different key, the key you supplied isn't valid).

I had envisioned this being exposed through a delegate method such that when the key is read the host app can be supplied with information for validating the key (in our case we'd make use of the fido2Service from this delegate callback to see if the key is valid, if valid we can return true and allow the NFCSession to close; if not valid we can return false and a NSString * that the YKNFCSession can then set on the NFCSession.alertMessage (per the apple docs that string can be updated while on screen to reflect changes).

does this sound like a better flow than the current one where the sheet just disappear upon reading a key?

I'm also noticing that when my key is accepted by my app, the sheet remains on screen until i pull the key away from the device. Is this intentional?

support for U2F signing of raw data; I will make the PR with a little guidance

To support ssh public key authentication with [email protected] keys in my SSH client there needs to be a way to perform U2F signing on raw data instead of JSON.

I have implemented changes to yubikit-ios to support this in 0694403 but I imagine you have some wishes on how raw U2F signing should be added to the SDK.

Please let me know how you would like such a change to be implemented or if the current commit is acceptable. I want this to be as easy for you as possible.

OpenPGP applet returns incorrect length for application related data DO?

When requesting the Application Related Data DO of the YubiKeys OpenPGP applet via SmartCardInterface, I consistently get the following byte sequence (here represented in hexadecimal):

6e8201374f10d27600012401030400061541020700005f520800730000e00590007f740381012073820110c00a7d000bfe080000ff0000c106010800001100c206010800001100c306010800001100da06010800001100c407ff7f7f7f030003c550d9f465e6fdce605597cfaf4aadee3f6b0dce0c6cee1a6cbde1a6948eeddc1f438aa30f5beeb312f8f8de0abd38638161d8c551a567b24de02e2d200e0000000000000000000000000000000000000000c6500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd105fa5bda85fa5bda85fa5bda800000000de0801010201030181027f660802020bfe02020bfed6020020d7020020d8020020d9020020

Trying to decode this information manually according to the Functional Specification of the OpenPGP application on ISO Smart Card Operating Systems yields the following result:

(sorry for the bad formatting)

6e - Application Related Data
	82 (why not 0x02?) 01 37 (total length is 0d311 = 0x0137)
	4f - Application identifier (AID)
	10 (length 16) d2 76 00 01 24 01 03 04 00 06 15 41 02 07 00 00

	5f52 - Historical bytes
	08 (length 8) 00 73 00 00 e0 05 90 00 

	7f74 - General feature management (optional)
	03 (length 3) 81 01 20 

	73 - Discretionary data objects 
	82 (why not 0x02?) 01 10

	c0 - Extended capabilities
	0a (length 10) 7d 00 0b fe 08 00 00 ff 00 00

	c1 - Algorithm attributes signature
	06 (length 6) 01 08 00 00 11 00

	c2 - Algorithm attributes decryption
	06 (length 6) 01 08 00 00 11 00 

	c3 - Algorithm attributes authentication
	06 (length 6) 01 08 00 00 11 00 

	da - Reserved for Algorithm attributes Attestation key (Yubico)
	06 (length 6) 01 08 00 00 11 00 
	
	c4 - PW Status Bytes
	07 (length 7) ff 7f 7f 7f 03 00 03 

	c5 - Fingerprints (20 bytes (dec.) each)
	50 (length 80)	d9 f4 65 e6 fd ce 60 55 97 cf af 4a ad ee 3f 6b 0d ce 0c 6c (Sig)
			ee 1a 6c bd e1 a6 94 8e ed dc 1f 43 8a a3 0f 5b ee b3 12 f8 (Dec)
			f8 de 0a bd 38 63 81 61 d8 c5 51 a5 67 b2 4d e0 2e 2d 20 0e (Auth)
			00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 (Attest)

	c6 - List of CA-Fingerprints (20 bytes (dec.) each)
	50 (length 80)	00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 (Sig)
			00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 (Dec)
			00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 (Auth)
			00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 (Attest)

	cd - List of generation dates/times of key pairs (4 bytes (dec.) each)
	10 (length 16)	5f a5 bd a8 5f a5 bd a8 5f a5 bd a8 00 00 00 00 

	de - Key Information (2 bytes (dec.) each)
	08 (length 8) 01 01 02 01 03 01 81 02 

	7f66 - Extended length information
	08 (length 8) 02 02 0b fe 02 02 0b fe 

	d6 - User Interaction Flag (UIF) for PSO:CDS
	02 (length 2) 00 20 

	d7 - UIF for PSO:DEC
	02 (length 2) 00 20 

	d8 - UIF for PSO:AUT
	02 (length 2) 00 20 

	d9 - UIF for Attestation key and Generate Attestation command (Yubico)
	02 (length 2) 00 20

I don't understand how both for length the total length of the Application Related Data (0x6e) and the length of the Discretionary data objects (0x73), I get 0x82 instead of - presumably - 0x02?
Am I misunderstanding the encoding scheme?

I am happy to provide more information or context if needed :) Thanks!

YubiKit 4.0.0 requires minimum iOS 13.0, but podspec says iOS 11

the podspec file specifies iOS 11

s.ios.deployment_target = '11.0'

But attempting to run in any version of iOS 12 will fail with:

dyld: Library not loaded: /System/Library/Frameworks/CryptoTokenKit.framework/CryptoTokenKit
Referenced from: /Users/username/Library/Developer/CoreSimulator/Devices/2E9560E2-BBDD-4328-8B0A-AEBB81F71E35/data/Containers/Bundle/Application/3692A730-7193-41E8-8EF5-28DD4F9F2918/VmwarePIV-D.app/Frameworks/YubiKit.framework/YubiKit
Reason: image not found

Bitcode Bundle could not be generated issue

Hi Team,

I am getting an issue, when i am archiving my application with libYubiKit.a i am getting bitcode enable related build error. If i am only building application with libYubiKit.a then it is working fine.
May i know what is am i doing wrong here? I took clone "https://github.com/Yubico/yubikit-ios" and picked libYubiKit.a from here. I also checked Bitcode value into Build Settings and it was Yes there.
I am attaching screenshot here.

Yubikey Bitcode Error

Build Setting Section

‼️ didFailConnectingNFC:(NSError *_Nonnull)error causes crash

Description

Here is a bug report.

In YKFManagerDelegate you define a didFailConnectingNFC function with _Nonnull error.
But in fact, we found that in some cases it called this with nil.

@protocol YKFManagerDelegate <NSObject>

// ...

@optional
- (void)didFailConnectingNFC:(NSError *_Nonnull)error;

@end

We use the YubiKit in Swift, and because of _Nonnull definition, delegate implementers will create corresponding methods based on (NSError *_Nonnull)error; like this:
Then, it will causes a crash.

error-01

error-02

How it happened

After turning on the scan, I quickly used the yubikey card to get close to the phone, and then quickly removed it. After trying a few more times, I entered the breakpoint in the first picture.

Please fix this issue.

OTP reading fails on iOS 15 with lightning port

Hi!
We experience that the OTP reading fails on iOS 15, where devices using lightning port. The issue is that the OTP is shorter than 44 characters, mostly we can read out only 43 chars, but sometimes only 42 or 41. As we see from our logs, the lightning port devices are affected. For the OTP reading we are using the same implementation as here: https://github.com/Yubico/yubikit-ios/blob/master/YubiKitDemo/YubiKitDemo/Demos/OTP/OTPUIResponder.swift
We also tried out to set wantsPriorityOverSystemBehavior to true for the UIKeyCommands.
Also tried it out in your YubiKitDemo app, and the same thing happens. I tried it with multiple devices and with multiple yubikeys. As I can see the problem is in the phone somewhere, because one of my phone works perfectly with all yubikeys and the other phone reads always shorter OTP's from all yubikeys. Our customers started to complain about this, why does it not work. Do you have any idea? I also checked the settings between our test phones, and there is no difference in the keyboard settings, language and region. Do you have any idea or are you aware of this issue?
Thanks!
Alex

Several 'not in scope errors'

Encountered these errors in YubiKitDemo/YubiKitDemo/Demos/FIDO2/FIDO2ViewController:
Cannot find 'YubiKitManager' in scope
Cannot find 'YubiKitDeviceCapabilities' in scope
Cannot find 'YubiKitManager' in scope

Am I missing something here?

API endpoint

Is this the correct endpoint we should be using in production for registration?

"https://demo.yubico.com/api/v1/user/%@/webauthn/register-begin"

I am getting an issue where my registered credentials (via that endpoint) are no longer recognized as valid after around 24 hours...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.