Reputation: 83
Context:
We developed a PCB integrating several sensors and a system on module (SoM) using Torizon (a Linux distribution), one of the roles of this PCB is to host an OPC-UA server.
We also included an Infineon 9673 TPM 2.0 on the PCB, interfaced via I2C with the Linux SoM, the idea being to dedicate cryptographic key generation, storage and cryptographic functions (encryption/decryption, signature, etc.) to this TPM module.
The OPC-UA server is run in a Docker container in the SOM, and the TPM architecture is as follows:
The persistent key set in the TPM was used to create a CSR for the OPC-UA server certificate with the following command using the Handle of this key set (0xhandle):
openssl req -provider tpm2 -provider default -propquery '?provider=tpm2' -new -subj "/C=FR/O=entreprise/CN=Certificat_Server_OPC_UA" -key handle:0xhandle -out server_rsa.csr
We then used our CA and CSR to create the OPC-UA server certificate:
openssl x509 -req in server_opc_ua.csr -CA /path/to/CA/ca.crt -CAkey /path/to/cakey/ca.key -CAcreateserial -out serveur_opc_ua_certificate.crt -days 365 sha256
We have verified the creation of the certificate with :
openssl x509 -in server_opc_ua_certificate.crt -noout -text
the certificate seems to have been correctly created. For the client(s) wishing to connect to the OPC-UA server, the idea is that they will send their respective CSRs to the SoM, which will take care of creating their certificates and sending them back.
The OPC-UA server is programmed in Python and uses the Free OPC-UA Library (https://github.com/FreeOpcUa) The next step is to load the certificate and the private key (from the TPM) into the OPC-UA server.
The library provides the following methods: load_certificate(path) load server certificate from file, either pem or der load_private_key(path)
We know that it's not possible to extract a private key from a TPM, so that's the idea behind this module. We used the mechanism: tpm2-pkcs#11 to create a token linked to our key in the TPM and then open a session that would allow the OPC-UA server to access our private key to perform crypto operations.
The PyKCS11 python library was used for this and it is possible to access our private key:
lib = self.get_PYKCS11LIB()
print("PYKCS11LIB={}".format(lib))
os.environ["PYKCS11LIB"] = lib
pkcs11 = PyKCS11.PyKCS11Lib()
pkcs11.load(lib) # define environment variable PYKCS11LIB=YourPKCS11Lib
# Obtention de la liste des slots où un token est présent
slots = pkcs11.getSlotList(tokenPresent=True)
print("Slots disponibles: ", len(slots), slots)
slot = pkcs11.getSlotList(tokenPresent=True)[0]
print(f"slot : {slot}")
print(f"ouverture de session")
session = pkcs11.openSession(slot, CKF_SERIAL_SESSION | CKF_RW_SESSION)
print(f"tentative de login")
session.login(user_pin)
print(f"trouver la première clé privée")
privKey = session.findObjects([(CKA_CLASS, CKO_PRIVATE_KEY)])[0]
print(f"private_key_data: { privKey }")
The problem is as follows: the python opc-ua library only seems to want to take a file via a path for the private key, which is not possible with a TPM as it does not allow private keys to be extracted.
Is there an implementation for interfacing the TPM with an OPC-UA python server or even with another programming language?
This document from the official OPC-UA documentation: https://opcconnect.opcfoundation.org/2018/06/practical-security-guidelines-for-building-opc-ua-applications/
Explains that a TPM improves the security of OPC-UA servers. I find it strange that it is not possible to interface our TPM with the configuration of the OPC-UA server :
‘Certificate and private key storage: Never store private keys or the corresponding certificate files (.pfx/p12) on an unencrypted file system. Use the dedicated certificate stores of your operating system and use operating system capabilities for setting the access rights. TPM modules or external secured hardware, like USB-based authentication tokens to store certificates and/or private keys improve the security level.’
I did some research to get round the problem and found a mechanism in the TPM: tpm2_duplicate -> An RSA private key created in the TPM with attributes that allow it to be duplicated on another platform, this key is protected by a parent key and is exported encrypted. It would be possible to use this key to decrypt the private key in a traditional file (PEM or DER format) and give it to the OPC-UA python server.
Do you know if this is feasible?
If so, from a cybersecurity point of view, this process is less reliable than using a ‘standard’ TPM private key, i.e. one that does not leave the TPM, since we are going to store the private key in an unencrypted file in linux (SoM).
Upvotes: 1
Views: 65
Reputation: 381
Never store private keys or the corresponding certificate files (.pfx/p12) on an unencrypted file system.
One easy solution is to store the private key files on an encrypted file system where only the matching user has read access to the private key file.
Unfortunately I don't find any good links, but I highly assume the TPM can be used to provide the root certificate to encrypt the file system / partition.
Upvotes: 0