Blog
Portable OpenSSL on Mac OS X
Date: 12/12/2014
Tags: dylib openssl
So it's been brought to my attention that Scribe's self install of OpenSSL on Mac doesn't actually work in v2.0.x, so the last week I've been looking into what it takes to do that.

The main issue is that load paths, are by default, absolute and hardcoded. Which works against you when you want a portable install of something. Secondly the OpenSSL .dylib is made of 2 libraries; libssl and libcrypt. And when you dlopen the first (libssl) the system needs to be able to find libcrypt. The link is embedded in the Mach-O image as a LC_LOAD_DYLIB segment. You can see that by issue the command:
otool -l ./libssl.1.0.0.dylib
Part of the output you'll get:
    cmd LC_LOAD_DYLIB
cmdsize 64
   name /usr/lib/libcrypto.1.0.0.dylib (offset 24)
   time stamp 2 Thu Jan  1 10:00:02 1970
That absolute path is what is causing the dlopen of libssl to fail. So we need to fix that. And the tool to do it 'install_name_tool', which is provided from Apple. Now I had two problems. Firstly what do you change the path to? And how do you actually get the tool to change the path?

Firstly Apple has several ways of locating shared libraries:
  1. @executable_path : relative to the main executable
  2. @loader_path : relative to the referring binary
  3. @rpath : relative to any of a list of paths.
What I wanted is the path to be relative to the executable, so I want:
@executable_path/libcrypto.1.0.0.dylib

But how to call install_name_tool to actually do that? Well to start with I tried:
install_name_tool -change /usr/lib/libcrypto.1.0.0.dylib @executable_path/libcrypto.1.0.0.dylib ./libssl.1.0.0.dylib
Which is actually the right command. But because the new string is longer than the old string the command fails (silently I might add). The trick to getting it to work is to add the linker command:
-Wl,-headerpad_max_install_names
to the CFLAG variable in the OpenSSL root Makefile. This causes the load segments to have extra padding bytes so that you can change the paths as much as you want later. Now after rebuilding the OpenSSL dylibs you can reissue the install_name_tool command and the link path changes:
MacOS matthew$ otool -l ./libssl.1.0.0.dylib
...
    cmd LC_LOAD_DYLIB
cmdsize 64
   name @executable_path/libcrypto.1.0.0.dylib (offset 24)
...
Then I could dlopen 'libssl.1.0.0.dylib' and it would pull in the right libcrypt file (both as sitting in the same folder as the executable).

I'm putting this here so I don't forget how to do this next time. Ha.
Comments:
Yakov Eremin
10/04/2015 8:09pm
Hello!

Thank you for sharing this solution. I trying to build OpenSSL 1.0.2a, but result libcrypto.1.0.0.dylib depends of /usr/lib/libcrypto.1.0.0.dylib, and libssl.1.0.0.dylib depends of both!
./Configure darwin64-x86_64-cc -shared
And after fix:
otool -L libssl.1.0.0.dylib 
libssl.1.0.0.dylib:
	/usr/local/ssl/lib/libssl.1.0.0.dylib (compatibility version 1.0.0, current version 1.0.0)
	@executable_path/libcrypto.1.0.0.dylib (compatibility version 1.0.0, current version 1.0.0)
otool -L libcrypto.1.0.0.dylib 
libcrypto.1.0.0.dylib:
	/usr/local/ssl/lib/libcrypto.1.0.0.dylib (compatibility version 1.0.0, current version 1.0.0)
Have you any ideas how to avoid this situation?
Yakov Eremin
12/04/2015 2:14am
I'm apparently solve this problem:
./Configure darwin64-x86_64-cc -shared --openssldir="@rpath"
After building app I add result dylibs to Frameworks folder, and modify application binary via install_name_tool:
install_name_tool -change /usr/lib/libcrypto.0.9.8.dylib\
 ../Frameworks/libcrypto.1.0.0.dylib BinaryName

install_name_tool -change /usr/lib/libssl.0.9.8.dylib\
 ../Frameworks/libssl.1.0.0.dylib BinaryName
Bash script
CasiGeant
15/03/2018 10:42am
Hello. I'm Jeff
 
Reply
From:
Email (optional): (Will be HTML encoded to evade harvesting)
Message:
 
Remember username and/or email in a cookie.
Notify me of new posts in this thread via email.
BBcode:
[q]text[/q]
[url=link]description[/url]
[img]url_to_image[/img]
[pre]some_code[/pre]
[b]bold_text[/b]