Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Openssl engine support - revisited #915

Closed
wants to merge 3 commits into from

Conversation

nicopernas
Copy link
Contributor

These changes were originally proposed on this other PR (#202) about 2 years ago. This is a revisited version, since the original was way behind the develop branch and I don't have access to the forked repo where the original PR comes from. Please read the motivations behind these changes there.

I've extended the original changes with an extra commit on top, to add support for a feature that enables passing on private key passwords to the engine to avoid the user from being prompted. Feel free to ignore it if you think it's not so helpful.

The testing I've done is not great, since I could not find a way to automate the openssl engine part of it. I thought I could come up with a mock-up engine or maybe find one out there but I was not so lucky. What I ended up doing was pretty much the same as with my original PR: setting up a very convoluted environment where I could manually test both clients and broker talking to each other.

The tests included within the repo are all passing with the exception of ./06-bridge-b2br-remapping.py and ./08-ssl-bridge.py which are also failing on the develop branch, so I left them out temporarily when running them. I am not disabling them on this PR.

# make test
...
./01-connect-success.py
./01-connect-invalid-protonum.py
./01-connect-invalid-id-0.py
...
./09-util-topic-matching.py cpp/09-util-topic-matching.test
./09-util-topic-tokenise.py cpp/09-util-topic-tokenise.test
./09-util-utf8-validate.py cpp/09-util-utf8-validate.test
make[2]: Leaving directory '/home/nico/mosquitto/test/lib'
make[1]: Leaving directory '/home/nico/mosquitto/test'

The manual testing mentioned above involves a TPM emulator, TrouSerS and a TPM OpenSSL engine. Ideally, I would have used a simpler environment or even a real one (a board with a real TPM) but unfortunately, I don't have access to such HW these days.

TPM emulator

I've downloaded and built this tpm-emulator by following the steps on the README file. I then ran it like this:

# sudo insmod tpmd_dev/linux/tpmd_dev.ko
# sudo ./build/tpmd/unix/tpmd -f
tpmd.c:523: Info: starting TPM Emulator daemon (1.2.0.7-475)
tpmd.c:102: Info: parsing options
tpmd.c:228: Info: installing signal handlers
tpmd.c:387: Info: staring main loop
tpmd.c:302: Info: initializing socket /var/run/tpm/tpmd_socket:0
tpm_emulator_extern.c:101: Info: _tpm_extern_init()
tpm_startup.c:29: Info: TPM_Init()
tpm_testing.c:243: Info: TPM_SelfTestFull()
tpm_testing.c:261: Info: Self-Test succeeded
tpm_startup.c:43: Info: TPM_Startup(2)

TrouSerS

On top of the emulated TPM device, we need the TrouSerS stack (TSS) so the OpenSSL engine can talk to the TPM. I realised the binaries were available in Ubuntu's repos so I got them from there. Make sure to use the -e option so tcsd can communicate to the TPM emulator via socket.

# sudo apt install trousers
# sudo tcsd -e -f
TCSD TDDL ioctl: (25) Inappropriate ioctl for device
TCSD TDDL Falling back to Read/Write device support.
TCSD trousers 0.3.13: TCSD up and running.

TPM tools

We also need the tpm-tools to operate with the TPM. There's a README file included that explains how to build and install them.

Once built and installed, we have to "take ownership" and create a Storage Root Key (SRK) by using the tpm_takeownership command. The tool prompts for a SRK and owner password - I used the same on both cases for the sake of testing.

OpenSSL TPM engine

I've gotten the openssl-tpm-engine and built it following the included instructions. The repo includes a piece of OpenSSL config file (openssl.cnf.sample) that I used in order to make the engine visible to openssl. Note the dynamic_path points to where libtpm.so was installed.

# sed -n '20,30 p' /etc/ssl/openssl.cnf
openssl_conf = openssl_def
[openssl_def]
engines = engine_section
[engine_section]
foo = tpm_section
[tpm_section]
dynamic_path = /usr/local/lib/openssl/engines/libtpm.so
engine_id = tpm
default_algorithms = ALL
init = 1
[ new_oids ]

The TPM engine was then visible and usable:

# openssl engine -t
(rdrand) Intel RDRAND engine
     [ available ]
(dynamic) Dynamic engine loading support
     [ unavailable ]
(tpm) TPM hardware engine support
     [ available ]

Keys

I then had to create a few keys. First, a private key using the TPM engine, with the create_tpm_key command (included in openssl-tpm-engine). The SRK password is required.

# sudo create_tpm_key tpm-test.key

With the TPM private key and making use of the testing CA included with the mosquitto testing code, I created new signing requests and certificates for both clients and server.

# openssl req -keyform engine -engine tpm -key tpm-test.key -new -out tpm-client.req
# openssl req -keyform engine -engine tpm -key tpm-test.key -new -out tpm-server.req

# openssl x509 -req -days 2000 -sha1 \
    -in /home/nico/ssl/tpm-client.req \
    -extensions usr_cert \
    -CA /home/nico/mosquitto/test/ssl/test-root-ca.crt \
    -CAkey /home/nico/mosquitto/test/ssl/test-root-ca.key \
    -CAcreateserial \
    -out tpm-client.cert

# openssl x509 -req -days 2000 -sha1 \
    -in /home/nico/ssl/tpm-server.req \
    -extensions usr_cert \
    -CA /home/nico/mosquitto/test/ssl/test-root-ca.crt \
    -CAkey /home/nico/mosquitto/test/ssl/test-root-ca.key \
    -CAcreateserial \
    -out /home/nico/ssl/tpm-server.cert

Running the actual test

In this case, I am running both sub and pub clients and the broker using the TPM engine. Please note this is not required, as in, only the client side could be using the TPM engine for example. However and for the sake of testing all components at the same time, I'm doing it this way.

# cat /home/nico/ssl/mosquitto.conf
cafile /home/nico/mosquitto/test/ssl/all-ca.crt
certfile /home/nico/ssl/tpm-server.cert
keyfile /home/nico/ssl/tpm-test.key
tls_engine tpm
tls_keyform engine
require_certificate true


# /home/nico/mosquitto/src/mosquitto -c /home/nico/ssl/mosquitto.conf
1534016728: mosquitto version 1.5 starting
1534016728: Config loaded from /home/nico/ssl/mosquitto.conf.
1534016728: Opening ipv4 listen socket on port 1883.
1534016728: Opening ipv6 listen socket on port 1883.
SRK authorization:
1534016736: New connection from ::1 on port 1883.
1534016739: New client connected from ::1 as mosqsub|27974-ubuntu (c1, k60).
1534016748: New connection from ::1 on port 1883.
1534016751: New client connected from ::1 as mosqpub|27977-ubuntu (c1, k60).
1534016751: Client mosqpub|27977-ubuntu disconnected.


# LD_LIBRARY_PATH=/home/nico/mosquitto/lib \
/home/nico/mosquitto/client/mosquitto_sub \
    --cafile /home/nico/mosquitto/test/ssl/all-ca.crt \
    --cert /home/nico/ssl/client.cert \
    --key /home/nico/ssl/tpm-test.key \
    --tls-engine tpm \
    --keyform engine \
    -v \
    -p 1883 \
    -F '[%U] %t %p' \
    -t my-topic
SRK authorization:
[1534016751.371236830] my-topic foo-bar-zoo


# LD_LIBRARY_PATH=/home/nico/mosquitto/lib \
/home/nico/mosquitto/client/mosquitto_pub 
    --cafile /home/nico/mosquitto/test/ssl/all-ca.crt \
    --cert /home/nico/ssl/client.cert \
    --key /home/nico/ssl/tpm-test.key \
    --tls-engine tpm \
    --keyform engine \
    -p 1883 \
    -t my-topic \
    -m foo-bar-zoo
SRK authorization:

Also, note how the TPM prompts me for the SRK password every time I want to use the private key generate it with it. This time, I'm using the tls_engine_kpass_sha option to avoid that.

My super secure SRK password is nico and this is the SHA1 hash I'm using.

# echo -n 'nico' | sha1sum
d659c10e27d52b00987b65e85d99bce5480adcae  -


# cat /home/nico/ssl/mosquitto.conf
cafile /home/nico/mosquitto/test/ssl/all-ca.crt
certfile /home/nico/ssl/tpm-server.cert
keyfile /home/nico/ssl/tpm-test.key
tls_engine tpm
tls_keyform engine
require_certificate true
tls_engine_kpass_sha d659c10e27d52b00987b65e85d99bce5480adcae


# /home/nico/mosquitto/src/mosquitto -c /home/nico/ssl/mosquitto.conf
1534017469: mosquitto version 1.5 starting
1534017469: Config loaded from /home/nico/ssl/mosquitto.conf.
1534017469: Opening ipv4 listen socket on port 1883.
1534017469: Opening ipv6 listen socket on port 1883.
1534017474: New connection from ::1 on port 1883.
1534017474: New client connected from ::1 as mosqsub|28042-ubuntu (c1, k60).
1534017478: New connection from ::1 on port 1883.
1534017479: New client connected from ::1 as mosqpub|28045-ubuntu (c1, k60).
1534017479: Client mosqpub|28045-ubuntu disconnected.


# LD_LIBRARY_PATH=/home/nico/mosquitto/lib \
/home/nico/mosquitto/client/mosquitto_sub \
    --cafile /home/nico/mosquitto/test/ssl/all-ca.crt \
    --cert /home/nico/ssl/client.cert \
    --key /home/nico/ssl/tpm-test.key \
    --tls-engine-kpass-sha 'd659c10e27d52b00987b65e85d99bce5480adcae' \
    --tls-engine tpm \
    --keyform engine \
    -v \
    -p 1883 \
    -F '[%U] %t %p' \
    -t my-topic
[1534017479.023951298] my-topic foo-bar-zoo


# LD_LIBRARY_PATH=/home/nico/mosquitto/lib \
/home/nico/mosquitto/client/mosquitto_pub 
    --cafile /home/nico/mosquitto/test/ssl/all-ca.crt \
    --cert /home/nico/ssl/client.cert \
    --key /home/nico/ssl/tpm-test.key \
    --tls-engine-kpass-sha 'd659c10e27d52b00987b65e85d99bce5480adcae' \
    --tls-engine tpm \
    --keyform engine \
    -p 1883 \
    -t my-topic \
    -m foo-bar-zoo

I tried to stick with your coding style as much as I could. I'm open to accept any suggestion you may have regarding variable naming, where the code was placed or anything you wanna bring up.

Thanks,
Nico.

- Clients can now offload crypto tasks to an external crypto device through
  the OpenSSL ENGINE API.
- The keyfiles can now be treated as PEM or ENGINE keys.
- Two new functions were added to libmosquitto to set up the previously
  mentioned features.
- Both mosquitto_sub and mosquitto_pub include support to turn on the mentioned
  features through command line options.

Signed-off-by: Nicolás Pernas Maradei <[email protected]>
Add same OpenSSL engine support to mosquitto (server side) previously added to
client side only.

Signed-off-by: Nicolás Pernas Maradei <[email protected]>
Some OpenSSL engines (selectable via tls_engine option) may require a
password to make use of private keys created with them in the first place.

The TPM engine for example, will require a password to access the underlying
TPM's Storage Root Key (SRK), which is the root key of a hierarchy of keys
associated with a TPM; it is generated within a TPM and is a non-migratable
key. Each owned TPM contains a SRK, generated by the TPM at the request
of the Owner. [1]

By default, the engine will prompt the user to introduce the SRK password
before any private keys created with the engine can be used. This could
be inconvenient when running on an unattended system.

Here's where the new tls_engine_kpass_sha option comes in handy. The user
can specify a SHA1 hash of its engine private key password via command
line or config file and it will be passed on to the engine directly.

This commit adds support for both clients (libmosquitto) and broker.

[1] https://goo.gl/qQoXBY

Signed-off-by: Nicolás Pernas Maradei <[email protected]>
@fcarlier
Copy link

Maybe close #202 ? ;)

@matthias1000
Copy link

Hi,
This feature looks like what we need in order to use libmosquitto and the TPM2-Engine (https://github.com/tpm2-software/tpm2-tss-engine).

What is the status of this PR and what would be needed to merge it?
If the tests are not sufficiently automated then where could one start to improve them?

Regards,
Matthias

@nicopernas
Copy link
Contributor Author

I sent out this PR not too long ago and at that time, everything was working as expected. Not sure why it did not get merged yet. I would guess the lack of automated tests would be the main reason though.

@ralight ralight added this to the 1.6 milestone Nov 1, 2018
@ralight
Copy link
Contributor

ralight commented Nov 1, 2018

The reason it hasn't been merged yet is because I want to fully understand what I'm merging and other more pressing work has got in the way. It'll be in 1.6.

@ralight
Copy link
Contributor

ralight commented Feb 26, 2019

This is now finally merged in 20894fc , I've modified it a bit to fit in with other changes, but they are mostly cosmetic. Thanks for your contribution!

@ralight ralight closed this Feb 26, 2019
@nicopernas nicopernas deleted the openssl_engine branch January 14, 2022 13:34
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Oct 15, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants