Is it possible to implement the functionality shown in the bash script below from a C++ application, possibly using an OpenSSL provider obtained using:
OSSL_PROVIDER * tpm2_provider = OSSL_PROVIDER_load(NULL, "tpm2");
or by another method?
# Create CSR using TPM-resident private key
openssl req -provider tpm2 -provider default -propquery '?provider=tpm2'
-new
-key handle:$TPMHandle
-config openssl.conf
-reqexts v3_req
-out device.csr
Can the private key remain in the TPM or is it necessary to extract the private key into the application, in order to sign the CSR in the C++ code?
I am able to create a CSR using the bash script with the openssl tpm2 provider to sign the CSR. I don't see a way to achieve the same functionality using the C or C++ APIs.
This code works but it retrieves the private key from the TPM. Can I achieve the same result without extracting the private key?
EVP_PKEY * GetPrivateKeyFromTPM(void) {
OSSL_STORE_CTX *storeCtx = NULL;
storeCtx = OSSL_STORE_open_ex("handle:0x81005020", tpm2_libctx,"?provider=tpm2", NULL, NULL, NULL,NULL, NULL);
while (!OSSL_STORE_eof(storeCtx)) {
OSSL_STORE_INFO *info = OSSL_STORE_load(storeCtx);
switch (OSSL_STORE_INFO_get_type(info)) {
case OSSL_STORE_INFO_PKEY:
EVP_PKEY *TPMpkey = OSSL_STORE_INFO_get1_PKEY(info);
if (TPMpkey) {
OSSL_STORE_close(storeCtx);
return TPMpkey;
}
break;
}
}
OSSL_STORE_close(storeCtx);
return NULL;
}
This C++ code can be used to get a Reference to a TPM-resident private key which can be used for crypto operations. The key itself remains in the TPM.
In my case, I wanted to create a CSR and sign it with the TPM-resident private key. The EVP_PKEY pointer returned from this code can be used to sign the CSR using other OpenSSL library calls in the normal way.
TPM_Private_Key_Handle argument is in the form 0x8000000.
EVP_PKEY* AWSCertificateMgr::GetPrivateKeyFromTPM(const std::string & TPM_Private_Key_Handle)
}
Code Explanation
Opening a Store Context: The OSSL_STORE_open_ex function opens a store context for a specified URI, which in this case is a TPM handle. This is a reference to where the key is stored, not the key itself.
The store context is an abstraction that allows OpenSSL to access keys and other objects in a variety of locations in a uniform manner.
The "?provider=tpm2" part specifies that the TPM 2.0 provider should be used.
Reading the Key: The code then enters a loop where it attempts to load objects from the store context using OSSL_STORE_load. For each object loaded, it checks if the object is a private key (OSSL_STORE_INFO_PKEY).
Accessing the Private Key: If a private key is found, it is accessed via OSSL_STORE_INFO_get1_PKEY, which increases the reference count of the EVP_PKEY object, meaning the caller is responsible for freeing it.
This EVP_PKEY object can then be used in OpenSSL cryptographic operations, but the actual private key material remains securely within the TPM.
Closure and Cleanup: The loop exits once the key is found or there are no more objects to load. The store context is closed, and the EVP_PKEY object is returned for use in the application.