Libcrypto API
OpenSSL provides two primary libraries: libssl and libcrypto. The libcrypto library provides the fundamental cryptographic routines used by libssl. You can however use libcrypto without using libssl.
Getting Started
In order to use libcrypto it must first (typically) be initialised:
#include <openssl/conf.h> #include <openssl/evp.h> int main(int arc, char *argv[]) { /* Load the human readable error strings for libcrypto */ ERR_load_crypto_strings(); /* Load all digest and cipher algorithms */ OpenSSL_add_all_algorithms(); /* Load config file, and other important initialisation */ OPENSSL_config(NULL); /* ... Do some crypto stuff here ... */ /* Clean up */ /* Removes all digests and ciphers */ EVP_cleanup(); /* Remove error strings */ ERR_free_strings(); return 0; }
High Level and Low Level Interfaces
For most uses, users should use the high level interface that is provided for performing cryptographic operations. This is known as the EVP interface (short for Envelope). This interface provides a suite of functions for performing encryption/decryption (both symmetric and asymmetric), signing/verifying, as well as generating hashes and MAC codes, across the full range of OpenSSL supported algorithms and modes. Working with the high level interface means that a lot of the complexity of performing cryptographic operations is hidden from view. A single consistent API is provided. In the event that you need to change your code to use a different algorithm (for example), then this is a simple change when using the high level interface. In addition low level issues such as padding and encryption modes are all handled for you.
Refer to EVP for further information on the high level interface.
In addition to the high level interface, OpenSSL also provides low level interfaces for working directly with the individual algorithms. These low level interfaces are not recommended for the novice user, but provide a degree of control that may not be possible when using only the high level interface. Note that many low-level interfaces are not available if you are running in FIPS mode.
Error Handling
Most OpenSSL functions will return an integer to indicate success or failure. Typically a function will return 1 on success or 0 on error. All return codes should be checked and handled as appropriate.
It is common to see errors handled in a way similar to the following:
if(1 != EVP_xxx()) goto err; if(1 != EVP_yyy()) goto err; /* ... do some stuff ... */ err: ERR_print_errors_fp(stderr);
Note that not all of the libcrypto functions return 0 for error and 1 for success. There are exceptions which can trip up the unwary. For example if you want to check a signature with some functions you get 1 if the signature is correct, 0 if it is not correct and -1 if something bad happened like a memory allocation failure. So if you do:
if (some_verify_function()) /* signature successful */
and someone can induce the "something bad happened" condition you end up behaving as though a bad signature is good. This one cropped up in the library internals at one point and was fixed in a security release. Currently you should check the manual pages or the source to be sure.
One way to avoid being bitten by this potential problem is to always use this idiom to check for errors when calling an OpenSSL function:
if (1 != some_openssl_function()) /* handle error */
Further libcrypto information
There are a number of other pages that cover specific aspects of working with libcrypto:
- EVP High level interface for cryptographic operations
- Low Level Cryptographic APIs
- Handling Random Numbers
- Working with BIOs
- Elliptic Curve Cryptography