-
Notifications
You must be signed in to change notification settings - Fork 1k
Description
Is your feature request related to a problem?
curl very recently (8.12.0) added support to use keys and certificates with PKCS#11 provider (a way to access keys and certificates in a secure element, instead of files).
curl/curl#15587
If you pass a valid pkcs11 uri in the --key or --cert argument, it will use them with the provider configured in OpenSSL.
They also added a new --key-type / --cert-type named "PROV", and if not explicitly set it will take the "PROV" value if a pkcs11 uri is detected in the --key-type / --cert-type arguments.
An example curl command that uses pkcs11 for the key and a file for the cert:
curl --key-type PROV --key "pkcs11:token=mytoken;object=mykey;type=private;pin-value=111111" --cert cert.pem --cacert ca_cert.pem https://localhost/
With cpr, it is not possible to currently use this feature because even if you pass a pkcs11 uri as an argument to KeyFile, it will explicitly set the key type to "PEM".
Possible Solution
One easy solution is to create a new KeyProv class, almost the same as KeyFile, but that returns "PROV" as the key type:
class KeyProv {
public:
// NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
KeyProv(fs::path&& p_filename) : filename(std::move(p_filename)) {}
template <typename FileType, typename PassType>
KeyProv(FileType&& p_filename, PassType p_password) : filename(std::forward<FileType>(p_filename)), password(std::move(p_password)) {}
virtual ~KeyProv() {
util::secureStringClear(password);
}
fs::path filename;
std::string password;
virtual const char* GetKeyType() const {
return "PROV";
}
};Same with CertFile:
class CertProv {
public:
// NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
CertProv(fs::path&& p_filename) : filename(std::move(p_filename)) {}
virtual ~CertProv() = default;
const fs::path filename;
virtual const char* GetCertType() const {
return "PROV";
}
};And the new SetOption:
void SetOption(const ssl::KeyProv& opt) {
key_file = opt.filename.string();
key_type = opt.GetKeyType();
key_pass = opt.password;
}
void SetOption(const ssl::CertProv& opt) {
cert_file = opt.filename.string();
cert_type = opt.GetCertType();
}I have tried this approach and works corrently with libcurl 8.12.1 with the key stored in the TPM:
// key_file contains a pkcs11 uri
cpr::SslOptions sslOpts =
cpr::Ssl(cpr::ssl::TLSv1_2{}, cpr::ssl::CertFile{cert_file},
cpr::ssl::KeyProv{key_file}, cpr::ssl::CaInfo{ca_file},
cpr::ssl::VerifyPeer{true}, cpr::ssl::VerifyHost{true});
cpr::Response r = cpr::Get(cpr::Url{"https://10.0.0.10"}, sslOpts);Alternatives
Another alternative, and maybe more direct option would be to add another constructor to KeyFile and CertFile to accept the key type as a parameter, than then gets returned by GetCertType or CetKeyType. This way, it would be possible to just use KeyFile("pkcs11:my-uri", "PROV");
Additional Context
I can provide a pull request with either approach.