ossl-guide-tls-client-block

title: ossl-guide-tls-client-block(7ossl)

summary: guide\-tls\-client\-block

text:
# ossl-guide-tls-client-block(7ossl)

## NAME
ossl-guide-tls-client-block - OpenSSL Guide: Writing a simple blocking TLS client

## SIMPLE BLOCKING TLS CLIENT EXAMPLE
This page will present various source code samples demonstrating how to write a simple TLS client application which connects to a server, sends an HTTP/1.0 request to it, and reads back the response.

We use a blocking socket for the purposes of this example. This means that attempting to read data from a socket that has no data available on it to read will block (and the function will not return), until data becomes available. For example, this can happen if we have sent our request, but we are still waiting for the server's response. Similarly any attempts to write to a socket that is not able to write at the moment will block until writing is possible.

This blocking behaviour simplifies the implementation of a client because you do not have to worry about what happens if data is not yet available. The application will simply wait until it is available.

The complete source code for this example blocking TLS client is available in the demos/guide directory of the OpenSSL source distribution in the file tls-client-block.c. It is also available online at <https://github.com/openssl/openssl/blob/master/demos/guide/tls-client-block.c>.

We assume that you already have OpenSSL installed on your system; that you already have some fundamental understanding of OpenSSL concepts and TLS (see ossl-guide-libraries-introduction(7) and ossl-guide-tls-introduction(7)); and that you know how to write and build C code and link it against the libcrypto and libssl libraries that are provided by OpenSSL. It also assumes that you have a basic understanding of TCP/IP and sockets.

### Creating the SSL_CTX and SSL objects
The first step is to create an SSL_CTX object for our client. We use the SSL_CTX_new(3) function for this purpose. We could alternatively use SSL_CTX_new_ex(3) if we want to associate the SSL_CTX with a particular OSSL_LIB_CTX (see ossl-guide-libraries-introduction(7) to learn about OSSL_LIB_CTX). We pass as an argument the return value of the function TLS_client_method(3). You should use this method whenever you are writing a TLS client. This method will automatically use TLS version negotiation to select the highest version of the protocol that is mutually supported by both the client and the server.

```
    /*
     * Create an SSL_CTX which we can use to create SSL objects from. We
     * want an SSL_CTX for creating clients so we use TLS_client_method()
     * here.
     */
    ctx = SSL_CTX_new(TLS_client_method());
    if (ctx == NULL) {
        printf("Failed to create the SSL_CTX\n");
        goto end;
    }
```

Since we are writing a client we must ensure that we verify the server's certificate. We do this by calling the SSL_CTX_set_verify(3) function and pass the SSL_VERIFY_PEER value to it. The final argument to this function is a callback that you can optionally supply to override the default handling for certificate verification. Most applications do not need to do this so this can safely be set to NULL to get the default handling.

```
    /*
     * Configure the client to abort the handshake if certificate
     * verification fails. Virtually all clients should do this unless you
     * really know what you are doing.
     */
    SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
```

In order for certificate verification to be successful you must have configured where the trusted certificate store to be used is located (see ossl-guide-tls-introduction(7)). In most cases you just want to use the default store so we call SSL_CTX_set_default_verify_paths(3).

```
    /* Use the default trusted certificate store */
    if (!SSL_CTX_set_default_verify_paths(ctx)) {
        printf("Failed to set the default trusted certificate store\n");
        goto end;
    }
```

We would also like to restrict the TLS versions that we are willing to accept to TLSv1.2 or above. TLS protocol versions earlier than that are generally to be avoided where possible. We can do that using SSL_CTX_set_min_proto_version(3):

```
    /*
     * TLSv1.1 or earlier are deprecated by IETF and are generally to be
     * avoided if possible. We require a minimum TLS version of TLSv1.2.
     */
    if (!SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION)) {
        printf("Failed to set the minimum TLS protocol version\n");
        goto end;
    }
```

That is all the setup that we need to do for the SSL_CTX, so next we need to create an SSL object to represent the TLS connection. In a real application we might expect to be creating more than one TLS connection over time. In that case we would expect to reuse the SSL_CTX that we already created each time. There is no need to repeat those steps. In fact it is best not to since certain internal resources are cached in the SSL_CTX. You will get better performance by reusing an existing SSL_CTX instead of creating a new one each time.

Creating the SSL object is a simple matter of calling the SSL_new(3) function and passing the SSL_CTX we created as an argument.

```
    /* Create an SSL object to represent the TLS connection */
    ssl = SSL_new(ctx);
    if (ssl == NULL) {
        printf("Failed to create the SSL object\n");
        goto end;
    }
```

### Creating the socket and BIO
TLS data is transmitted over an underlying transport layer. Normally a TCP socket. It is the application's responsibility for ensuring that the socket is created and associated with an SSL object (via a BIO).

Socket creation for use by a client is typically a 2 step process, i.e. constructing the socket; and connecting the socket.

How to construct a socket is platform specific - but most platforms (including Windows) provide a POSIX compatible interface via the socket function, e.g. to create an IPv4 TCP socket:

```
    int sock;
    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock == -1)
        return NULL;
```

Once the socket is constructed it must be connected to the remote server. Again the details are platform specific but most platforms (including Windows) provide the POSIX compatible connect function. For example:

```
    struct sockaddr_in serveraddr;
    struct hostent *server;
    server = gethostbyname("www.openssl.org");
    if (server == NULL) {
        close(sock);
        return NULL;
    }
    memset(&serveraddr, 0, sizeof(serveraddr));
    serveraddr.sin_family = server->h_addrtype;
    serveraddr.sin_port = htons(443);
    memcpy(&serveraddr.sin_addr.s_addr, server->h_addr, server->h_length);
    if (connect(sock, (struct sockaddr *)&serveraddr,
                sizeof(serveraddr)) == -1) {
        close(sock);
        return NULL;
    }
```

OpenSSL provides portable helper functions to do these tasks which also integrate into the OpenSSL error system to log error data, e.g.

```
    int sock = -1;
    BIO_ADDRINFO *res;
    const BIO_ADDRINFO *ai = NULL;
    /*
     * Lookup IP address info for the server.
     */
    if (!BIO_lookup_ex(hostname, port, BIO_LOOKUP_CLIENT, family, SOCK_STREAM, 0,
                       &res))
        return NULL;
    /*
     * Loop through all the possible addresses for the server and find one
     * we can connect to.
     */
    for (ai = res; ai != NULL; ai = BIO_ADDRINFO_next(ai)) {
        /*
         * Create a TCP socket. We could equally use non-OpenSSL calls such
         * as "socket" here for this and the subsequent connect and close
         * functions. But for portability reasons and also so that we get
         * errors on the OpenSSL stack in the event of a failure we use
         * OpenSSL's versions of these functions.
         */
        sock = BIO_socket(BIO_ADDRINFO_family(ai), SOCK_STREAM, 0, 0);
        if (sock == -1)
            continue;
        /* Connect the socket to the server's address */
        if (!BIO_connect(sock, BIO_ADDRINFO_address(ai), BIO_SOCK_NODELAY)) {
            BIO_closesocket(sock);
            sock = -1;
            continue;
        }
        /* We have a connected socket so break out of the loop */
        break;
    }
    /* Free the address information resources we allocated earlier */
    BIO_ADDRINFO_free(res);
```

See BIO_lookup_ex(3), BIO_socket(3), BIO_connect(3), BIO_closesocket(3), BIO_ADDRINFO_next(3), BIO_ADDRINFO_address(3) and BIO_ADDRINFO_free(3) for further information on the functions used here. In the above example code the hostname and port variables are strings, e.g. "www.example.com" and "443". Note also the use of the family variable, which can take the values of AF_INET or AF_INET6 based on the command line -6 option, to allow specific connections to an ipv4 or ipv6 enabled host.

Sockets created using the methods described above will automatically be blocking sockets - which is exactly what we want for this example.

Once the socket has been created and connected we need to associate it with a BIO object:

```
    BIO *bio;
    /* Create a BIO to wrap the socket */
    bio = BIO_new(BIO_s_socket());
    if (bio == NULL) {
        BIO_closesocket(sock);
        return NULL;
    }
    /*
     * Associate the newly created BIO with the underlying socket. By
     * passing BIO_CLOSE here the socket will be automatically closed when
     * the BIO is freed. Alternatively you can use BIO_NOCLOSE, in which
     * case you must close the socket explicitly when it is no longer
     * needed.
     */
    BIO_set_fd(bio, sock, BIO_CLOSE);
```

See BIO_new(3), BIO_s_socket(3) and BIO_set_fd(3) for further information on these functions.

Finally we associate the SSL object we created earlier with the BIO using the SSL_set_bio(3) function. Note that this passes ownership of the BIO object to the SSL object. Once ownership is passed the SSL object is responsible for its management and will free it automatically when the SSL is freed. So, once SSL_set_bio(3) has been been called, you should not call BIO_free(3) on the BIO.

```
    SSL_set_bio(ssl, bio, bio);
```

### Setting the server's hostname
We have already connected our underlying socket to the server, but the client still needs to know the server's hostname. It uses this information for 2 key purposes and we need to set the hostname for each one.

Firstly, the server's hostname is included in the initial ClientHello message sent by the client. This is known as the Server Name Indication (SNI). This is important because it is common for multiple hostnames to be fronted by a single server that handles requests for all of them. In other words a single server may have multiple hostnames associated with it and it is important to indicate which one we want to connect to. Without this information we may get a handshake failure, or we may get connected to the "default" server which may not be the one we were expecting.

