Difference between revisions of "Libcrypto API"
(Added advice around some functions not returning 0 for error and 1 for success) |
m (→Getting Started: missing include in the first example) |
||
(20 intermediate revisions by 8 users not shown) | |||
Line 5: | Line 5: | ||
In order to use libcrypto it must first (typically) be initialised: | In order to use libcrypto it must first (typically) be initialised: | ||
+ | #include <openssl/conf.h> | ||
#include <openssl/evp.h> | #include <openssl/evp.h> | ||
+ | #include <openssl/err.h> | ||
int main(int arc, char *argv[]) | int main(int arc, char *argv[]) | ||
Line 16: | Line 18: | ||
/* Load config file, and other important initialisation */ | /* Load config file, and other important initialisation */ | ||
− | + | OPENSSL_config(NULL); | |
/* ... Do some crypto stuff here ... */ | /* ... Do some crypto stuff here ... */ | ||
Line 24: | Line 26: | ||
/* Removes all digests and ciphers */ | /* Removes all digests and ciphers */ | ||
EVP_cleanup(); | EVP_cleanup(); | ||
+ | |||
+ | /* if you omit the next, a small leak may be left when you make use of the BIO (low level API) for e.g. base64 transformations */ | ||
+ | CRYPTO_cleanup_all_ex_data(); | ||
/* Remove error strings */ | /* Remove error strings */ | ||
Line 37: | Line 42: | ||
Refer to [[EVP]] for further information on the high level interface. | 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. | + | 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 140-2|FIPS]] mode. |
==Error Handling== | ==Error Handling== | ||
Line 45: | Line 50: | ||
It is common to see errors handled in a way similar to the following: | It is common to see errors handled in a way similar to the following: | ||
− | if(!EVP_xxx()) goto err; | + | if(1 != EVP_xxx()) goto err; |
− | if(!EVP_yyy()) goto err; | + | if(1 != EVP_yyy()) goto err; |
/* ... do some stuff ... */ | /* ... do some stuff ... */ | ||
Line 61: | Line 66: | ||
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. | 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: | ||
+ | |||
+ | <pre> | ||
+ | if (1 != some_openssl_function()) | ||
+ | /* handle error */ | ||
+ | </pre> | ||
+ | |||
+ | Refer to the [[Library Errors]] page for more information about OpenSSL errors. | ||
+ | |||
+ | == Thread Safety == | ||
+ | |||
+ | OpenSSL currently is thread-NOT-safe by default. In order to make it thread-safe the caller has to provide various callbacks for locking, atomic integer addition, and thread ID determination (this last has reasonable defaults). This makes it difficult to use OpenSSL from multiple distinct objects in one multi-threaded process: one of them had better provide these callbacks, but only one of them should. | ||
+ | |||
+ | Currently the only moderately safe way for libraries using OpenSSL to handle thread safety is to do the following as early as possible, possible in .init or DllMain: | ||
+ | |||
+ | * Check if the locking callback has been set, then set it if not; | ||
+ | * CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK), set the remaining callbacks (threadid, dynlock, and add_lock) if not already set, then CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK); | ||
+ | |||
+ | In the future we hope that OpenSSL will self-initialize thread-safely to use native threading where available. | ||
+ | |||
+ | == Fork Safety == | ||
+ | : ''main article: [[Random fork-safety]]'' | ||
+ | |||
+ | OpenSSL library functions are generally not async-signal-safe, therefore: | ||
+ | |||
+ | * do not call OpenSSL functions from signal handlers | ||
+ | * do not call OpenSSL functions on the child-side of fork() (exec or _exit) | ||
+ | * do not call OpenSSL functions from pthread_atfork() handlers (fork() itself is and must be and remain async-signal-safe) | ||
+ | |||
+ | If you have an application for which using OpenSSL on the parent and child sides of fork() (without exec'ing) and it does not blow up naturally, then you should arrange to call RAND_poll() on the child-side of fork() before using any other RAND functions. | ||
+ | |||
+ | == Further libcrypto information == | ||
+ | |||
+ | There are a number of other pages that cover specific aspects of working with libcrypto: | ||
+ | * [[EVP|EVP High level interface for cryptographic operations]] | ||
+ | * [[Cryptographic Algorithms]] | ||
+ | * [[Random Numbers|Handling Random Numbers]] | ||
+ | * [[BIO|Working with BIOs]] | ||
+ | * [[Elliptic Curve Cryptography]] | ||
==See also== | ==See also== | ||
* [[Libssl API]] | * [[Libssl API]] | ||
− | + | ||
+ | [[Category:crypto API]] | ||
+ | [[Category:C level]] | ||
+ | [[Category:Examples]] |
Latest revision as of 03:30, 10 December 2014
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[edit]
In order to use libcrypto it must first (typically) be initialised:
#include <openssl/conf.h> #include <openssl/evp.h> #include <openssl/err.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(); /* if you omit the next, a small leak may be left when you make use of the BIO (low level API) for e.g. base64 transformations */ CRYPTO_cleanup_all_ex_data(); /* Remove error strings */ ERR_free_strings(); return 0; }
High Level and Low Level Interfaces[edit]
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[edit]
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 */
Refer to the Library Errors page for more information about OpenSSL errors.
Thread Safety[edit]
OpenSSL currently is thread-NOT-safe by default. In order to make it thread-safe the caller has to provide various callbacks for locking, atomic integer addition, and thread ID determination (this last has reasonable defaults). This makes it difficult to use OpenSSL from multiple distinct objects in one multi-threaded process: one of them had better provide these callbacks, but only one of them should.
Currently the only moderately safe way for libraries using OpenSSL to handle thread safety is to do the following as early as possible, possible in .init or DllMain:
- Check if the locking callback has been set, then set it if not;
- CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK), set the remaining callbacks (threadid, dynlock, and add_lock) if not already set, then CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
In the future we hope that OpenSSL will self-initialize thread-safely to use native threading where available.
Fork Safety[edit]
- main article: Random fork-safety
OpenSSL library functions are generally not async-signal-safe, therefore:
- do not call OpenSSL functions from signal handlers
- do not call OpenSSL functions on the child-side of fork() (exec or _exit)
- do not call OpenSSL functions from pthread_atfork() handlers (fork() itself is and must be and remain async-signal-safe)
If you have an application for which using OpenSSL on the parent and child sides of fork() (without exec'ing) and it does not blow up naturally, then you should arrange to call RAND_poll() on the child-side of fork() before using any other RAND functions.
Further libcrypto information[edit]
There are a number of other pages that cover specific aspects of working with libcrypto:
- EVP High level interface for cryptographic operations
- Cryptographic Algorithms
- Handling Random Numbers
- Working with BIOs
- Elliptic Curve Cryptography