libcrypto.dylib for architecture x86_64

We've been trying to update an app that contains SFTP access to servers. It uses libssh2. We get the following error:


cannot link directly with dylib/framework, your binary is not an allowed client of /usr/lib/libcrypto.dylib for architecture x86_64


Is this a 32-bit issue, or something else? What does "not an allowed client of mean"?

Replies

What platform are you targeting?

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Latest released MacOS.

Are you trying to use the OpenSSL libraries built in to macOS? If so, that’s not something we support. Those libraries were deprecated back in the 10.7 days. Watch WWDC 2011 Session 212 Next-Generation Cryptographic Services for a full explanation as to why.

[Ironically, the replacement crypto API, Security Transforms, is now effectively deprecated as well, but there are other APIs you can use. In fact, Apple’s crypto APIs are in a better shape today than they have ever been.]

As to how you should proceed, that depends on your goals:

  • If you’re using libcrypto in your own code for basic cryptographic operations, rewrite that code to use one of Apple’s crypto APIs. If you post details about what you need, I can point you in the right direction.

  • If you’re not using libcrypto directly, but instead are using some other library (like OpenSSL) that depends on libcrypto, you have two choices:

    • You can tweak that library to use an Apple API directly. IMO, most open source libraries would benefit from having a crypto abstraction layer, because crypto APIs vary wildly across platforms and it’s generally best to use the platform-specific API.

    • You can build libcrypto from source and include that in your product.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

We are basically using libssh2. I'm not sure where the libcrypto comes in, i.e., somewhere in their library. We has created some wrappers and Objective C interfaces to create a full sftp client within our app, added a few things for progress indicators, etc. It all worked great until the recent system.


I just downloaded and installed XCode 11.1 from "downloads". (The App Store version simply refuses to complete a download -- subject of a separate discussion in the XCode area.)


I'll delve into this some more and try to digest your suggestions.

I don't think you are using the deprecated library. On Mojave, /usr/lib/libcrypto.dylib is a symbolic link to /usr/lib/libcrypto.35.dylib. But on Catalina, /usr/lib/libcrypto.dylib is some sort of small stub or wrapper library. It is not a symlink. When I look at with "strings", there is a comment about "Clients should not load the unversioned libcrypto dylib as it does not have a stalbe ABI". I guess that is what is tripping you up.


It is tempting to just link to the included open-source libraries that are included with macOS. But that really isn't reliable, as you have discovered. Apple builds these libraries for its own use only. Apple expects developers to only link against its published APIs. I have been burned numerous times when linking directly to libraries. Now, if I need an Apple framework, I'll link to the framework. But if I have some 3rd party library or code that wants to link directly to an underlying dynamic library, I will build and include that library in my app and make a number of other changes to the project to ensure I include and link against my library. That way, I know it always works and always has a stable interface.

It is tempting to just link to the included open-source libraries that are included with macOS. But that really isn't reliable, as you have discovered. Apple builds these libraries for its own use only.

Hmmm, that’s missing a key subtlety. In general, you should feel free to use libraries (regardless of whether they originated with open source) whose headers and stub libraries appear in the macOS SDK. While there are some exceptions — more on this below — there are tonnes of such libraries in the macOS SDK that are fully supported. For example, it makes no sense at all to ship with your own copy of libxml2.

Most of the problems here stem from the distant past, in an era before the advent of formal SDKs, where folks used the libraries as they appeared in

/usr/include/
and
/usr/lib/
on their running systems. Occasionally Apple would add headers to
/usr/include/
without properly considering the long-term binary compatibility impact of that decision. This is exactly what happened with OpenSSL.

In recent years Apple has been much more careful about what’s in the macOS SDK [1], and any remaining libraries in the SDK, except where deprecated, should be considered supported API.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

[1] Hey, we finally managed to remove the kernel’s MAC framework headers, and thus resolve the issue described in QA1574.

Well, this is going to be awkward.


It was actually libxml2 that burned me one of those times. 🙂 But you are correct about it being subtle. If I remember correctly, the bug in libxml2 seemed to be in code embedded in NSXMLDocument. The standalone, system libxml2 was not affected. I think. But still, I lost a lot of confidence in system libraries after that. I like to be SURE that my app isn't going to suffer from introduced system bugs. This was a special case. I only mentioned it because you brought up that specific library. I have seen problems in other system libraries too. Another one I remember in particular involved crashes in the system sqlite that didn't occur in my own build.


To be clear, custom builds are not easy. There is a big difference between building open-source tools for personal use and building them for inclusion in your own software. Many open-source libraries are hard-configured for particular architectures or platforms. At least we don't have to support i386 builds anymore, but most people will want to move to iOS at some point. I have one complex project where I've almost completely abandonned system libraries due to differences between iOS and macOS. It is definitely more work to setup the build infrastructure, but then you can have a lot more confidence in the output. You can also freely use custom build options and enhanced functionalities that may not be present in the system builds.


This case seems like a clear-cut example of a subtle change in the OS that would be solved with a custom build. I actually had an app using libssh2 once. What I did was link statically against libssh2 and openssl-1.0.1m(libssl and libcrypto). This was a Mac App Store app, so I already had a custom openssl build for receipt validation, as Apple recommends. I did link directly against the system libz and libcurl. But if this was an app that I had wanted to port to iOS, I would have needed a custom build of libcurl.

That last post reminded me of something. Here is a "link" to a set of pre-built OpenSSL libraries for all Apple platforms: receigen.etiemble.com/guides-openssl.html


This is for support of the great Receigen app. But since you need one of the libraries, it should work. You will need to manually specify the path to the OpenSSL headers and probably statically link to avoid problems with the system file of the same name. But I'm confident it will solve the problem.