To set the SNI hostname data we call the SSL_set_tlsext_host_name(3) function like this:

```
    /*
     * Tell the server during the handshake which hostname we are attempting
     * to connect to in case the server supports multiple hosts.
     */
    if (!SSL_set_tlsext_host_name(ssl, hostname)) {
        printf("Failed to set the SNI hostname\n");
        goto end;
    }
```

Here the "hostname" argument is a string representing the hostname of the server, e.g. "www.example.com".

Secondly, we need to tell OpenSSL what hostname we expect to see in the certificate coming back from the server. This is almost always the same one that we asked for in the original request. This is important because, without this, we do not verify that the hostname in the certificate is what we expect it to be and any certificate is acceptable unless your application explicitly checks this itself. We do this via the SSL_set1_host(3) function:

```
    /*
     * Ensure we check during certificate verification that the server has
     * supplied a certificate for the hostname that we were expecting.
     * Virtually all clients should do this unless you really know what you
     * are doing.
     */
    if (!SSL_set1_host(ssl, hostname)) {
        printf("Failed to set the certificate verification hostname");
        goto end;
    }
```

All of the above steps must happen before we attempt to perform the handshake otherwise they will have no effect.

### Performing the handshake
Before we can start sending or receiving application data over a TLS connection the TLS handshake must be performed. We can do this explicitly via the SSL_connect(3) function.

```
    /* Do the handshake with the server */
    if (SSL_connect(ssl) < 1) {
        printf("Failed to connect to the server\n");
        /*
         * If the failure is due to a verification error we can get more
         * information about it from SSL_get_verify_result().
         */
        if (SSL_get_verify_result(ssl) != X509_V_OK)
            printf("Verify error: %s\n",
                X509_verify_cert_error_string(SSL_get_verify_result(ssl)));
        goto end;
    }
```

The SSL_connect(3) function can return 1, 0 or less than 0. Only a return value of 1 is considered a success. For a simple blocking client we only need to concern ourselves with whether the call was successful or not. Anything else indicates that we have failed to connect to the server.

A common cause of failures at this stage is due to a problem verifying the server's certificate. For example if the certificate has expired, or it is not signed by a CA in our trusted certificate store. We can use the SSL_get_verify_result(3) function to find out more information about the verification failure. A return value of X509_V_OK indicates that the verification was successful (so the connection error must be due to some other cause). Otherwise we use the X509_verify_cert_error_string(3) function to get a human readable error message.

### Sending and receiving data
Once the handshake is complete we are able to send and receive application data. Exactly what data is sent and in what order is usually controlled by some application level protocol. In this example we are using HTTP 1.0 which is a very simple request and response protocol. The client sends a request to the server. The server sends the response data and then immediately closes down the connection.

To send data to the server we use the SSL_write_ex(3) function and to receive data from the server we use the SSL_read_ex(3) function. In HTTP 1.0 the client always writes data first. Our HTTP request will include the hostname that we are connecting to. For simplicity, we write the HTTP request in three chunks. First we write the start of the request. Secondly we write the hostname we are sending the request to. Finally we send the end of the request.

```
    size_t written;
    const char *request_start = "GET / HTTP/1.0\r\nConnection: close\r\nHost: ";
    const char *request_end = "\r\n\r\n";
    /* Write an HTTP GET request to the peer */
    if (!SSL_write_ex(ssl, request_start, strlen(request_start), &written)) {
        printf("Failed to write start of HTTP request\n");
        goto end;
    }
    if (!SSL_write_ex(ssl, hostname, strlen(hostname), &written)) {
        printf("Failed to write hostname in HTTP request\n");
        goto end;
    }
    if (!SSL_write_ex(ssl, request_end, strlen(request_end), &written)) {
        printf("Failed to write end of HTTP request\n");
        goto end;
    }
```

The SSL_write_ex(3) function returns 0 if it fails and 1 if it is successful. If it is successful then we can proceed to waiting for a response from the server.

```
    size_t readbytes;
    char buf[160];
    /*
     * Get up to sizeof(buf) bytes of the response. We keep reading until the
     * server closes the connection.
     */
    while (SSL_read_ex(ssl, buf, sizeof(buf), &readbytes)) {
        /*
        * OpenSSL does not guarantee that the returned data is a string or
        * that it is NUL terminated so we use fwrite() to write the exact
        * number of bytes that we read. The data could be non-printable or
        * have NUL characters in the middle of it. For this simple example
        * we're going to print it to stdout anyway.
        */
        fwrite(buf, 1, readbytes, stdout);
    }
    /* In case the response didn't finish with a newline we add one now */
    printf("\n");
```

We use the SSL_read_ex(3) function to read the response. We don't know exactly how much data we are going to receive back so we enter a loop reading blocks of data from the server and printing each block that we receive to the screen. The loop ends as soon as SSL_read_ex(3) returns 0 - meaning that it failed to read any data.

A failure to read data could mean that there has been some error, or it could simply mean that server has sent all the data that it wants to send and has indicated that it has finished by sending a "close_notify" alert. This alert is a TLS protocol level message indicating that the endpoint has finished sending all of its data and it will not send any more. Both of these conditions result in a 0 return value from SSL_read_ex(3) and we need to use the function SSL_get_error(3) to determine the cause of the 0 return value.

```
    /*
     * Check whether we finished the while loop above normally or as the
     * result of an error. The 0 argument to SSL_get_error() is the return
     * code we received from the SSL_read_ex() call. It must be 0 in order
     * to get here. Normal completion is indicated by SSL_ERROR_ZERO_RETURN.
     */
    if (SSL_get_error(ssl, 0) != SSL_ERROR_ZERO_RETURN) {
        /*
         * Some error occurred other than a graceful close down by the
         * peer
         */
        printf ("Failed reading remaining data\n");
        goto end;
    }
```

If SSL_get_error(3) returns SSL_ERROR_ZERO_RETURN then we know that the server has finished sending its data. Otherwise an error has occurred.

### Shutting down the connection
Once we have finished reading data from the server then we are ready to close the connection down. We do this via the SSL_shutdown(3) function which has the effect of sending a TLS protocol level message (a "close_notify" alert) to the server saying that we have finished writing data:

```
    /*
     * The peer already shutdown gracefully (we know this because of the
     * SSL_ERROR_ZERO_RETURN above). We should do the same back.
     */
    ret = SSL_shutdown(ssl);
    if (ret < 1) {
        /*
         * ret < 0 indicates an error. ret == 0 would be unexpected here
         * because that means "we've sent a close_notify and we're waiting
         * for one back". But we already know we got one from the peer
         * because of the SSL_ERROR_ZERO_RETURN above.
         */
        printf("Error shutting down\n");
        goto end;
    }
```

The SSL_shutdown(3) function will either return 1, 0, or less than 0. A return value of 1 is a success, and a return value less than 0 is an error. More precisely a return value of 1 means that we have sent a "close_notify" alert to the server, and that we have also received one back. A return value of 0 means that we have sent a "close_notify" alert to the server, but we have not yet received one back. Usually in this scenario you would call SSL_shutdown(3) again which (with a blocking socket) would block until the "close_notify" is received. However in this case we already know that the server has sent us a "close_notify" because of the SSL_ERROR_ZERO_RETURN that we received from the call to SSL_read_ex(3). So this scenario should never happen in practice. We just treat it as an error in this example.

### Final clean up
Before the application exits we have to clean up some memory that we allocated. If we are exiting due to an error we might also want to display further information about that error if it is available to the user:

```
    /* Success! */
    res = EXIT_SUCCESS;
 end:
    /*
     * If something bad happened then we will dump the contents of the
     * OpenSSL error stack to stderr. There might be some useful diagnostic
     * information there.
     */
    if (res == EXIT_FAILURE)
        ERR_print_errors_fp(stderr);
    /*
     * Free the resources we allocated. We do not free the BIO object here
     * because ownership of it was immediately transferred to the SSL object
     * via SSL_set_bio(). The BIO will be freed when we free the SSL object.
     */
    SSL_free(ssl);
    SSL_CTX_free(ctx);
    return res;
```

To display errors we make use of the ERR_print_errors_fp(3) function which simply dumps out the contents of any errors on the OpenSSL error stack to the specified location (in this case stderr).

We need to free up the SSL object that we created for the connection via the SSL_free(3) function. Also, since we are not going to be creating any more TLS connections we must also free up the SSL_CTX via a call to SSL_CTX_free(3).

## TROUBLESHOOTING
There are a number of things that might go wrong when running the demo application. This section describes some common things you might encounter.

### Failure to connect the underlying socket
This could occur for numerous reasons. For example if there is a problem in the network route between the client and the server; or a firewall is blocking the communication; or the server is not in DNS. Check the network configuration.

### Verification failure of the server certificate
A verification failure of the server certificate would result in a failure when running the SSL_connect(3) function. ERR_print_errors_fp(3) would display an error which would look something like this:

```
 Verify error: unable to get local issuer certificate
 40E74AF1F47F0000:error:0A000086:SSL routines:tls_post_process_server_certificate:certificate verify failed:ssl/statem/statem_clnt.c:2069:
```

A server certificate verification failure could be caused for a number of reasons. For example

Failure to correctly setup the trusted certificate store

See the page ossl-guide-tls-introduction(7) and check that your trusted certificate store is correctly configured

Unrecognised CA

