Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Attempting to link LibFido2Swift to xcodes #387

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

hi2gage
Copy link

@hi2gage hi2gage commented Oct 18, 2024

Do not merge

I'm looking for some help linking LibFido2Swift to the xcodes executableTarget.

The project builds, it will run as expected if running within Xcode.

Screenshot 2024-10-18 at 12 58 51 PM

but as soon as I go to run that exact same build from the command line
/Users/gage/Library/Developer/Xcode/DerivedData/xcodes-eftbhwhateverlfqcanhgofyytinnj/Build/Products/Debug/xcodes list

I get this error

dyld[86238]: Library not loaded: @rpath/libcrypto.3.dylib
  Referenced from: <BBAB7C02-49D7-3938-BC1C-CB4BF14387FB> /Users/gage/Library/Developer/Xcode/DerivedData/xcodes-eftbhsfbyqplfqcanhgofyytinnj/Build/Products/Debug/xcodes
  Reason: tried: '/Users/gage/Library/Developer/Xcode/DerivedData/xcodes-eftbhsfbyqplfqcanhgofyytinnj/Build/Products/Debug/PackageFrameworks/libcrypto.3.dylib' (no such file),
'/System/Volumes/Preboot/Cryptexes/OS/Users/gage/Library/Developer/Xcode/DerivedData/xcodes-eftbhsfbyqplfqcanhgofyytinnj/Build/Products/Debug/PackageFrameworks/libcrypto.3.dylib' (no such file),
 '/Users/gage/Library/Developer/Xcode/DerivedData/xcodes-eftbhsfbyqplfqcanhgofyytinnj/Build/Products/lib/libcrypto.3.dylib' (no such file),
 '/Users/gage/Library/Developer/Xcode/DerivedData/xcodes-eftbhsfbyqplfqcanhgofyytinnj/Build/Products/Debug/PackageFrameworks/libcrypto.3.dylib' (no such file),
 '/System/Volumes/Preboot/Cryptexes/OS/Users/gage/Library/Developer/Xcode/DerivedData/xcodes-eftbhsfbyqplfqcanhgofyytinnj/Build/Products/Debug/PackageFrameworks/libcrypto.3.dylib' (no such file),
 '/Users/gage/Library/Developer/Xcode/DerivedData/xcodes-eftbhsfbyqplfqcanhgofyytinnj/Build/Products/lib/libcrypto.3.dylib' (no such file)
[1]    86238 abort

At first I thought it was an issue with LibFido2Swift not linking libcrypto but I tried adding

linkerSettings: [
    .linkedFramework("LibCbor"),
    .linkedFramework("LibCrypto"),
    .linkedFramework("libfido2"),
]

but that did not work either.

I then tried to just copy the content LibFido2Swift into this project then create a "local" LibFido2Swift module internally and that didn't work either.

I'm wondering if I'm missing something about the linking binaryTargets to a executable product.

@kinoroy or @MattKiazyk if could take a look at this branch see if I'm missing anything that would be awesome!

@@ -2,6 +2,7 @@ import Foundation
import PromiseKit
import PMKFoundation
import Rainbow
import LibFido2Swift
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be used later for Hardware challenge

@kinoroy
Copy link

kinoroy commented Oct 18, 2024

Hm, I guess the problem is that LibFido2Swift relies on dynamic/shared libraries. Shared libraries aren't merged into the executable. If you have an app bundle, they're embedded in the bundle (example: Xcodes.app/Contents/Frameworks/...), but with an executable there's no obvious place to store those libraries, unless we install them somewhere explicitly on the users machine and then set the runtime load path to search there. Will have to think a bit more about how we could do this.
We could bundle the CLI tool in the Xcodes.app bundle, and users could run it from there but I'm not sure how easy that would be given the projects are split into 2 separate repos

@kinoroy
Copy link

kinoroy commented Oct 19, 2024

Also I believe that it works when running from within Xcode because Xcode does some magic by setting DYLD_LIBRARY_PATH environment variable to be the DerivedData folder when running the executable, which overrides the dylib's baked in ID path of @rpath/libcrypto.3.dylib or the equivalent for other libraries. When you run from the command line, it goes back to trying to load from @rpath/libcrypto.3.dylib and since we haven't installed the dylib anywhere in the rpath, it won't be able to find it. In the Xcodes.app bundle we install it in the Frameworks folder which is in the rpath.

