All Manuals > LispWorks® User Guide and Reference Manual > 25 TCP and UDP socket communication and SSL

25.10 Advanced OpenSSL-specific issues

This section describes advanced issue that related to using OpenSSL. Read the previous sections before using anything descibed here.

25.10.1 OpenSSL interface

The configuration interface contains mostly FLI function definitions that map directly to OpenSSL calls. See below for a list of those provided.

There are also some functions to make common cases simpler. These are read-dhparams, pem-read, set-ssl-ctx-options, set-ssl-ctx-password-callback, and set-ssl-ctx-dh.

25.10.1.1 OpenSSL constants

The Lisp constants SSL_FILETYPE_ASN1 and SSL_FILETYPE_PEM representing file types are provided.

25.10.1.2 Naming conventions for direct OpenSSL calls

This section describes the mapping between OpenSSL function names and the corresponding Lisp names.

25.10.1.3 Mapping C names to Lisp names

For functions that map directly to OpenSSL calls, the convention is to create the LISP name from the C name by replacing underscores by hyphens.

25.10.1.4 Mapping Lisp names to C names

To find the C name from the LISP function name:

  1. the hyphens need to be replaced by underscores, and:
  2. the initial SSL or SSL_CTX has to be in uppercase, and:
  3. the rest has to be lowercase, except that:
  4. the following phrases are cased specially, like this: "RSAPrivateKey", "DSH ", "ASN1", "CA", "PrivateKey".

25.10.2 Direct calls to OpenSSL

The following functions map directly to the OpenSSL functions. Check the OpenSSL documentation for details.

Where an OpenSSL function takes an SSL* or SSL_CTX*, the Lisp function's argument must be a foreign pointer of type ssl-pointer, ssl-ctx-pointer or ssl-cipher-pointer. Where an OpenSSL function takes a char* or int, the Lisp function's argument must be a string or integer. Where an OpenSSL function takes other kinds of pointers, the Lisp function's argument must be a foreign pointer. The return values are integers or foreign pointers unless stated otherwise.

If an error occurs in one of these functions, an error code is returned. They do not signal any Common Lisp conditions and so you should check the return value carefully.

Direct calls to OpenSSL
Lisp functionReturn values

ssl-add-client-ca

ssl-cipher-get-bits

First value is number of bits the cipher actually uses.
Second value is number of bits the algorithm of the cipher can use (which may be higher).

ssl-cipher-get-name

string.
e.g. "DHE-RSA-AES256-SHA"

ssl-cipher-get-version

string.
e.g. "TLSv1/SSLv3"

ssl-clear-num-renegotiations

ssl-ctrl

ssl-ctx-add-client-ca

ssl-ctx-add-extra-chain-cert

ssl-ctx-ctrl

ssl-ctx-get-max-cert-list

ssl-ctx-get-mode

ssl-ctx-get-options

ssl-ctx-get-read-ahead

ssl-ctx-get-verify-mode

integer

ssl-ctx-load-verify-locations

ssl-ctx-need-tmp-rsa

ssl-ctx-sess-set-cache-size

ssl-ctx-sess-get-cache-size

ssl-ctx-sess-set-cache-mode

ssl-ctx-sess-get-cache-mode

ssl-ctx-set-client-ca-list

ssl-ctx-set-max-cert-list

ssl-ctx-set-mode

ssl-ctx-set-options

ssl-ctx-set-read-ahead

ssl-ctx-set-tmp-rsa

ssl-ctx-set-tmp-dh

ssl-ctx-use-certificate-chain-file

ssl-ctx-use-certificate-file

ssl-ctx-use-privatekey-file

ssl-ctx-use-rsaprivatekey-file

ssl-get-current-cipher

ssl-cipher-pointer
Can be a null pointer.

ssl-get-max-cert-list

ssl-get-mode

ssl-get-options

ssl-get-verify-mode

integer

ssl-get-version

string
"TLSv1", "SSLv2" or "SSLv3"

ssl-load-client-ca-file

ssl-need-tmp-rsa

ssl-num-renegotiations

ssl-session-reused

ssl-set-accept-state

None

ssl-set-client-ca-list

ssl-set-connect-state

None

ssl-set-max-cert-list

ssl-set-mode

ssl-set-options

ssl-set-tmp-rsa

ssl-set-tmp-dh

ssl-total-renegotiations

ssl-use-certificate-file

ssl-use-rsaprivatekey-file

ssl-use-privatekey-file

If you need OpenSSL functionality that is not provided here, you can define your own foreign functions via the LispWorks Foreign Language Interface.

If you do this, an important point to note is that on Microsoft Windows, the :calling-convention must be :cdecl (it defaults to :stdcall). If using OpenSSL suddenly causes mysterious crashes, the calling-convention in your foreign function definitions is the first thing to check.

25.10.3 Using SSL objects directly

The C objects SSL and SSL_CTX are represented in LispWorks by foreign pointers with type ssl-pointer and ssl-ctx-pointer, which correspond to the C types SSL* and SSL_CTX*. These foreign types should be used for any foreign function that takes or returns these C types, and must be used when passing a foreign pointer as the value of the :ssl-ctx argument.

Making SSL objects is a way of getting access to them to perform configuration, but, especially in the case of the SSL_CTX, it is a useful way to avoid repeated calls to the configuration routines which may be time consuming. For example, if we have defined a function configure-a-ctx, and we want to read once every 60 seconds from some URL, we can write:

(loop (with-open-stream
          (str (comm:open-tcp-stream some-url 443 :ssl-ctx t
                                     :ctx-configure-callback 'configure-a-ctx))
        (read-something str))
      (sleep 60))

This will cause configure-a-ctx to be called each time. If it is expensive, we can call it only once by changing the code to:

(let ((ctx (comm:make-ssl-ctx :ssl-side :client)))
  (configure-a-ctx ctx)
  (loop (with-open-stream
    (str (comm:open-tcp-stream some-url 443 :ssl-ctx ctx))
          (read-something str))
        (sleep 60))
  (comm:destroy-ssl-ctx ctx))

The SSL objects could be made either by make-ssl-ctx or ssl-new or by user code that calls the C functions SSL_CTX_new and SSL_new. destroy-ssl-ctx frees the SSL_CTX object. To free an SSL object you would call destroy-ssl. See the manual entries for full descriptions of these functions.

Alternatively, the SSL objects can be obtained from a socket-stream by calling socket-stream-ssl or socket-stream-ctx and from an async-io-state by calling async-io-state-ssl or async-io-state-ctx. You can also find the ssl-side value that was passed to the interface call that created the SSL objects by calling socket-stream-ssl-side or async-io-state-ssl-side.

25.10.4 Initialization

All the functions that make a SSL_CTX first call ensure-ssl, so normally you do not need to initialize the library. If your code makes a SSL_CTX itself (that is, not by calling any of the LispWorks interface functions), it needs to initialize the library first. Normally that should be done by an explicit call to ensure-ssl, which loads the SSL library and calls SSL_library_init and SSL_load_error_strings, and also does some LispWorks specific initializations. If your code must do the initialization, ensure-ssl should still be called with the argument :already-done t, which tells it that the library is already loaded and initialized.


LispWorks® User Guide and Reference Manual - 01 Dec 2021 19:30:24