#### Programming with OpenSSL * Is OpenSSL thread-safe? Yes but with some limitations; for example, an SSL connection cannot be used concurrently by multiple threads. This is true for most OpenSSL objects. For version 1.1.0 and later, there is nothing further you need do. For earlier versions than 1.1.0, it is necessary for your application to set up the thread callback functions. To do this, your application must call CRYPTO_set_locking_callback(3) and one of the CRYPTO_THREADID_set... API's. See the OpenSSL threads manpage for details and "note on multi-threading" in the INSTALL file in the source distribution. * My code gets "undefined structure" or "unknown size" when building with 1.1.0 or later. In 1.1.0 we made most of the structures opaque. This means that you can no longer access the fields directly, but must use settor and accessor functions. You can also no longer have direct instances of the objects, but can only use pointers to them. For example, the first line below is wrong; the second is correct: RSA r; /* wrong */ RSA *r; /* right */ * I've compiled a program under Windows and it crashes: why? This is usually because you've missed the comment in INSTALL.W32. Your application must link against the same version of the Win32 C-Runtime against which your openssl libraries were linked. The default version for OpenSSL is /MD - "Multithreaded DLL". If you are using Microsoft Visual C++'s IDE (Visual Studio), in many cases, your new project most likely defaulted to "Debug Singlethreaded" - /ML. This is NOT interchangeable with /MD and your program will crash, typically on the first BIO related read or write operation. For each of the six possible link stage configurations within Win32, your application must link against the same by which OpenSSL was built. If you are using MS Visual C++ (Studio) this can be changed by: 1. Select Settings... from the Project Menu. 2. Select the C/C++ Tab. 3. Select "Code Generation from the "Category" drop down list box 4. Select the Appropriate library (see table below) from the "Use run-time library" drop down list box. Perform this step for both your debug and release versions of your application (look at the top left of the settings panel to change between the two) Single Threaded /ML - MS VC++ often defaults to this for the release version of a new project. Debug Single Threaded /MLd - MS VC++ often defaults to this for the debug version of a new project. Multithreaded /MT Debug Multithreaded /MTd Multithreaded DLL /MD - OpenSSL defaults to this. Debug Multithreaded DLL /MDd Note that debug and release libraries are NOT interchangeable. If you built OpenSSL with /MD your application must use /MD and cannot use /MDd. As per 0.9.8 the above limitation is eliminated for .DLLs. OpenSSL .DLLs compiled with some specific run-time option [we insist on the default /MD] can be deployed with application compiled with different option or even different compiler. But there is a catch! Instead of re-compiling OpenSSL toolkit, as you would have to with prior versions, you have to compile small C snippet with compiler and/or options of your choice. The snippet gets installed as <install-root>/include/openssl/applink.c and should be either added to your application project or simply #include-d in one [and only one] of your application source files. Failure to link this shim module into your application manifests itself as fatal "no OPENSSL_Applink" run-time error. An explicit reminder is due that in this situation [mixing compiler options] it is as important to add CRYPTO_malloc_init prior first call to OpenSSL. * How do I read or write a DER encoded buffer using the ASN1 functions? You have two options. You can either use a memory BIO in conjunction with the i2d_*_bio() or d2i_*_bio() functions or you can use the i2d_*(), d2i_*() functions directly. Since these are often the cause of grief here are some code fragments using PKCS7 as an example: unsigned char *buf, *p; int len = i2d_PKCS7(p7, NULL); buf = OPENSSL_malloc(len); /* error checking omitted */ p = buf; i2d_PKCS7(p7, &p); At this point buf contains the len bytes of the DER encoding of p7. The opposite assumes we already have len bytes in buf: unsigned char *p = buf; p7 = d2i_PKCS7(NULL, &p, len); At this point p7 contains a valid PKCS7 structure or NULL if an error occurred. If an error occurred ERR_print_errors(bio) should give more information. The reason for the temporary variable 'p' is that the ASN1 functions increment the passed pointer so it is ready to read or write the next structure. This is often a cause of problems: without the temporary variable the buffer pointer is changed to point just after the data that has been read or written. This may well be uninitialized data and attempts to free the buffer will have unpredictable results because it no longer points to the same address. Memory allocation and encoding can also be combined in a single operation by the ASN1 routines: unsigned char *buf = NULL; int len = i2d_PKCS7(p7, &buf); if (len < 0) { /* Error */ } /* Do some things with 'buf' */ /* Finished with buf: free it */ OPENSSL_free(buf); In this special case the "buf" parameter is *not* incremented, it points to the start of the encoding. * OpenSSL uses DER but I need BER format: does OpenSSL support BER? The short answer is yes, because DER is a special case of BER and OpenSSL ASN1 decoders can process BER. The longer answer is that ASN1 structures can be encoded in a number of different ways. One set of ways is the Basic Encoding Rules (BER) with various permissible encodings. A restriction of BER is the Distinguished Encoding Rules (DER): these uniquely specify how a given structure is encoded. Therefore, because DER is a special case of BER, DER is an acceptable encoding for BER. * The encoding for GeneralName is wrong; why is the SEQUENCE tag missing? In RFC 5280 GeneralName is defined in the module in Appendix A.2, and that module specifies the use of IMPLICIT tagging. This means that there is not an explicit SEQUENCE (30) tag following the A0 tag (you just know from the ASN.1 that what follows the A1 tag is a SEQUENCE). This is in contrast to the value field within OtherName (test@kerberose-domain.internal), where the tag for UTF8String (0C) follows the A0 tag, since EXPLICIT tagging is specified for that particular field. You will notice the same thing if you look at other choices within GeneralName. If you look at the DNS names encoded in the subjectAltName extension, the 82 tag (corresponding to [2]) is not followed by a tag for IA5String (22). It is not needed since the ASN.1 indicates that what follows the 82 tag is an IA5String. However, if the module specified EXPLICIT encoding, then there would be a 16 tag after the 82 tag. (Thanks to David Cooper for this text.) * I tried to set a cipher list with a valid cipher, but the call fails, why? OpenSSL 1.1.0 introduced the concept of a “security level”, allowing for a configuration to be made more secure by excluding algorithms and key sizes that are known to be flawed or susceptible to brute force at a given level of work. SSL_CTX_set_security_level(3) can be used to programmatically set a security level, or the keyword "@SECLEVEL=N" can be used in a TLS cipher string, for values of N from 0 to 5 (inclusive). The default is level 1, which excludes MD5 as the MAC and algorithms with less than 80 bits of security. A value of 0 can be used, with appropriate caution, to produce behavior compatible with previous versions of OpenSSL (to the extent possible), but this is not recommended for general usage. * I've called <some function> and it fails, why? Before submitting a report or asking in one of the mailing lists, you should try to determine the cause. In particular, you should call ERR_print_errors(3) or ERR_print_errors_fp(3) after the failed call and see if the message helps. Note that the problem may occur earlier than you think -- you should check for errors after every call where it is possible, otherwise the actual problem may be hidden because some OpenSSL functions clear the error state. * I just get a load of numbers for the error output, what do they mean? The actual format is described in the ERR_print_errors(3) manual page. You should call the function ERR_load_crypto_strings(3) before hand and the message will be output in text form. If you can't do this (for example it is a pre-compiled binary) you can use the errstr(1) utility on the error code itself (the hex digits after the second colon). * Why do I get errors about unknown algorithms? The cause is forgetting to load OpenSSL's table of algorithms with OpenSSL_add_all_algorithms(3). See the manual page for more information. This can cause several problems such as being unable to read in an encrypted PEM file, unable to decrypt a PKCS12 file or signature failure when verifying certificates. * Why can't the OpenSSH configure script detect OpenSSL? Several reasons for problems with the automatic detection exist. OpenSSH requires at least version 0.9.5a of the OpenSSL libraries. Sometimes the distribution has installed an older version in the system locations that is detected instead of a new one installed. The OpenSSL library might have been compiled for another CPU or another mode (32/64 bits). Permissions might be wrong. The general answer is to check the config.log file generated when running the OpenSSH configure script. It should contain the detailed information on why the OpenSSL library was not detected or considered incompatible. * Can I use OpenSSL's SSL library with non-blocking I/O? Yes; make sure to read the SSL_get_error(3) manual page! A pitfall to avoid: Don't assume that SSL_read(3) will just read from the underlying transport or that SSL_write(3) will just write to it -- it is also possible that SSL_write(3) cannot do any useful work until there is data to read, or that SSL_read(3) cannot do anything until it is possible to send data. One reason for this is that the peer may request a new TLS/SSL handshake at any time during the protocol, requiring a bi-directional message exchange; both SSL_read(3) and SSL_write(3) will try to continue any pending handshake. * Why doesn't my server application receive a client certificate? Due to the TLS protocol definition, a client will only send a certificate, if explicitly asked by the server. Use the SSL_VERIFY_PEER flag of the SSL_CTX_set_verify(3) function to enable the use of client certificates. * I think I've detected a memory leak, is this a bug? In most cases the cause of an apparent memory leak is an OpenSSL internal table that is allocated when an application starts up. Since such tables do not grow in size over time they are harmless. Starting with OpenSSL 1.1.0, everything should be cleaned up on exit (or when the shared library unloads). If not, please find out what resource is leaked and report an issue. In previous releases, internal tables can be freed up when an application closes using various functions. Currently these include following: Thread-local cleanup functions include ERR_remove_state(3). Application-global cleanup functions that are aware of usage (and therefore thread-safe) include ENGINE_cleanup(3) and CONF_modules_unload(3). "Brutal" (thread-unsafe) Application-global cleanup functions include: ERR_free_strings(3), EVP_cleanup(3) and CRYPTO_cleanup_all_ex_data(3). * Why doesn't a memory BIO work when a file does? This can occur in several cases for example reading an S/MIME email message. The reason is that a memory BIO can do one of two things when all the data has been read from it. The default behaviour is to indicate that no more data is available and that the call should be retried, this is to allow the application to fill up the BIO again if necessary. Alternatively it can indicate that no more data is available and that EOF has been reached. If a memory BIO is to behave in the same way as a file this second behaviour is needed. This must be done by calling: BIO_set_mem_eof_return(bio, 0); See the manual pages for more details. * Where are the declarations and implementations of d2i_X509(3) etc? These are defined and implemented by macros of the form: DECLARE_ASN1_FUNCTIONS(X509) and IMPLEMENT_ASN1_FUNCTIONS(X509) The implementation passes an ASN1 "template" defining the structure into an ASN1 interpreter using generalised functions such as ASN1_item_d2i(3). * When debugging I observe SIGILL during OpenSSL initialization: why? OpenSSL adapts to processor it executes on and for this reason has to query its capabilities. Unfortunately on some processors the only way to achieve this for non-privileged code is to attempt instructions that can cause Illegal Instruction exceptions. The initialization procedure is coded to handle these exceptions to manipulate corresponding bits in capabilities vector. This normally appears transparent, except when you execute it under debugger, which stops prior delivering signal to handler. Simply resuming execution does the trick, but when debugging a lot it might feel counterproductive. Two options. Either set explicit capability environment variable in order to bypass the capability query (see corresponding crypto/*cap.c for details). Or configure debugger not to stop upon SIGILL exception, e.g. in gdb case add 'handle SIGILL nostop' to your .gdbinit.