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

Accept PKCS11 uri as key or certificate in sslOptions #1193

Open
martxel opened this issue Mar 7, 2025 · 2 comments
Open

Accept PKCS11 uri as key or certificate in sslOptions #1193

martxel opened this issue Mar 7, 2025 · 2 comments

Comments

@martxel
Copy link

martxel commented Mar 7, 2025

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.

@COM8
Copy link
Member

COM8 commented Mar 20, 2025

@martxel thanks for reporting!
I would love to see this in cpr.

I'd prefer going with the CertProv class approach since it is more verbose and aligns better with the current coding style of cpr.

@martxel
Copy link
Author

martxel commented Mar 21, 2025

Ok, I went with that approach in my project. I will provide a merge request in a few days.

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants