1

I'm using OS X 10.10 with Xcode 7 beta 2. I want to use AES/GCM from OpenSSL. I wanted to get started with an example, so I took one from the OpenSSL wiki. The code is below.

The code doesn't compile. It looks like the compiler can't find the following:

  • EVP_aes_256_gcm
  • EVP_CTRL_GCM_SET_IVLEN
  • EVP_CTRL_GCM_GET_TAG

I take it items involving GCM mode are missing. What should I do? Is there a way to update my library or something I didn't import?


Here is my code:

#include <openssl/evp.h>
#include <openssl/crypto.h>
#include <openssl/aes.h>

void handleErrors()
{
}

int encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *aad,
            int aad_len, unsigned char *key, unsigned char *iv,
            unsigned char *ciphertext, unsigned char *tag)
{
    EVP_CIPHER_CTX *ctx;

    int len;

    int ciphertext_len;


    /* Create and initialise the context */
    if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors();

    /* Initialise the encryption operation. */
    if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL))
        handleErrors();

    /* Set IV length if default 12 bytes (96 bits) is not appropriate */
    if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 16, NULL))
        handleErrors();

    /* Initialise key and IV */
    if(1 != EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv)) handleErrors();

    /* Provide any AAD data. This can be called zero or more times as
     * required
     */
    if(1 != EVP_EncryptUpdate(ctx, NULL, &len, aad, aad_len))
        handleErrors();

    /* Provide the message to be encrypted, and obtain the encrypted output.
     * EVP_EncryptUpdate can be called multiple times if necessary
     */
    if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
        handleErrors();
    ciphertext_len = len;

    /* Finalise the encryption. Normally ciphertext bytes may be written at
     * this stage, but this does not occur in GCM mode
     */
    if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) handleErrors();
    ciphertext_len += len;

    /* Get the tag */
    if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag))
        handleErrors();

    /* Clean up */
    EVP_CIPHER_CTX_free(ctx);

    return ciphertext_len;
}

int main()
{
}
jww
  • 97,681
  • 90
  • 411
  • 885
Matteo Monti
  • 8,362
  • 19
  • 68
  • 114
  • 1
    AES GCM is in the 1.1+ openssl branches. The libcrypto shipped with OS X (10.10.4) is (a) deprecated as of 10.7, and (b) only covers through version 0.9.8zf (according to `openssl version`). Looks like Common Crypto may be worth looking into. – WhozCraig Jul 07 '15 at 18:58
  • Well... I would need my code to be reasonably portable on Linux... is Common Crypto an OS X only library? Isn't there any way to update my library? – Matteo Monti Jul 07 '15 at 19:18
  • Update: from brew I managed what looks like the latest version of openssl. From command line, if I ask "openssl version" I now get "OpenSSL 1.0.2c 12 Jun 2015". But still SSLeay_version outputs "OpenSSL 0.9.8zf 19 Mar 2015". The functions and defines I needed are now actually found, but the linker is complaining for missing symbols. Am I missing something? Maybe the include and library paths are wrong somewhere? – Matteo Monti Jul 07 '15 at 19:22
  • CC is OSX only (and frankly, I'd be surprised if it offered GCM regardless as I've not really looked for it). Updating to a later openssl is certainly plausible, especially if someone else did the legwork for you already (looks like brew has). You likely have to link to a different dylib, or just use the static lib, and in either case, from the version installed by brew; not the one installed with OS X. Luck be with you on that hunt, as I don't use brew and thusly cannot say where it was dropped. – WhozCraig Jul 07 '15 at 19:25
  • Ok, so... when I say "-lcrypto" I am referring to a libcrypto.dylib file that could be anywhere in my system? No way to track it down? Because I know where to find the new one, installed by brew... – Matteo Monti Jul 07 '15 at 19:35
  • If you know where the new one resides you should be able to at-least-link to it via the Build Phases linked libraries for your build Target. Your program knowing where to *find* it at runtime is another issue. You may just end up static linking the .a file instead. – WhozCraig Jul 07 '15 at 19:42
  • I managed to do that with a -L/path/to/new/lib set as linker flag. Thanks!! – Matteo Monti Jul 07 '15 at 19:48
  • Please submit a bug report requesting that AES GCM needs to be added to Common Crypto: http://bugreport.apple.com. – zaph Jul 07 '15 at 19:53

1 Answers1

2

I take it items involving GCM mode are missing. What should I do? Is there a way to update my library or something I didn't import?

OS X provides OpenSSL 0.9.8. Its very anemic, now and it lacks most EC stuff, TLS 1.1, TLS 1.2, good support for client certs, etc. In December, 2015, it will enter End of Life.

What you should do is download and install OpenSSL 1.0.2. Download it from OpenSSL Sources and Tarballs. Unpack it, and then (most of its taken from OpenSSL's Compilation and Installation):

cd openssl-1.0.2

export KERNEL_BITS=64
./config no-ssl2 no-ssl3 enable-ec_nistp_64_gcc_128 --openssldir=/usr/local/ssl/macosx-x64/
make
make test
sudo make install

You have to manually add enable-ec_nistp_64_gcc_128 for 64-bit architectures because Configure can't determine it on its own.

Then, perform a dclean, and optionally build for 32-bit:

export KERNEL_BITS=32
make clean && make dclean
./config no-ssl2 no-ssl3 --openssldir=/usr/local/ssl/macosx-x86/
make
make test
sudo make install

In the above, shared was omitted. That's because Apple linkers always use the shared object, even if you try to specify the static archive. Shared libraries will also get you in trouble because Apple's version of the dylib will be found before your version (unless you use tricks like DYLD_LIBRARY_PATH or RPATHs).

You should also consider adding no-comp because we know compression leaks information in some contexts. CRIME and BREACH are two demonstrations of the information leak.

Finally, you should not build a fat library. In fact, the build system does not allow it by adding -arch i386 -arch x86_64 (requires manual modifications to Makefile.org). It breaks the ar command, IIRC. If you could build a fat library, or use lipo to create one, then opensslconf.h would be incorrect for one of the platforms.


Use these Xcode Build Settings setting for x86_64:

  • Always Search User Paths: NO
  • Header Search Path: /usr/local/ssl/macosx-x64/include
  • Library Search Path: /usr/local/ssl/macosx-x64/lib

And use these Xcode Build Settings setting for i386:

  • Always Search User Paths: NO
  • Header Search Path: /usr/local/ssl/macosx-x86/include
  • Library Search Path: /usr/local/ssl/macosx-x86/lib

Be sure to specify the libcrypto.a library or you will get linker errors. Its not easy/intuitive under Xcode. For that, see something like How to “add existing frameworks” in Xcode?

Community
  • 1
  • 1
jww
  • 97,681
  • 90
  • 411
  • 885