6

I'm trying to use OpenSSL to compute sha1 hash from a c program. I am compiling with clang on Mac OS X Yosemite with an Intel i7 (so 64 bit).

The relevant piece of code is roughly like so:

#include <openssl/evp.h>
...
unsigned char outHash[20]; 
hash("SHA1","abcd", 20, outHash);

The thing is, when using the "hash" function from openssl/evp.h, compiling with clang yields the following error:

Undefined symbols for architecture x86_64:
  "_hash", referenced from:
      _getRandomSHA1 in main-68ccd6.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

So it looks like OpenSSL is not found by the linker (the "hash" function is unidentified). Any ideas on how to fix this?

EDIT:

It turns out that I was trying to use a function that does not exist ("hash") - sorry for misleading you about that.

However I'm still having quite the same problem: including openssl/evp.h does not seem to work.

This is the hash function that I am using, it uses evp to perform sha1 encoding:

unsigned int hash(const char *mode, const char* dataToHash, size_t dataSize, unsigned char* outHashed) {
    unsigned int md_len = -1;
    const EVP_MD *md = EVP_get_digestbyname(mode);
    if(NULL != md) {
        EVP_MD_CTX mdctx;
        EVP_MD_CTX_init(&mdctx);
        EVP_DigestInit_ex(&mdctx, md, NULL);
        EVP_DigestUpdate(&mdctx, dataToHash, dataSize);
        EVP_DigestFinal_ex(&mdctx, outHashed, &md_len);
        EVP_MD_CTX_cleanup(&mdctx);
    }
    return md_len;
}

And then I call:

hash("SHA1","abcd", 20, outHash);

I am compiling same as before, this is my compile command (pretty simple):

 clang main.c

And I'm getting the following error from the linker:

Undefined symbols for architecture x86_64:
  "_EVP_DigestFinal_ex", referenced from:
      _hash in main-935849.o
  "_EVP_DigestInit_ex", referenced from:
      _hash in main-935849.o
  "_EVP_DigestUpdate", referenced from:
      _hash in main-935849.o
  "_EVP_MD_CTX_cleanup", referenced from:
      _hash in main-935849.o
  "_EVP_MD_CTX_init", referenced from:
      _hash in main-935849.o
  "_EVP_get_digestbyname", referenced from:
      _hash in main-935849.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
orcaman
  • 6,263
  • 8
  • 54
  • 69
  • 1
    What is your compile and link command? – jww Jun 19 '15 at 16:16
  • Currently just "clang -Wall main.c". I have openssl under /opt/local/include/openssl. Do I need to let clang know about this somehow? – orcaman Jun 19 '15 at 16:48
  • Hmm, if I run the compile with -v, I see that clang is looking for includes on /usr/local/include, which also has openssl and evp.h under it. So it's weird that it still cannot link succesfully – orcaman Jun 19 '15 at 17:01
  • See the updated answer. Its a common oversight. – jww Jun 19 '15 at 17:54
  • 1
    I added info on static linking to avoid unexpected runtime errors. I missed the detail earlier, but saw it in one of your comments. – jww Jun 21 '15 at 04:00

2 Answers2

4
#include <openssl/evp.h>
...
unsigned char outHash[20]; 
hash("SHA1","abcd", 20, outHash);

OpenSSL does not have a int hash(...) or char* hash(...) function.

$ cat /usr/include/openssl/evp.h | grep hash returns 0 hits. man 3 hash returns BSD's "hash database access method".


Undefined symbols for architecture x86_64:
  "_hash", referenced from:
      _getRandomSHA1 in main-68ccd6.o

Latching on to _getRandomSHA1, there is a SHA function, but it's available from sha.h, and not evp.h (I filtered out the DEPRECATED_IN... macro):

$ cat /usr/include/openssl/sha.h | grep SHA | grep char
...
unsigned char *SHA(const unsigned char *d, size_t n, unsigned char *md);
...

I believe it uses a static buffer, and its use is discouraged.

The project recommends using EVP Message Digests interface now.


(EDIT): I am compiling same as before, this is my compile command (pretty simple):
clang main.c

See Linking OpenSSL libraries to a program. You need to add -lcrypto to the end of the compile command.


(EDIT, from comment): I have openssl at /opt/local/include/openssl....

You are going to have more problems because you are probably runtime linking against the wrong version of the OpenSSL library. For that problem, see Statically link OpenSSL in XCode. The same problem exists from the command line and Xcode.

Here's the easiest solution. Notice that it does not use -lcrypto (-lfoo is usually the solution, except when runtime linking to the wrong shared object becomes a problem):

 clang main.c -I /opt/local/include /opt/local/lib/libcrypto.a -o my_hash.exe 

An archive is just a collection of object files, so an archive can be used in place where an object file is required.

OS X does not honor RPATHs. Another solution is to build OpenSSL and your program with an RPATH so the correct version of the library is loaded at runtime. For that, see Compilation and Installation | Using RPATHs on the OpenSSL wiki and Build OpenSSL with RPATH? on Stack Overflow.

jww
  • 97,681
  • 90
  • 411
  • 885
  • upvoted. you're right - there is no hash function. still, when trying to use evp interface, I get the same error. I edited my question to reflect what I've learned, your help is appreciated. – orcaman Jun 19 '15 at 16:33
1

Which SDK are you using, and which version of Xcode? OpenSSL was deprecated in OS X 10.7 and removed from the 10.11 SDK, which ships with the Xcode 7 Beta. Downloading OpenSSL separately should work, though you may need to change your project configuration for the new location.

Flash Sheridan
  • 1,671
  • 1
  • 14
  • 14
  • 1
    I have openssl at /opt/local/include/openssl. I updated it via Mac Ports so I have the latest version. Do I need to let clang know about this location in order for the linking process to work? About Xcode/SDK - Not using Xcode. Regarding SDK version - what SDK do you mean? – orcaman Jun 19 '15 at 16:39
  • If you’re not using Xcode, are you using Apple’s Command Line Tools, or did you build your own version of Clang? Either way, which version, and could you post the output of the failing command with the -v option? – Flash Sheridan Jun 19 '15 at 17:35
  • Mac OS X and MacPorts are important details. (But you only realize it once you've worked with the platform a while). – jww Jun 21 '15 at 04:11