If the CA used by the server's certificate is not in the trusted certificate store for the client then this will cause a verification failure during connection. Often this can occur if the server is using a self-signed certificate (i.e. a test certificate that has not been signed by a CA at all).

Missing intermediate CAs

This is a server misconfiguration where the client has the relevant root CA in its trust store, but the server has not supplied all of the intermediate CA certificates between that root CA and the server's own certificate. Therefore a trust chain cannot be established.

Mismatched hostname

If for some reason the hostname of the server that the client is expecting does not match the hostname in the certificate then this will cause verification to fail.

Expired certificate

The date that the server's certificate is valid to has passed.

The "unable to get local issuer certificate" we saw in the example above means that we have been unable to find the issuer of the server's certificate (or one of its intermediate CA certificates) in our trusted certificate store (e.g. because the trusted certificate store is misconfigured, or there are missing intermediate CAs, or the issuer is simply unrecognised).

## FURTHER READING
See ossl-guide-tls-client-non-block(7) to read a tutorial on how to modify the client developed on this page to support a nonblocking socket.

See ossl-guide-tls-server-block(7) for a tutorial on how to implement a simple TLS server handling one client at a time over a blocking socket.

See ossl-guide-quic-client-block(7) to read a tutorial on how to modify the client developed on this page to support QUIC instead of TLS.

## SEE ALSO
ossl-guide-introduction(7), ossl-guide-libraries-introduction(7), ossl-guide-libssl-introduction(7), ossl-guide-tls-introduction(7), ossl-guide-tls-client-non-block(7), ossl-guide-quic-client-block(7)

## COPYRIGHT
Copyright 2023-2024 The OpenSSL Project Authors. All Rights Reserved.

Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy in the file LICENSE in the source distribution or at <https://www.openssl.org/source/license.html>.


ossl-guide-tls-client-non-block

package: openssl

title: ossl-guide-tls-client-non-block(7ossl)

summary: guide\-tls\-client\-non\-block

text:
# ossl-guide-tls-client-non-block(7ossl)

## NAME
ossl-guide-tls-client-non-block - OpenSSL Guide: Writing a simple nonblocking TLS client

## SIMPLE NONBLOCKING TLS CLIENT EXAMPLE
This page will build on the example developed on the ossl-guide-tls-client-block(7) page which demonstrates how to write a simple blocking TLS client. On this page we will amend that demo code so that it supports a nonblocking socket.

The complete source code for this example nonblocking TLS client is available in the demos/guide directory of the OpenSSL source distribution in the file tls-client-non-block.c. It is also available online at <https://github.com/openssl/openssl/blob/master/demos/guide/tls-client-non-block.c>.

As we saw in the previous example a blocking socket is one which waits (blocks) until data is available to read if you attempt to read from it when there is no data yet. Similarly it waits when writing if the socket is currently unable to write at the moment. This can simplify the development of code because you do not have to worry about what to do in these cases. The execution of the code will simply stop until it is able to continue. However in many cases you do not want this behaviour. Rather than stopping and waiting your application may need to go and do other tasks whilst the socket is unable to read/write, for example updating a GUI or performing operations on some other socket.

With a nonblocking socket attempting to read or write to a socket that is currently unable to read or write will return immediately with a non-fatal error. Although OpenSSL does the reading/writing to the socket this nonblocking behaviour is propagated up to the application so that OpenSSL I/O functions such as SSL_read_ex(3) or SSL_write_ex(3) will not block.

Since this page is building on the example developed on the ossl-guide-tls-client-block(7) page we assume that you are familiar with it and we only explain how this example differs.

### Setting the socket to be nonblocking
The first step in writing an application that supports nonblocking is to set the socket into nonblocking mode. A socket will be default be blocking. The exact details on how to do this can differ from one platform to another. Fortunately OpenSSL offers a portable function that will do this for you:

```
    /* Set to nonblocking mode */
    if (!BIO_socket_nbio(sock, 1)) {
        sock = -1;
        continue;
    }
```

You do not have to use OpenSSL's function for this. You can of course directly call whatever functions that your Operating System provides for this purpose on your platform.