@hi2gage
Copy link
Author

hi2gage commented Oct 19, 2024

Interesting. Yeah I kind of assumed that Xcode was crating some sort of magic sandboxing.

Is there a way we could "bundle" all of the dependencies into a single package that includes the static dependencies?

Seems like there are other people dealing with adjacent issues.
https://forums.swift.org/t/swiftpm-binary-target-with-sub-dependencies/40197

It would be great if we could keep this separate from Xcodes.app.

I can't find the forum post, but there was a forum reply somewhere talking telling the compiler to look at the global install path. But that doesn't allow us to only tell users who need this to install the given dependencies.

@hi2gage
Copy link
Author

hi2gage commented Oct 19, 2024

or we rewrite libfido2 in swift along with all of it's dependencies 😜

@kinoroy
Copy link

kinoroy commented Oct 22, 2024

Is there a way we could "bundle" all of the dependencies into a single package that includes the static dependencies?

I'm not sure if this is possible with SPM. I could maybe just make a .bundle manually, or with a script that just puts all the dylib dependencies together and release that as a release artifact on the LibFido2Swift repo. But then for using this in xcodes I'm not sure if SPM even provides any way to set the rpath for an executable? We might need to be using an Xcode project to do that, and not just a Swift package as its currently set up.

Maybe mergable libraries could also help, but that's also an Xcode feature and not supported in SPM to my knowledge.

@MattKiazyk
Copy link
Contributor

Sorry busy trying to understand crypto for the login issue so haven't been responding.

What is LibCrypto and LibCbor in your repo?

The idea that I had was that if the only dependency is libfido2 - then you check (similar to aria2) for that executable on the users device if they are trying to use key based authentication. If they don't have it, they have to install it, like aria2 (or pass in the path).

@kinoroy
Copy link

kinoroy commented Oct 22, 2024

libcrypto and libcbor are both dynamic library dependencies of libfido2. libcrypto is part of OpenSSL, and libcbor is an open source library for parsing CBOR. libfido2 uses them at runtime, so I don't think there's a way around needing to have them installed somewhere.

Yeah perhaps we can do something like what is done for aria2 where the user provides the dependencies, but it's a bit trickier since these are not executables but dynamic libraries. If SPM supports optionally linking in dynamic libraries and then loading them dlopen then it could maybe be done that way. But I don't know if that's possible with SPM.

@hi2gage
Copy link
Author

hi2gage commented Oct 22, 2024

libcrypto and libcbor are both dynamic library dependencies of libfido2. libcrypto is part of OpenSSL, and libcbor is an open source library for parsing CBOR. libfido2 uses them at runtime, so I don't think there's a way around needing to have them installed somewhere.

Yeah perhaps we can do something like what is done for aria2 where the user provides the dependencies, but it's a bit trickier since these are not executables but dynamic libraries. If SPM supports optionally linking in dynamic libraries and then loading them dlopen then it could maybe be done that way. But I don't know if that's possible with SPM.

Yeah I don't think there is optional linking in SPM currently.

IMO libfido2 is a little bloated for our use case all we really want to do is get the HID device list and then have it respond to the challenge then we pass that back. We don't care about linux or all of the other editing and saving of pins etc...

Looking deeper into libfido2's implementation it's using IOKit/hid which Apple provides Swift wrappers. I would vote that we just implement the functionality needed in swift using swift IOKit and do not use the libfido2 at all. I started coding some examples last night and I was able to get IOHIDManager reading my hardware keys.

It will still be a good chunk of work but I think long term it's better than doing the dynamic linking gymnastics.

I'm more than willing to continue working on this to get it over the finish line

@kinoroy
Copy link

kinoroy commented Oct 22, 2024

Yeah honestly I think that's a really good idea. I had a lot of trouble getting it working for Xcodes.app in the first place lol so I would be down for this approach.

Lmk if you need any help :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants