> For the complete documentation index, see [llms.txt](https://book.bsdcn.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://book.bsdcn.org/ask/flat/chapter-29-security/di-29.5-jie-openssl.md).

# 29.5 OpenSSL

OpenSSL 3 has been included in the base system since FreeBSD 14, introducing the provider module architecture. This section covers self-signed certificate generation (self-signed CA), FIPS compliance configuration (fips\_module integrity check and openssl fipsinstall), and loading of deprecated algorithms.

## Overview

OpenSSL is a cryptographic toolkit that implements the Secure Sockets Layer (SSL) and Transport Layer Security (TLS) network protocols, and provides a rich set of cryptographic routines.

The `openssl` program is the command-line entry point to this toolkit, allowing users to invoke various functions of the OpenSSL cryptographic library from the shell, including:

* Creation and management of private keys, public keys, and parameters
* Public key cryptographic operations
* Creation of X.509 certificates, CSRs, and CRLs
* Computation of message digests and message authentication codes
* Encryption and decryption using ciphers
* SSL/TLS client and server testing
* S/MIME signed or encrypted email processing
* Timestamp request, generation, and verification
* Performance testing of cryptographic routines

For more information, refer to the free [OpenSSL Cookbook](https://www.feistyduck.com/books/openssl-cookbook/).

## Generating Certificates

OpenSSL supports generating certificates that can be submitted to a CA for signing or used independently. Specifically:

### Certificate Signing Request Requiring CA Signing

Execute openssl with the following parameters to generate a certificate for CA signing:

```sh
# openssl req -new -noenc -out req.pem -keyout cert.key -sha512 -newkey rsa:4096
```

Explanation of command options:

| Option             | Explanation                                                                                    |
| ------------------ | ---------------------------------------------------------------------------------------------- |
| `openssl req`      | Generate a Certificate Signing Request (CSR)                                                   |
| `-new`             | Create a new certificate signing request                                                       |
| `-noenc`           | Do not set a password for the private key; the generated private key will not be encrypted     |
| `-out req.pem`     | Specify the output filename for the generated certificate signing request file, here `req.pem` |
| `-keyout cert.key` | Specify the output path for the generated private key file, here `cert.key`                    |
| `-sha512`          | Use the SHA-512 hash algorithm for the hash computation of the signing request                 |
| `-newkey rsa:4096` | Generate a new RSA key pair using 4096-bit RSA encryption algorithm                            |

The output should resemble the following:

```
...+......+.......+.....+.+.....+....+...+..+++++++++++++++++++++++++++++++++++++++++++++*.........+++++++++++++++++++++++++++++++++++++++++++++*..+................+....+......+.....+++++

......some output omitted......

-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:CN # Two-letter country/region code
State or Province Name (full name) [Some-State]:Beijing      # State or province
Locality Name (eg, city) []:Beijing  # City
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Chinese FreeBSD Community (CFC) # Organization name
Organizational Unit Name (eg, section) []:Systems Administrator      # Organizational unit name
Common Name (e.g. server FQDN or YOUR name) []:bsdcn.org # Common name
Email Address []:ykla@bsdcn.org      # Email address

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:1234 # Password must be at least four digits
An optional company name []:1234
```

The above command generates a Certificate Signing Request (CSR), which **must be submitted to a CA for signing before a certificate can be obtained**.

This command creates two files in the current directory:

```sh
req.pem              cert.key
```

Submit the certificate request file **req.pem** to a CA, which will verify the credentials, sign it, and return the signed certificate;

The other file **cert.key** is the certificate private key, which must be kept secure. If the private key is leaked, others can impersonate the user or server.

### Self-Signed Certificate

If CA signing is not required, you can create a self-signed certificate yourself.

> **Warning**
>
> The following command writes the certificate and private key directly to the `/etc/ssl/` system directory. If certificate files already exist at that path, they will be overwritten and cannot be recovered. Please back up existing certificates first.

Execute the following command to generate an X.509 format self-signed certificate:

```sh
# openssl req -new -x509 -days 365 -sha512 -newkey rsa:4096 -keyout /etc/ssl/cert.key -out /etc/ssl/certs/cert.crt
```

The output should resemble the following:

```
.+.+...........+.........+......+...+....+..+.+...+..+.........+...+...+............+.......+.....+...+............+.+..+.+............+..+...+....+.........+.....+++++++++++++++++++++++++++++++++++++++++++++*............+...+...+....+.....+++++++++++++++++++++++++++++++++++++++++++++*.....

......some output omitted......

Enter PEM pass phrase: # Set password
Verifying - Enter PEM pass phrase: # Re-enter password
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:Beijing
Locality Name (eg, city) []:Beijing
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Chinese FreeBSD Community (CFC)
Organizational Unit Name (eg, section) []:Systems Administrator
Common Name (e.g. server FQDN or YOUR name) []:bsdcn.org
Email Address []:ykla@bsdcn.org
```

This command creates the certificate file **cert.crt** in the **/etc/ssl/certs** directory.

```sh
-rw-r--r--  1 root wheel 2228 May 22 13:18 /etc/ssl/certs/cert.crt
```

Run the following command to verify:

```sh
# openssl x509 -in /etc/ssl/certs/cert.crt -text -noout
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            36:78:41:ef:1a:ba:e0:61:85:7e:af:1e:c3:08:58:95:af:5e:95:51
        Signature Algorithm: sha512WithRSAEncryption
        Issuer: C=CN, ST=Beijing, L=Beijing, O=Chinese FreeBSD Community (CFC), OU=Systems Administrator, CN=bsdcn.org, emailAddress=ykla@bsdcn.org
        Validity
            Not Before: May 22 05:18:09 2026 GMT
            Not After : May 22 05:18:09 2027 GMT
        Subject: C=CN, ST=Beijing, L=Beijing, O=Chinese FreeBSD Community (CFC), OU=Systems Administrator, CN=bsdcn.org, emailAddress=ykla@bsdcn.org

......some output omitted......
```

The certificate private key **cert.key** is located in the **/etc/ssl/** directory:

```sh
-rw-------  1 root wheel 1886 Apr 16 11:53 /etc/ssl/cert.key
```

Verify the private key:

```sh
# openssl x509 -noout -modulus -in /etc/ssl/certs/cert.crt | openssl sha256
SHA2-256(stdin)= 2246982ddf52bdbe15cb4df06df58f8e3c5ff075e6aa08bc564caf965ee75203
# openssl rsa -noout -modulus -in /etc/ssl/cert.key | openssl sha256
Enter pass phrase for /etc/ssl/cert.key: # Enter the previously set password
SHA2-256(stdin)= 2246982ddf52bdbe15cb4df06df58f8e3c5ff075e6aa08bc564caf965ee75203
```

If the SHA-256 values match, the private key and certificate are paired.

It is recommended to store the above files in the **/etc/ssl/** directory and set permissions using the `chmod` command: certificates (`.crt`) are public information and should be set to `0644`, while private keys (`.key`) should be set to `0600`.

```sh
# cp /etc/ssl/certs/cert.crt /etc/ssl/
# chmod 0644 /etc/ssl/cert.crt
# chmod 0600 /etc/ssl/cert.key
```

## Configuring the FIPS Provider

OpenSSL 3 has been included in the base system since FreeBSD 14, bringing with it the new concept of provider modules.

In addition to the built-in default provider, the `legacy` module implements optional and deprecated cryptographic algorithms, while the `fips` module is strictly limited to the set of cryptographic algorithms permitted by the FIPS standard.

The FIPS-related portions of OpenSSL receive [special attention](https://www.openssl.org/docs/fips.html), have a [list of known security issues](https://www.openssl.org/news/fips-cve.html), and undergo periodic [FIPS 140 validation process](https://github.com/openssl/openssl/blob/master/README-FIPS.md) reviews. These measures allow users to ensure FIPS compliance requirements are met.

The fips\_module is also protected by additional security mechanisms; it cannot be used without passing an integrity check. The local system administrator can configure this check as needed, and then allow each OpenSSL 3 user to load the module. If configured improperly, the FIPS module will report an error as follows:

```sh
# echo test | openssl aes-128-cbc -a -provider fips -pbkdf2
```

The output should resemble the following:

```
aes-128-cbc: unable to load provider fips
Hint: use -provider-path option or OPENSSL_MODULES environment variable.
1090A56510220000:error:12800067:DSO support routines:dlfcn_load:could not load the sharedlibrary:/usr/src/crypto/openssl/crypto/dso/dso_dlfcn.c:115:filename(/usr/lib/ossl-modules/fips.so): Cannot open "/usr/lib/ossl-modules/fips.so"
1090A56510220000:error:12800067:DSO support routines:DSO_load:could not load the shared library:/usr/src/crypto/openssl/crypto/dso/dso_lib.c:147:
1090A56510220000:error:07880025:common libcrypto routines:provider_init:reason(37):/usr/src/crypto/openssl/crypto/provider_core.c:1026:name=fips
```

You can configure the integrity check by creating **/etc/ssl/fipsmodule.cnf** and referencing it in the main OpenSSL configuration file **/etc/ssl/openssl.cnf**.

You need to install a certified version of OpenSSL via Ports, referring to the [FIPS validated version list](https://www.openssl.org/source/). Then copy the **fips.so** library to the appropriate location.

> **Warning**
>
> **FIPS Module Cross-Major-Version Mixing Risk**: The following operation copies the OpenSSL **3.0** FIPS module from Ports to the base system path, mixing it with the base system's OpenSSL **3.5**. This cross-major-version (3.0 to 3.5) mixing carries the following serious risks:
>
> * **ABI Incompatibility**: Internal data structures and function interfaces between different major versions of OpenSSL may be incompatible, leading to program crashes or abnormal behavior.
> * **FIPS Certification Invalidation**: FIPS 140 validation is issued for specific version combinations; cross-major-version mixing renders FIPS compliance invalid both legally and technically.
> * **Security Risks**: Older FIPS modules may lack security fixes from newer OpenSSL versions; mixing may introduce known vulnerabilities.
>
> To use the FIPS module in compliance, ensure that the FIPS module and OpenSSL library versions strictly match. **If you are unsure about version compatibility, do not perform the following operations.**

OpenSSL provides `openssl fipsinstall` to assist with this process. Usage is as follows:

```sh
# cp /usr/local/lib/ossl-modules/fips.so /usr/lib/ossl-modules/
# openssl fipsinstall -module /usr/lib/ossl-modules/fips.so -out /etc/ssl/fipsmodule.cnf
```

The output should resemble the following (version number depends on the OpenSSL version installed from Ports):

```
    name:           OpenSSL FIPS Provider
    version:        3.0.20
    build:          3.0.20
INSTALL PASSED
```

Next, modify **/etc/ssl/openssl.cnf** to add the following three configurations:

* Include the generated **/etc/ssl/fipsmodule.cnf** file,
* Export the FIPS module for invocation,
* And explicitly activate the default module.

```ini
......other content omitted......

# For FIPS
# Optionally include a file that is generated by the OpenSSL fipsinstall
# application. This file contains configuration data required by the OpenSSL
# fips provider. It contains a named section e.g. [fips_sect] which is
# referenced from the [provider_sect] below.
# Refer to the OpenSSL security policy for more information.
.include /etc/ssl/fipsmodule.cnf

......other content omitted......

# List of providers to load
[provider_sect]
default = default_sect
# The fips section name should match the section name inside the
# included fipsmodule.cnf.
fips = fips_sect

# If no providers are activated explicitly, the default one is activated implicitly.
# See man 7 OSSL_PROVIDER-default for more details.
#
# If you add a section explicitly activating any other provider(s), you most
# probably need to explicitly activate the default provider, otherwise it
# becomes unavailable in openssl.  As a consequence applications depending on
# OpenSSL may not work correctly which could lead to significant system
# problems including inability to remotely access the system.
[default_sect]
activate = 1
```

After completing the above steps, you can confirm that the FIPS module is available and working properly:

```sh
# echo test | openssl aes-128-cbc -a -provider fips -pbkdf2
```

The output should resemble the following:

```
enter AES-128-CBC encryption password: # Enter password
Verifying - enter AES-128-CBC encryption password: # Re-enter password
U2FsdGVkX1+cIAxHqRAhBgFQdCjTDU2sGevQ152Gw74=
```

View the current OpenSSL provider status:

```sh
# openssl list -providers
Providers:
  default
    name: OpenSSL Default Provider
    version: 3.5.6
    status: active
  fips
    name: OpenSSL FIPS Provider
    version: 3.0.20
    status: active
```

In the above output, the default provider version number depends on the OpenSSL version used by the system (base system or Ports), and the FIPS provider version number depends on the OpenSSL version installed from Ports.

When the FIPS module changes (such as after a system update or after the base system OpenSSL applies security fixes), the above process must be repeated.

## Exercises

1. Use the `openssl speed` command to test the throughput of AES-128-CBC, AES-256-GCM, and ChaCha20-Poly1305 encryption algorithms on a local FreeBSD system, and analyze the reasons for the differences in results.
2. Use `openssl s_client -connect` to connect to a public HTTPS website, extract the certificate chain, protocol version, and negotiated cipher suite from the output, and draw the trust chain structure diagram of the certificate.
3. Use `openssl req -x509` to generate a self-signed certificate, then configure Nginx or Apache on FreeBSD to use this certificate to provide HTTPS service.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://book.bsdcn.org/ask/flat/chapter-29-security/di-29.5-jie-openssl.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