### Performing work while waiting for the socket
In a nonblocking application you will need work to perform in the event that we want to read or write to the socket, but we are currently unable to. In fact this is the whole point of using a nonblocking socket, i.e. to give the application the opportunity to do something else. Whatever it is that the application has to do, it must also be prepared to come back and retry the operation that it previously attempted periodically to see if it can now complete. Ideally it would only do this in the event that the state of the underlying socket has actually changed (e.g. become readable where it wasn't before), but this does not have to be the case. It can retry at any time.

Note that it is important that you retry exactly the same operation that you tried last time. You cannot start something new. For example if you were attempting to write the text "Hello World" and the operation failed because the socket is currently unable to write, then you cannot then attempt to write some other text when you retry the operation.

In this demo application we will create a helper function which simulates doing other work. In fact, for the sake of simplicity, it will do nothing except wait for the state of the socket to change.

We call our function wait_for_activity() because all it does is wait until the underlying socket has become readable or writeable when it wasn't before.

```
    static void wait_for_activity(SSL *ssl, int write)
    {
        fd_set fds;
        int width, sock;
        /* Get hold of the underlying file descriptor for the socket */
        sock = SSL_get_fd(ssl);
        FD_ZERO(&fds);
        FD_SET(sock, &fds);
        width = sock + 1;
        /*
         * Wait until the socket is writeable or readable. We use select here
         * for the sake of simplicity and portability, but you could equally use
         * poll/epoll or similar functions
         *
         * NOTE: For the purposes of this demonstration code this effectively
         * makes this demo block until it has something more useful to do. In a
         * real application you probably want to go and do other work here (e.g.
         * update a GUI, or service other connections).
         *
         * Let's say for example that you want to update the progress counter on
         * a GUI every 100ms. One way to do that would be to add a 100ms timeout
         * in the last parameter to "select" below. Then, when select returns,
         * you check if it did so because of activity on the file descriptors or
         * because of the timeout. If it is due to the timeout then update the
         * GUI and then restart the "select".
         */
        if (write)
            select(width, NULL, &fds, NULL, NULL);
        else
            select(width, &fds, NULL, NULL, NULL);
    }
```

In this example we are using the "select" function because it is very simple to use and is available on most Operating Systems. However you could use any other similar function to do the same thing. "select" waits for the state of the underlying socket(s) to become readable/writeable before returning. It also supports a "timeout" (as do most other similar functions) so in your own applications you can make use of this to periodically wake up and perform work while waiting for the socket state to change. But we don't use that timeout capability in this example for the sake of simplicity.

### Handling errors from OpenSSL I/O functions
An application that uses a nonblocking socket will need to be prepared to handle errors returned from OpenSSL I/O functions such as SSL_read_ex(3) or SSL_write_ex(3). Errors may be fatal (for example because the underlying connection has failed), or non-fatal (for example because we are trying to read from the underlying socket but the data has not yet arrived from the peer).

SSL_read_ex(3) and SSL_write_ex(3) will return 0 to indicate an error and SSL_read(3) and SSL_write(3) will return 0 or a negative value to indicate an error. SSL_shutdown(3) will return a negative value to incidate an error.

In the event of an error an application should call SSL_get_error(3) to find out what type of error has occurred. If the error is non-fatal and can be retried then SSL_get_error(3) will return SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE depending on whether OpenSSL wanted to read to or write from the socket but was unable to. Note that a call to SSL_read_ex(3) or SSL_read(3) can still generate SSL_ERROR_WANT_WRITE because OpenSSL may need to write protocol messages (such as to update cryptographic keys) even if the application is only trying to read data. Similarly calls to SSL_write_ex(3) or SSL_write(3) might generate SSL_ERROR_WANT_READ.

Another type of non-fatal error that may occur is SSL_ERROR_ZERO_RETURN. This indicates an EOF (End-Of-File) which can occur if you attempt to read data from an SSL object but the peer has indicated that it will not send any more data on it. In this case you may still want to write data to the connection but you will not receive any more data.

Fatal errors that may occur are SSL_ERROR_SYSCALL and SSL_ERROR_SSL. These indicate that the underlying connection has failed. You should not attempt to shut it down with SSL_shutdown(3). SSL_ERROR_SYSCALL indicates that OpenSSL attempted to make a syscall that failed. You can consult errno for further details. SSL_ERROR_SSL indicates that some OpenSSL error occurred. You can consult the OpenSSL error stack for further details (for example by calling ERR_print_errors(3) to print out details of errors that have occurred).

In our demo application we will write a function to handle these errors from OpenSSL I/O functions:

```
    static int handle_io_failure(SSL *ssl, int res)
    {
        switch (SSL_get_error(ssl, res)) {
        case SSL_ERROR_WANT_READ:
            /* Temporary failure. Wait until we can read and try again */
            wait_for_activity(ssl, 0);
            return 1;
        case SSL_ERROR_WANT_WRITE:
            /* Temporary failure. Wait until we can write and try again */
            wait_for_activity(ssl, 1);
            return 1;
        case SSL_ERROR_ZERO_RETURN:
            /* EOF */
            return 0;
        case SSL_ERROR_SYSCALL:
            return -1;
        case SSL_ERROR_SSL:
            /*
            * If the failure is due to a verification error we can get more
            * information about it from SSL_get_verify_result().
            */
            if (SSL_get_verify_result(ssl) != X509_V_OK)
                printf("Verify error: %s\n",
                    X509_verify_cert_error_string(SSL_get_verify_result(ssl)));
            return -1;
        default:
            return -1;
        }
    }
```

This function takes as arguments the SSL object that represents the connection, as well as the return code from the I/O function that failed. In the event of a non-fatal failure, it waits until a retry of the I/O operation might succeed (by using the wait_for_activity() function that we developed in the previous section). It returns 1 in the event of a non-fatal error (except EOF), 0 in the event of EOF, or -1 if a fatal error occurred.

### Creating the SSL_CTX and SSL objects
In order to connect to a server we must create SSL_CTX and SSL objects for this. The steps do this are the same as for a blocking client and are explained on the ossl-guide-tls-client-block(7) page. We won't repeat that information here.

### Performing the handshake
As in the demo for a blocking TLS client we use the SSL_connect(3) function to perform the TLS handshake with the server. Since we are using a nonblocking socket it is very likely that calls to this function will fail with a non-fatal error while we are waiting for the server to respond to our handshake messages. In such a case we must retry the same SSL_connect(3) call at a later time. In this demo we this in a loop:

```
    /* Do the handshake with the server */
    while ((ret = SSL_connect(ssl)) != 1) {
        if (handle_io_failure(ssl, ret) == 1)
            continue; /* Retry */
        printf("Failed to connect to server\n");
        goto end; /* Cannot retry: error */
    }
```

We continually call SSL_connect(3) until it gives us a success response. Otherwise we use the handle_io_failure() function that we created earlier to work out what we should do next. Note that we do not expect an EOF to occur at this stage, so such a response is treated in the same way as a fatal error.

### Sending and receiving data
As with the blocking TLS client demo we use the SSL_write_ex(3) function to send data to the server. As with SSL_connect(3) above, because we are using a nonblocking socket, this call could fail with a non-fatal error. In that case we should retry exactly the same SSL_write_ex(3) call again. Note that the parameters must be exactly the same, i.e. the same pointer to the buffer to write with the same length. You must not attempt to send different data on a retry. An optional mode does exist (SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER) which will configure OpenSSL to allow the buffer being written to change from one retry to the next. However, in this case, you must still retry exactly the same data - even though the buffer that contains that data may change location. See SSL_CTX_set_mode(3) for further details. As in the TLS client blocking tutorial (ossl-guide-tls-client-block(7)) we write the request in three chunks.

```
    /* Write an HTTP GET request to the peer */
    while (!SSL_write_ex(ssl, request_start, strlen(request_start), &written)) {
        if (handle_io_failure(ssl, 0) == 1)
            continue; /* Retry */
        printf("Failed to write start of HTTP request\n");
        goto end; /* Cannot retry: error */
    }
    while (!SSL_write_ex(ssl, hostname, strlen(hostname), &written)) {
        if (handle_io_failure(ssl, 0) == 1)
            continue; /* Retry */
        printf("Failed to write hostname in HTTP request\n");
        goto end; /* Cannot retry: error */
    }
    while (!SSL_write_ex(ssl, request_end, strlen(request_end), &written)) {
        if (handle_io_failure(ssl, 0) == 1)
            continue; /* Retry */
        printf("Failed to write end of HTTP request\n");
        goto end; /* Cannot retry: error */
    }
```

On a write we do not expect to see an EOF response so we treat that case in the same way as a fatal error.

Reading a response back from the server is similar:

```
    do {
        /*
         * Get up to sizeof(buf) bytes of the response. We keep reading until
         * the server closes the connection.
         */
        while (!eof && !SSL_read_ex(ssl, buf, sizeof(buf), &readbytes)) {
            switch (handle_io_failure(ssl, 0)) {
            case 1:
                continue; /* Retry */
            case 0:
                eof = 1;
                continue;
            case -1:
            default:
                printf("Failed reading remaining data\n");
                goto end; /* Cannot retry: error */
            }
        }
        /*
         * OpenSSL does not guarantee that the returned data is a string or
         * that it is NUL terminated so we use fwrite() to write the exact
         * number of bytes that we read. The data could be non-printable or
         * have NUL characters in the middle of it. For this simple example
         * we're going to print it to stdout anyway.
         */
        if (!eof)
            fwrite(buf, 1, readbytes, stdout);
    } while (!eof);
    /* In case the response didn't finish with a newline we add one now */
    printf("\n");
```

The main difference this time is that it is valid for us to receive an EOF response when trying to read data from the server. This will occur when the server closes down the connection after sending all the data in its response.

In this demo we just print out all the data we've received back in the response from the server. We continue going around the loop until we either encounter a fatal error, or we receive an EOF (indicating a graceful finish).

### Shutting down the connection
As in the TLS blocking example we must shutdown the connection when we are finished with it.

If our application was initiating the shutdown then we would expect to see SSL_shutdown(3) give a return value of 0, and then we would continue to call it until we received a return value of 1 (meaning we have successfully completed the shutdown). In this particular example we don't expect SSL_shutdown() to return 0 because we have already received EOF from the server indicating that it has shutdown already. So we just keep calling it until SSL_shutdown() returns 1. Since we are using a nonblocking socket we might expect to have to retry this operation several times. If SSL_shutdown(3) returns a negative result then we must call SSL_get_error(3) to work out what to do next. We use our handle_io_failure() function that we developed earlier for this:

```
    /*
     * The peer already shutdown gracefully (we know this because of the
     * SSL_ERROR_ZERO_RETURN (i.e. EOF) above). We should do the same back.
     */
    while ((ret = SSL_shutdown(ssl)) != 1) {
        if (ret < 0 && handle_io_failure(ssl, ret) == 1)
            continue; /* Retry */
        /*
         * ret == 0 is unexpected here because that means "we've sent a
         * close_notify and we're waiting for one back". But we already know
         * we got one from the peer because of the SSL_ERROR_ZERO_RETURN
         * (i.e. EOF) above.
         */
        printf("Error shutting down\n");
        goto end; /* Cannot retry: error */
    }
```

### Final clean up
As with the blocking TLS client example, once our connection is finished with we must free it. The steps to do this for this example are the same as for the blocking example, so we won't repeat it here.

## FURTHER READING
See ossl-guide-tls-client-block(7) to read a tutorial on how to write a blocking TLS client. See ossl-guide-quic-client-block(7) to see how to do the same thing for a QUIC client.

## SEE ALSO
ossl-guide-introduction(7), ossl-guide-libraries-introduction(7), ossl-guide-libssl-introduction(7), ossl-guide-tls-introduction(7), ossl-guide-tls-client-block(7), ossl-guide-quic-client-block(7)

## COPYRIGHT
Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.

Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy in the file LICENSE in the source distribution or at <https://www.openssl.org/source/license.html>.

branch: sisyphus


ossl-guide-tls-introduction

title: ossl-guide-tls-introduction(7ossl)

summary: guide\-tls\-introduction

text:
# ossl-guide-tls-introduction(7ossl)

## NAME
ossl-guide-tls-introduction - OpenSSL Guide: An introduction to SSL/TLS in OpenSSL

## INTRODUCTION
This page will provide an introduction to some basic SSL/TLS concepts and background and how it is used within OpenSSL. It assumes that you have a basic understanding of TCP/IP and sockets.

## WHAT IS TLS?
TLS stands for Transport Layer Security. TLS allows applications to securely communicate with each other across a network such that the confidentiality of the information exchanged is protected (i.e. it prevents eavesdroppers from listening in to the communication). Additionally it protects the integrity of the information exchanged to prevent an attacker from changing it. Finally it provides authentication so that one or both parties can be sure that they are talking to who they think they are talking to and not some imposter.

Sometimes TLS is referred to by its predecessor's name SSL (Secure Sockets Layer). OpenSSL dates from a time when the SSL name was still in common use and hence many of the functions and names used by OpenSSL contain the "SSL" abbreviation. Nonetheless OpenSSL contains a fully fledged TLS implementation.

TLS is based on a client/server model. The application that initiates a communication is known as the client. The application that responds to a remotely initiated communication is the server. The term "endpoint" refers to either of the client or the server in a communication. The term "peer" refers to the endpoint at the other side of the communication that we are currently referring to. So if we are currently talking about the client then the peer would be the server.

TLS is a standardised protocol and there are numerous different implementations of it. Due to the standards an OpenSSL client or server is able to communicate seamlessly with an application using some different implementation of TLS. TLS (and its predecessor SSL) have been around for a significant period of time and the protocol has undergone various changes over the years. Consequently there are different versions of the protocol available. TLS includes the ability to perform version negotiation so that the highest protocol version that the client and server share in common is used.

TLS acts as a security layer over some lower level transport protocol. Typically the transport layer will be TCP.

## SSL AND TLS VERSIONS
SSL was initially developed by Netscape Communications and its first publicly released version was SSLv2 in 1995. Note that SSLv1 was never publicly released. SSLv3 came along quickly afterwards in 1996. Subsequently development of the protocol moved to the IETF which released the first version of TLS (TLSv1.0) in 1999 as RFC2246. TLSv1.1 was released in 2006 as RFC4346 and TLSv1.2 came along in 2008 as RFC5246. The most recent version of the standard is TLSv1.3 which was released in 2018 as RFC8446.

Today TLSv1.3 and TLSv1.2 are the most commonly deployed versions of the protocol. The IETF have formally deprecated TLSv1.1 and TLSv1.0, so anything below TLSv1.2 should be avoided since the older protocol versions are susceptible to security problems.

OpenSSL does not support SSLv2 (it was removed in OpenSSL 1.1.0). Support for SSLv3 is available as a compile time option - but it is not built by default. Support for TLSv1.0, TLSv1.1, TLSv1.2 and TLSv1.3 are all available by default in a standard build of OpenSSL. However special run-time configuration is required in order to make TLSv1.0 and TLSv1.1 work successfully.

OpenSSL will always try to negotiate the highest protocol version that it has been configured to support. In most cases this will mean either TLSv1.3 or TLSv1.2 is chosen.

## CERTIFICATES
In order for a client to establish a connection to a server it must authenticate the identity of that server, i.e. it needs to confirm that the server is really the server that it claims to be and not some imposter. In order to do this the server will send to the client a digital certificate (also commonly referred to as an X.509 certificate). The certificate contains various information about the server including its full DNS hostname. Also within the certificate is the server's public key. The server operator will have a private key which is linked to the public key and must not be published.

Along with the certificate the server will also send to the client proof that it knows the private key associated with the public key in the certificate. It does this by digitally signing a message to the client using that private key. The client can verify the signature using the public key from the certificate. If the signature verifies successfully then the client knows that the server is in possession of the correct private key.

The certificate that the server sends will also be signed by a Certificate Authority. The Certificate Authority (commonly known as a CA) is a third party organisation that is responsible for verifying the information in the server's certificate (including its DNS hostname). The CA should only sign the certificate if it has been able to confirm that the server operator does indeed have control of the server associated with its DNS hostname and that the server operator has control of the private key.

In this way, if the client trusts the CA that has signed the server's certificate and it can verify that the server has the right private key then it can trust that the server truly does represent the DNS hostname given in the certificate. The client must also verify that the hostname given in the certificate matches the hostname that it originally sent the request to.

Once all of these checks have been done the client has successfully verified the identify of the server. OpenSSL can perform all of these checks automatically but it must be provided with certain information in order to do so, i.e. the set of CAs that the client trusts as well as the DNS hostname for the server that this client is trying to connect to.

Note that it is common for certificates to be built up into a chain. For example a server's certificate may be signed by a key owned by a an intermediate CA. That intermediate CA also has a certificate containing its public key which is in turn signed by a key owned by a root CA. The client may only trust the root CA, but if the server sends both its own certificate and the certificate for the intermediate CA then the client can still successfully verify the identity of the server. There is a chain of trust between the root CA and the server.

By default it is only the client that authenticates the server using this method. However it is also possible to set things up such that the server additionally authenticates the client. This is known as "client authentication". In this approach the client will still authenticate the server in the same way, but the server will request a certificate from the client. The client sends the server its certificate and the server authenticates it in the same way that the client does.

## TRUSTED CERTIFICATE STORE
The system described above only works if a chain of trust can be built between the set of CAs that the endpoint trusts and the certificate that the peer is using. The endpoint must therefore have a set of certificates for CAs that it trusts before any communication can take place. OpenSSL itself does not provide such a set of certificates. Therefore you will need to make sure you have them before you start if you are going to be verifying certificates (i.e. always if the endpoint is a client, and only if client authentication is in use for a server).

Fortunately other organisations do maintain such a set of certificates. If you have obtained your copy of OpenSSL from an Operating System (OS) vendor (e.g. a Linux distribution) then normally the set of CA certificates will also be distributed with that copy.

You can check this by running the OpenSSL command line application like this:

```
 openssl version -d
```

This will display a value for OPENSSLDIR. Look in the certs sub directory of OPENSSLDIR and check its contents. For example if OPENSSLDIR is "/usr/local/ssl", then check the contents of the "/usr/local/ssl/certs" directory.

You are expecting to see a list of files, typically with the suffix ".pem" or ".0". If they exist then you already have a suitable trusted certificate store.

If you are running your version of OpenSSL on Windows then OpenSSL (from version 3.2 onwards) will use the default Windows set of trusted CAs.

If you have built your version of OpenSSL from source, or obtained it from some other location and it does not have a set of trusted CA certificates then you will have to obtain them yourself. One such source is the Curl project. See the page <https://curl.se/docs/caextract.html> where you can download trusted certificates in a single file. Rename the file to "cert.pem" and store it directly in OPENSSLDIR. For example if OPENSSLDIR is "/usr/local/ssl", then save it as "/usr/local/ssl/cert.pem".

You can also use environment variables to override the default location that OpenSSL will look for its trusted certificate store. Set the SSL_CERT_PATH environment variable to give the directory where OpenSSL should looks for its certificates or the SSL_CERT_FILE environment variable to give the name of a single file containing all of the certificates. See openssl-env(7) for further details about OpenSSL environment variables. For example you could use this capability to have multiple versions of OpenSSL all installed on the same system using different values for OPENSSLDIR but all using the same trusted certificate store.

You can test that your trusted certificate store is setup correctly by using it via the OpenSSL command line. Use the following command to connect to a TLS server:

```
 openssl s_client www.openssl.org:443
```

Once the command has connected type the letter "Q" followed by "<enter>" to exit the session. This will print a lot of information on the screen about the connection. Look for a block of text like this:

```
 SSL handshake has read 4584 bytes and written 403 bytes
 Verification: OK
```

Hopefully if everything has worked then the "Verification" line will say "OK". If its not working as expected then you might see output like this instead:

```
 SSL handshake has read 4584 bytes and written 403 bytes
 Verification error: unable to get local issuer certificate
```

The "unable to get local issuer certificate" error means that OpenSSL has been unable to find a trusted CA for the chain of certificates provided by the server in its trusted certificate store. Check your trusted certificate store configuration again.

Note that s_client is a testing tool and will still allow you to connect to the TLS server regardless of the verification error. Most applications should not do this and should abort the connection in the event of a verification error.

## IMPORTANT OBJECTS FOR AN OPENSSL TLS APPLICATION
A TLS connection is represented by the SSL object in an OpenSSL based application. Once a connection with a remote peer has been established an endpoint can "write" data to the SSL object to send data to the peer, or "read" data from it to receive data from the server.

A new SSL object is created from an SSL_CTX object. Think of an SSL_CTX as a "factory" for creating SSL objects. You can create a single SSL_CTX object and then create multiple connections (i.e. SSL objects) from it. Typically you can set up common configuration options on the SSL_CTX so that all the SSL object created from it inherit the same configuration options.

Note that internally to OpenSSL various items that are shared between multiple SSL objects are cached in the SSL_CTX for performance reasons. Therefore it is considered best practice to create one SSL_CTX for use by multiple SSL objects instead of having one SSL_CTX for each SSL object that you create.

Each SSL object is also associated with two BIO objects. A BIO object is used for sending or receiving data from the underlying transport layer. For example you might create a BIO to represent a TCP socket. The SSL object uses one BIO for reading data and one BIO for writing data. In most cases you would use the same BIO for each direction but there could be some circumstances where you want them to be different.

It is up to the application programmer to create the BIO objects that are needed and supply them to the SSL object. See ossl-guide-tls-client-block(7) and ossl-guide-tls-server-block(7) for usage examples.

Finally, an endpoint can establish a "session" with its peer. The session holds various TLS parameters about the connection between the client and the server. The session details can then be reused in a subsequent connection attempt to speed up the process of connecting. This is known as "resumption". Sessions are represented in OpenSSL by the SSL_SESSION object. In TLSv1.2 there is always exactly one session per connection. In TLSv1.3 there can be any number per connection including none.

## PHASES OF A TLS CONNECTION
A TLS connection starts with an initial "set up" phase. The endpoint creates the SSL_CTX (if one has not already been created) and configures it.

A client then creates an SSL object to represent the new TLS connection. Any connection specific configuration parameters are then applied and the underlying socket is created and associated with the SSL via BIO objects.

A server will create a socket for listening for incoming connection attempts from clients. Once a connection attempt is made the server will create an SSL object in the same way as for a client and associate it with a BIO for the newly created incoming socket.

After set up is complete the TLS "handshake" phase begins. A TLS handshake consists of the client and server exchanging a series of TLS handshake messages to establish the connection. The client starts by sending a "ClientHello" handshake message and the server responds with a "ServerHello". The handshake is complete once an endpoint has sent its last message (known as the "Finished" message) and received a Finished message from its peer. Note that this might occur at slightly different times for each peer. For example in TLSv1.3 the server always sends its Finished message before the client. The client later responds with its Finished message. At this point the client has completed the handshake because it has both sent and received a Finished message. The server has sent its Finished message but the Finished message from the client may still be in-flight, so the server is still in the handshake phase. It is even possible that the server will fail to complete the handshake (if it considers there is some problem with the messages sent from the client), even though the client may have already progressed to sending application data. In TLSv1.2 this can happen the other way around, i.e. the server finishes first and the client finishes second.

Once the handshake is complete the application data transfer phase begins. Strictly speaking there are some situations where the client can start sending application data even earlier (using the TLSv1.3 "early data" capability) - but we're going to skip over that for this basic introduction.

During application data transfer the client and server can read and write data to the connection freely. The details of this are typically left to some higher level application protocol (for example HTTP). Not all information exchanged during this phase is application data. Some protocol level messages may still be exchanged - so it is not necessarily the case that, just because the underlying socket is "readable", that application data will be available to read.

When the connection is no longer required then it should be shutdown. A shutdown may be initiated by either the client or the server via a message known as a "close_notify" alert. The client or server that receives a close_notify may respond with one and then the connection is fully closed and application data can no longer be sent or received.

Once shutdown is complete a TLS application must clean up by freeing the SSL object.

## FURTHER READING
See ossl-guide-tls-client-block(7) for an example of how to apply these concepts in order to write a simple TLS client based on a blocking socket. See ossl-guide-tls-server-block(7) for an example of how to apply these concepts in order to write a simple TLS server handling one client at a time over a blocking socket. See ossl-guide-quic-introduction(7) for an introduction to QUIC in OpenSSL.

## SEE ALSO
ossl-guide-introduction(7), ossl-guide-libraries-introduction(7), ossl-guide-libssl-introduction(7), ossl-guide-tls-client-block(7), ossl-guide-tls-server-block(7), ossl-guide-quic-introduction(7)

## COPYRIGHT
Copyright 2023-2025 The OpenSSL Project Authors. All Rights Reserved.

Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy in the file LICENSE in the source distribution or at <https://www.openssl.org/source/license.html>.


ossl-guide-tls-server-block

title: ossl-guide-tls-server-block(7ossl)

summary: guide\-tls\-server\-block

text:
# ossl-guide-tls-server-block(7ossl)

## NAME
ossl-guide-tls-server-block - OpenSSL Guide: Writing a simple blocking TLS server

## SIMPLE BLOCKING TLS SERVER EXAMPLE
This page will present various source code samples demonstrating how to write a simple, non-concurrent, TLS "echo" server application which accepts one client connection at a time, echoing input from the client back to the same client. Once the current client disconnects, the next client connection is accepted.

Both the acceptor socket and client connections are "blocking". A more typical server might use nonblocking sockets with an event loop and callbacks for I/O events.

The complete source code for this example blocking TLS server is available in the demos/guide directory of the OpenSSL source distribution in the file tls-server-block.c. It is also available online at <https://github.com/openssl/openssl/blob/master/demos/guide/tls-server-block.c>.

We assume that you already have OpenSSL installed on your system; that you already have some fundamental understanding of OpenSSL concepts and TLS (see ossl-guide-libraries-introduction(7) and ossl-guide-tls-introduction(7)); and that you know how to write and build C code and link it against the libcrypto and libssl libraries that are provided by OpenSSL. It also assumes that you have a basic understanding of TCP/IP and sockets.

### Creating the SSL_CTX and SSL objects
The first step is to create an SSL_CTX object for our server. We use the SSL_CTX_new(3) function for this purpose. We could alternatively use SSL_CTX_new_ex(3) if we want to associate the SSL_CTX with a particular OSSL_LIB_CTX (see ossl-guide-libraries-introduction(7) to learn about OSSL_LIB_CTX). We pass as an argument the return value of the function TLS_server_method(3). You should use this method whenever you are writing a TLS server. This method will automatically use TLS version negotiation to select the highest version of the protocol that is mutually supported by both the server and the client.

```
    /*
     * An SSL_CTX holds shared configuration information for multiple
     * subsequent per-client SSL connections.
     */
    ctx = SSL_CTX_new(TLS_server_method());
    if (ctx == NULL) {
        ERR_print_errors_fp(stderr);
        errx(res, "Failed to create server SSL_CTX");
    }
```

We would also like to restrict the TLS versions that we are willing to accept to TLSv1.2 or above. TLS protocol versions earlier than that are generally to be avoided where possible. We can do that using SSL_CTX_set_min_proto_version(3):

```
    /*
     * TLS versions older than TLS 1.2 are deprecated by IETF and SHOULD
     * be avoided if possible.
     */
    if (!SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION)) {
        SSL_CTX_free(ctx);
        ERR_print_errors_fp(stderr);
        errx(res, "Failed to set the minimum TLS protocol version");
    }
```

Next we configure some option flags, see SSL_CTX_set_options(3) for details:

```
    /*
     * Tolerate clients hanging up without a TLS "shutdown".  Appropriate in all
     * application protocols which perform their own message "framing", and
     * don't rely on TLS to defend against "truncation" attacks.
     */
    opts = SSL_OP_IGNORE_UNEXPECTED_EOF;
    /*
     * Block potential CPU-exhaustion attacks by clients that request frequent
     * renegotiation.  This is of course only effective if there are existing
     * limits on initial full TLS handshake or connection rates.
     */
    opts |= SSL_OP_NO_RENEGOTIATION;
    /*
     * Most servers elect to use their own cipher preference rather than that of
     * the client.
     */
    opts |= SSL_OP_CIPHER_SERVER_PREFERENCE;
    /* Apply the selection options */
    SSL_CTX_set_options(ctx, opts);
```

Servers need a private key and certificate. Though anonymous ciphers (no server certificate) are possible in TLS 1.2, they are rarely applicable, and are not currently defined for TLS 1.3. Additional intermediate issuer CA certificates are often also required, and both the server (end-entity or EE) certificate and the issuer ("chain") certificates are most easily configured in a single "chain file". Below we load such a chain file (the EE certificate must appear first), and then load the corresponding private key, checking that it matches the server certificate. No checks are performed to check the integrity of the chain (CA signatures or certificate expiration dates, for example).

```
    /*
     * Load the server's certificate *chain* file (PEM format), which includes
     * not only the leaf (end-entity) server certificate, but also any
     * intermediate issuer-CA certificates.  The leaf certificate must be the
     * first certificate in the file.
     *
     * In advanced use-cases this can be called multiple times, once per public
     * key algorithm for which the server has a corresponding certificate.
     * However, the corresponding private key (see below) must be loaded first,
     * *before* moving on to the next chain file.
     */
    if (SSL_CTX_use_certificate_chain_file(ctx, "chain.pem") <= 0) {
        SSL_CTX_free(ctx);
        ERR_print_errors_fp(stderr);
        errx(res, "Failed to load the server certificate chain file");
    }
    /*
     * Load the corresponding private key, this also checks that the private
     * key matches the just loaded end-entity certificate.  It does not check
     * whether the certificate chain is valid, the certificates could be
     * expired, or may otherwise fail to form a chain that a client can validate.
     */
    if (SSL_CTX_use_PrivateKey_file(ctx, "pkey.pem", SSL_FILETYPE_PEM) <= 0) {
        SSL_CTX_free(ctx);
        ERR_print_errors_fp(stderr);
        errx(res, "Error loading the server private key file, "
                  "possible key/cert mismatch???");
    }
```

Next we enable session caching, which makes it possible for clients to more efficiently make additional TLS connections after completing an initial full TLS handshake. With TLS 1.3, session resumption typically still performs a fresh key agreement, but the certificate exchange is avoided.

```
    /*
     * Servers that want to enable session resumption must specify a cache id
     * byte array, that identifies the server application, and reduces the
     * chance of inappropriate cache sharing.
     */
    SSL_CTX_set_session_id_context(ctx, (void *)cache_id, sizeof(cache_id));
    SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER);
    /*
     * How many client TLS sessions to cache.  The default is
     * SSL_SESSION_CACHE_MAX_SIZE_DEFAULT (20k in recent OpenSSL versions),
     * which may be too small or too large.
     */
    SSL_CTX_sess_set_cache_size(ctx, 1024);
    /*
     * Sessions older than this are considered a cache miss even if still in
     * the cache.  The default is two hours.  Busy servers whose clients make
     * many connections in a short burst may want a shorter timeout, on lightly
     * loaded servers with sporadic connections from any given client, a longer
     * time may be appropriate.
     */
    SSL_CTX_set_timeout(ctx, 3600);
```

Most servers, including this one, do not solicit client certificates. We therefore do not need a "trust store" and allow the handshake to complete even when the client does not present a certificate. Note: Even if a client did present a trusted ceritificate, for it to be useful, the server application would still need custom code to use the verified identity to grant nondefault access to that particular client. Some servers grant access to all clients with certificates from a private CA, this then requires processing of certificate revocation lists to deauthorise a client. It is often simpler and more secure to instead keep a list of authorised public keys.

Though this is the default setting, we explicitly call the SSL_CTX_set_verify(3) function and pass the SSL_VERIFY_NONE value to it. The final argument to this function is a callback that you can optionally supply to override the default handling for certificate verification. Most applications do not need to do this so this can safely be set to NULL to get the default handling.

```
    /*
     * Clients rarely employ certificate-based authentication, and so we don't
     * require "mutual" TLS authentication (indeed there's no way to know
     * whether or how the client authenticated the server, so the term "mutual"
     * is potentially misleading).
     *
     * Since we're not soliciting or processing client certificates, we don't
     * need to configure a trusted-certificate store, so no call to
     * SSL_CTX_set_default_verify_paths() is needed.  The server's own
     * certificate chain is assumed valid.
     */
    SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
```

That is all the setup that we need to do for the SSL_CTX. Next we create an acceptor BIO on which to accept client connections. This just records the intended port (and optional "host:" prefix), without actually creating the socket. This delayed processing allows the programmer to specify additional behaviours before the listening socket is actually created.

```
    /*
     * Create a listener socket wrapped in a BIO.
     * The first call to BIO_do_accept() initialises the socket
     */
    acceptor_bio = BIO_new_accept(hostport);
    if (acceptor_bio == NULL) {
        SSL_CTX_free(ctx);
        ERR_print_errors_fp(stderr);
        errx(res, "Error creating acceptor bio");
    }
```

Servers almost always want to use the "SO_REUSEADDR" option to avoid startup failures if there are still lingering client connections, so we do that before making the first call to BIO_do_accept(3) which creates the listening socket, without accepting a client connection. Subsequent calls to the same function will accept new connections.

```
    BIO_set_bind_mode(acceptor_bio, BIO_BIND_REUSEADDR);
    if (BIO_do_accept(acceptor_bio) <= 0) {
        SSL_CTX_free(ctx);
        ERR_print_errors_fp(stderr);
        errx(res, "Error setting up acceptor socket");
    }
```

### Server loop
The server now enters a "forever" loop handling one client connection at a time. Before each connection we clear the OpenSSL error stack, so that any error reports are related to just the new connection.

```
    /* Pristine error stack for each new connection */
    ERR_clear_error();
```

At this point the server blocks to accept the next client:

```
    /* Wait for the next client to connect */
    if (BIO_do_accept(acceptor_bio) <= 0) {
        /* Client went away before we accepted the connection */
        continue;
    }
```

On success the accepted client connection has been wrapped in a fresh BIO and pushed onto the end of the acceptor BIO chain. We pop it off returning the acceptor BIO to its initial state.

```
    /* Pop the client connection from the BIO chain */
    client_bio = BIO_pop(acceptor_bio);
    fprintf(stderr, "New client connection accepted\n");
```

Next, we create an SSL object by calling the SSL_new(3) function and passing the SSL_CTX we created as an argument. The client connection BIO is configured as the I/O conduit for this SSL handle. SSL_set_bio transfers ownership of the BIO or BIOs involved (our client_bio) to the SSL handle.

```
    /* Associate a new SSL handle with the new connection */
    if ((ssl = SSL_new(ctx)) == NULL) {
        ERR_print_errors_fp(stderr);
        warnx("Error creating SSL handle for new connection");
        BIO_free(client_bio);
        continue;
    }
    SSL_set_bio(ssl, client_bio, client_bio);
```

And now we're ready to attempt the SSL handshake. With a blocking socket OpenSSL will perform all the read and write operations required to complete the handshake (or detect and report a failure) before returning.

```
    /* Attempt an SSL handshake with the client */
    if (SSL_accept(ssl) <= 0) {
        ERR_print_errors_fp(stderr);
        warnx("Error performing SSL handshake with client");
        SSL_free(ssl);
        continue;
    }
```

With the handshake complete, the server loops echoing client input back to the client:

```
    while (SSL_read_ex(ssl, buf, sizeof(buf), &nread) > 0) {
        if (SSL_write_ex(ssl, buf, nread, &nwritten) > 0 &&
            nwritten == nread) {
            total += nwritten;
            continue;
        }
        warnx("Error echoing client input");
        break;
    }
```

Once the client closes its connection, we report the number of bytes sent to stderr and free the SSL handle, which also frees the client_bio and closes the underlying socket.

```
    fprintf(stderr, "Client connection closed, %zu bytes sent\n", total);
    SSL_free(ssl);
```

The server is now ready to accept the next client connection.

### Final clean up
If the server could somehow manage to break out of the infinite loop, and be ready to exit, it would first deallocate the constructed SSL_CTX.

```
    /*
     * Unreachable placeholder cleanup code, the above loop runs forever.
     */
    SSL_CTX_free(ctx);
    return EXIT_SUCCESS;
```

## SEE ALSO
ossl-guide-introduction(7), ossl-guide-libraries-introduction(7), ossl-guide-libssl-introduction(7), ossl-guide-tls-introduction(7), ossl-guide-tls-client-non-block(7), ossl-guide-quic-client-block(7)

## COPYRIGHT
Copyright 2024 The OpenSSL Project Authors. All Rights Reserved.

Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy in the file LICENSE in the source distribution or at <https://www.openssl.org/source/license.html>.


title: ossl_store(7ossl)

summary: Store retrieval functions

text:
# ossl_store(7ossl)

## NAME
ossl_store - Store retrieval functions

## SYNOPSIS
\#include <openssl/store.h>

## DESCRIPTION

### General
A STORE is a layer of functionality to retrieve a number of supported objects from a repository of any kind, addressable as a filename or as a URI.

The functionality supports the pattern "open a channel to the repository", "loop and retrieve one object at a time", and "finish up by closing the channel".

The retrieved objects are returned as a wrapper type OSSL_STORE_INFO, from which an OpenSSL type can be retrieved.

### URI schemes and loaders
Support for a URI scheme is called a STORE "loader", and can be added dynamically from the calling application or from a loadable engine.

Support for the 'file' scheme is built into "libcrypto". See ossl_store-file(7) for more information.

### UI_METHOD and pass phrases
The OSS_STORE API does nothing to enforce any specific format or encoding on the pass phrase that the UI_METHOD provides. However, the pass phrase is expected to be UTF-8 encoded. The result of any other encoding is undefined.

## EXAMPLES

### A generic call

```
 #include <openssl/ui.h> /* for UI_get_default_method */
 #include <openssl/store.h>
 OSSL_STORE_CTX *ctx = OSSL_STORE_open("file:/foo/bar/data.pem",
                        UI_get_default_method(), NULL, NULL, NULL);
 /*
  * OSSL_STORE_eof() simulates file semantics for any repository to signal
  * that no more data can be expected
  */
 while (!OSSL_STORE_eof(ctx)) {
     OSSL_STORE_INFO *info = OSSL_STORE_load(ctx);
     /*
      * Do whatever is necessary with the OSSL_STORE_INFO,
      * here just one example
      */
     switch (OSSL_STORE_INFO_get_type(info)) {
     case OSSL_STORE_INFO_CERT:
         /* Print the X.509 certificate text */
         X509_print_fp(stdout, OSSL_STORE_INFO_get0_CERT(info));
         /* Print the X.509 certificate PEM output */
         PEM_write_X509(stdout, OSSL_STORE_INFO_get0_CERT(info));
         break;
     }
     OSSL_STORE_INFO_free(info);
 }
 OSSL_STORE_close(ctx);
```

## SEE ALSO
OSSL_STORE_INFO(3), OSSL_STORE_LOADER(3), OSSL_STORE_open(3), OSSL_STORE_expect(3), OSSL_STORE_SEARCH(3)

## COPYRIGHT
Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved.

Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy in the file LICENSE in the source distribution or at <https://www.openssl.org/source/license.html>.


title: ossl_store-file(7ossl)

summary: The store \*(Aqfile\*(Aq scheme loader

text:
# ossl_store-file(7ossl)

## NAME
ossl_store-file - The store 'file' scheme loader

## SYNOPSIS
\#include <openssl/store.h>

## DESCRIPTION
Support for the 'file' scheme is built into "libcrypto". Since files come in all kinds of formats and content types, the 'file' scheme has its own layer of functionality called "file handlers", which are used to try to decode diverse types of file contents.

In case a file is formatted as PEM, each called file handler receives the PEM name (everything following any '"-----BEGIN "') as well as possible PEM headers, together with the decoded PEM body. Since PEM formatted files can contain more than one object, the file handlers are called upon for each such object.

If the file isn't determined to be formatted as PEM, the content is loaded in raw form in its entirety and passed to the available file handlers as is, with no PEM name or headers.

Each file handler is expected to handle PEM and non-PEM content as appropriate. Some may refuse non-PEM content for the sake of determinism (for example, there are keys out in the wild that are represented as an ASN.1 OCTET STRING. In raw form, it's not easily possible to distinguish those from any other data coming as an ASN.1 OCTET STRING, so such keys would naturally be accepted as PEM files only).

## NOTES
When needed, the 'file' scheme loader will require a pass phrase by using the UI_METHOD that was passed via OSSL_STORE_open(). This pass phrase is expected to be UTF-8 encoded, anything else will give an undefined result. The files made accessible through this loader are expected to be standard compliant with regards to pass phrase encoding. Files that aren't should be re-generated with a correctly encoded pass phrase. See passphrase-encoding(7) for more information.

## SEE ALSO
ossl_store(7), passphrase-encoding(7)

## COPYRIGHT
Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.

Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy in the file LICENSE in the source distribution or at <https://www.openssl.org/source/license.html>.


passphrase-encoding

title: passphrase-encoding(7ossl)

summary: encoding

text:
# passphrase-encoding(7ossl)

## NAME
passphrase-encoding - How diverse parts of OpenSSL treat pass phrases character encoding

## DESCRIPTION
In a modern world with all sorts of character encodings, the treatment of pass phrases has become increasingly complex. This manual page attempts to give an overview over how this problem is currently addressed in different parts of the OpenSSL library.

### The general case
The OpenSSL library doesn't treat pass phrases in any special way as a general rule, and trusts the application or user to choose a suitable character set and stick to that throughout the lifetime of affected objects. This means that for an object that was encrypted using a pass phrase encoded in ISO-8859-1, that object needs to be decrypted using a pass phrase encoded in ISO-8859-1. Using the wrong encoding is expected to cause a decryption failure.

### PKCS#12
PKCS#12 is a bit different regarding pass phrase encoding. The standard stipulates that the pass phrase shall be encoded as an ASN.1 BMPString, which consists of the code points of the basic multilingual plane, encoded in big endian (UCS-2 BE).

OpenSSL tries to adapt to this requirements in one of the following manners:

1.

Treats the received pass phrase as UTF-8 encoded and tries to re-encode it to UTF-16 (which is the same as UCS-2 for characters U+0000 to U+D7FF and U+E000 to U+FFFF, but becomes an expansion for any other character), or failing that, proceeds with step 2.

2.

Assumes that the pass phrase is encoded in ASCII or ISO-8859-1 and opportunistically prepends each byte with a zero byte to obtain the UCS-2 encoding of the characters, which it stores as a BMPString. Note that since there is no check of your locale, this may produce UCS-2 / UTF-16 characters that do not correspond to the original pass phrase characters for other character sets, such as any ISO-8859-X encoding other than ISO-8859-1 (or for Windows, CP 1252 with exception for the extra "graphical" characters in the 0x80-0x9F range).

OpenSSL versions older than 1.1.0 do variant 2 only, and that is the reason why OpenSSL still does this, to be able to read files produced with older versions.

It should be noted that this approach isn't entirely fault free.

A pass phrase encoded in ISO-8859-2 could very well have a sequence such as 0xC3 0xAF (which is the two characters "LATIN CAPITAL LETTER A WITH BREVE" and "LATIN CAPITAL LETTER Z WITH DOT ABOVE" in ISO-8859-2 encoding), but would be misinterpreted as the perfectly valid UTF-8 encoded code point U+00EF (LATIN SMALL LETTER I WITH DIAERESIS) if the pass phrase doesn't contain anything that would be invalid UTF-8. A pass phrase that contains this kind of byte sequence will give a different outcome in OpenSSL 1.1.0 and newer than in OpenSSL older than 1.1.0.

```
 0x00 0xC3 0x00 0xAF                    # OpenSSL older than 1.1.0
 0x00 0xEF                              # OpenSSL 1.1.0 and newer
```

On the same accord, anything encoded in UTF-8 that was given to OpenSSL older than 1.1.0 was misinterpreted as ISO-8859-1 sequences.

### OSSL_STORE
ossl_store(7) acts as a general interface to access all kinds of objects, potentially protected with a pass phrase, a PIN or something else. This API stipulates that pass phrases should be UTF-8 encoded, and that any other pass phrase encoding may give undefined results. This API relies on the application to ensure UTF-8 encoding, and doesn't check that this is the case, so what it gets, it will also pass to the underlying loader.

## RECOMMENDATIONS
This section assumes that you know what pass phrase was used for encryption, but that it may have been encoded in a different character encoding than the one used by your current input method. For example, the pass phrase may have been used at a time when your default encoding was ISO-8859-1 (i.e. "naïve" resulting in the byte sequence 0x6E 0x61 0xEF 0x76 0x65), and you're now in an environment where your default encoding is UTF-8 (i.e. "naïve" resulting in the byte sequence 0x6E 0x61 0xC3 0xAF 0x76 0x65). Whenever it's mentioned that you should use a certain character encoding, it should be understood that you either change the input method to use the mentioned encoding when you type in your pass phrase, or use some suitable tool to convert your pass phrase from your default encoding to the target encoding.

Also note that the sub-sections below discuss human readable pass phrases. This is particularly relevant for PKCS#12 objects, where human readable pass phrases are assumed. For other objects, it's as legitimate to use any byte sequence (such as a sequence of bytes from /dev/urandom that's been saved away), which makes any character encoding discussion irrelevant; in such cases, simply use the same byte sequence as it is.

### Creating new objects
For creating new pass phrase protected objects, make sure the pass phrase is encoded using UTF-8. This is default on most modern Unixes, but may involve an effort on other platforms. Specifically for Windows, setting the environment variable OPENSSL_WIN32_UTF8 will have anything entered on [Windows] console prompt converted to UTF-8 (command line and separately prompted pass phrases alike).

### Opening existing objects
For opening pass phrase protected objects where you know what character encoding was used for the encryption pass phrase, make sure to use the same encoding again.

For opening pass phrase protected objects where the character encoding that was used is unknown, or where the producing application is unknown, try one of the following:

1.

Try the pass phrase that you have as it is in the character encoding of your environment. It's possible that its byte sequence is exactly right.

2.

Convert the pass phrase to UTF-8 and try with the result. Specifically with PKCS#12, this should open up any object that was created according to the specification.

3.

Do a naïve (i.e. purely mathematical) ISO-8859-1 to UTF-8 conversion and try with the result. This differs from the previous attempt because ISO-8859-1 maps directly to U+0000 to U+00FF, which other non-UTF-8 character sets do not. This also takes care of the case when a UTF-8 encoded string was used with OpenSSL older than 1.1.0. (for example, "ï", which is 0xC3 0xAF when encoded in UTF-8, would become 0xC3 0x83 0xC2 0xAF when re-encoded in the naïve manner. The conversion to BMPString would then yield 0x00 0xC3 0x00 0xA4 0x00 0x00, the erroneous/non-compliant encoding used by OpenSSL older than 1.1.0)

## SEE ALSO
evp(7), ossl_store(7), EVP_BytesToKey(3), EVP_DecryptInit(3), PEM_do_header(3), PKCS12_parse(3), PKCS12_newpass(3), d2i_PKCS8PrivateKey_bio(3)

## COPYRIGHT
Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.

Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy in the file LICENSE in the source distribution or at <https://www.openssl.org/source/license.html>.


property

title: property(7ossl)

text:
# property(7ossl)

## NAME
property - Properties, a selection mechanism for algorithm implementations

## DESCRIPTION
As of OpenSSL 3.0, a new method has been introduced to decide which of multiple implementations of an algorithm will be used. The method is centered around the concept of properties. Each implementation defines a number of properties and when an algorithm is being selected, filters based on these properties can be used to choose the most appropriate implementation of the algorithm.

Properties are like variables, they are referenced by name and have a value assigned.

### Property Names
Property names fall into two categories: those reserved by the OpenSSL project and user defined names. A reserved property name consists of a single C-style identifier (except for leading underscores not being permitted), which begins with a letter and can be followed by any number of letters, numbers and underscores. Property names are case-insensitive, but OpenSSL will only use lowercase letters.

A user defined property name is similar, but it must consist of two or more C-style identifiers, separated by periods. The last identifier in the name can be considered the 'true' property name, which is prefixed by some sort of 'namespace'. Providers for example could include their name in the prefix and use property names like

```
  <provider_name>.<property_name>
  <provider_name>.<algorithm_name>.<property_name>
```

### Properties
A property is a name=value pair. A property definition is a sequence of comma separated properties. There can be any number of properties in a definition, however each name must be unique. For example: "" defines an empty property definition (i.e., no restriction); "my.foo=bar" defines a property named my.foo which has a string value bar and "iteration.count=3" defines a property named iteration.count which has a numeric value of 3. The full syntax for property definitions appears below.

### Implementations
Each implementation of an algorithm can define any number of properties. For example, the default provider defines the property provider=default for all of its algorithms. Likewise, OpenSSL's FIPS provider defines provider=fips and the legacy provider defines provider=legacy for all of their algorithms.

### Queries
A property query clause is a single conditional test. For example, "fips=yes", "provider!=default" or "?iteration.count=3". The first two represent mandatory clauses, such clauses must match for any algorithm to even be under consideration. The third clause represents an optional clause. Matching such clauses is not a requirement, but any additional optional match counts in favor of the algorithm. More details about that in the Lookups section. A property query is a sequence of comma separated property query clauses. It is an error if a property name appears in more than one query clause. The full syntax for property queries appears below, but the available syntactic features are:

- = is an infix operator providing an equality test.

- != is an infix operator providing an inequality test.

- ? is a prefix operator that means that the following clause is optional but preferred.

- - is a prefix operator that means any global query clause involving the following property name should be ignored.

- "..." is a quoted string. The quotes are not included in the body of the string.

- '...' is a quoted string. The quotes are not included in the body of the string.

### Lookups
When an algorithm is looked up, a property query is used to determine the best matching algorithm. All mandatory query clauses must be present and the implementation that additionally has the largest number of matching optional query clauses will be used. If there is more than one such optimal candidate, the result will be chosen from amongst those in an indeterminate way. Ordering of optional clauses is not significant.

### Shortcut
In order to permit a more concise expression of boolean properties, there is one short cut: a property name alone (e.g. "my.property") is exactly equivalent to "my.property=yes" in both definitions and queries.

### Global and Local
Two levels of property query are supported. A context based property query that applies to all fetch operations and a local property query. Where both the context and local queries include a clause with the same name, the local clause overrides the context clause.

It is possible for a local property query to remove a clause in the context property query by preceding the property name with a '-'. For example, a context property query that contains "fips=yes" would normally result in implementations that have "fips=yes".

However, if the setting of the "fips" property is irrelevant to the operations being performed, the local property query can include the clause "-fips". Note that the local property query could not use "fips=no" because that would disallow any implementations with "fips=yes" rather than not caring about the setting.

## SYNTAX
The lexical syntax in EBNF is given by:

```
 Definition     ::= PropertyName ( '=' Value )?
                        ( ',' PropertyName ( '=' Value )? )*
 Query          ::= PropertyQuery ( ',' PropertyQuery )*
 PropertyQuery  ::= '-' PropertyName
                  | '?'? ( PropertyName (( '=' | '!=' ) Value)?)
 Value          ::= NumberLiteral | StringLiteral
 StringLiteral  ::= QuotedString | UnquotedString
 QuotedString   ::= '"' [^"]* '"' | "'" [^']* "'"
 UnquotedString ::= [A-Za-z] [^{space},]+
 NumberLiteral  ::= '0' ( [0-7]* | 'x' [0-9A-Fa-f]+ ) | '-'? [1-9] [0-9]+
 PropertyName   ::= [A-Za-z] [A-Za-z0-9_]* ( '.' [A-Za-z] [A-Za-z0-9_]* )*
```

The flavour of EBNF being used is defined by: <https://www.w3.org/TR/2010/REC-xquery-20101214/#EBNFNotation>.

## HISTORY
Properties were added in OpenSSL 3.0

## COPYRIGHT
Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.

Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy in the file LICENSE in the source distribution or at <https://www.openssl.org/source/license.html>.