Search code examples
sslcurlssl-certificatepinning

SSL certificate pinning with libcurl


I'd like to know if this example is enough to provide certificate pinning with libcurl: http://curl.haxx.se/libcurl/c/cacertinmem.html

because I have found that curl also allows http://curl.haxx.se/libcurl/c/CURLOPT_PINNEDPUBLICKEY.html

Since I'll be using a self-signed certificate and only trust on it I don't know if it's truly necessary to pinn it too.

resume: Can the connection be compromised if I only add my certificate (self-signed) to the x509 certificate store like the example? do I need to add extra checks? do I need to use the CURLOPT_PINNEDPUBLICKEY option?

Thanks.


Solution

  • You can find another example in the implementation of the new curl option in git 2.8 (March 2016):

    See commit aeff8a6 (15 Feb 2016) by Christoph Egger (siccegge).
    (Merged by Junio C Hamano -- gitster -- in commit e79112d, 24 Feb 2016)

    http: implement public key pinning

    Add the http.pinnedpubkey configuration option for public key pinning. It allows any string supported by libcurl -- base64(sha256(pubkey)) or filename of the full public key.

    If cURL does not support pinning (is too old) output a warning to the user.

    The git config man page mentions:

    http.pinnedpubkey:
    

    Public key of the https service.
    It may either be the filename of a PEM or DER encoded public key file or a string starting with 'sha256//' followed by the base64 encoded sha256 hash of the public key. See also libcurl 'CURLOPT_PINNEDPUBLICKEY'.
    git will exit with an error if this option is set but not supported by cURL.


    With Git 2.34 (Q4 2021), HTTPS error handling is updated when it comes to SSL certificate pinning:

    See commit 3e8084f (24 Sep 2021) by Ævar Arnfjörð Bjarmason (avar).
    (Merged by Junio C Hamano -- gitster -- in commit 97492aa, 11 Oct 2021)

    http: check CURLE_SSL_PINNEDPUBKEYNOTMATCH when emitting errors

    Signed-off-by: Ævar Arnfjörð Bjarmason

    Change the error shown when a http.pinnedPubKey doesn't match to point the http.pinnedPubKey variable added in aeff8a6 ("http: implement public key pinning", 2016-02-15, Git v2.8.0-rc0 -- merge listed in batch #8), e.g.:

    git -c http.pinnedPubKey=sha256/someNonMatchingKey ls-remote https://github.com/git/git.git
    fatal: unable to access 'https://github.com/git/git.git/' with http.pinnedPubkey configuration: SSL: public key does not match pinned public key!
    

    Before this we'd emit the exact same thing without the " with http.pinnedPubkey configuration".
    The advantage of doing this is that we're going to get a translated message (everything after the ":" is hardcoded in English in libcurl), and we've got a reference to the git-specific configuration variable that is causing the error.

    Unfortunately we can't test this easily, as there are no tests that require https:// in the test suite, and t/lib-httpd.sh doesn't know how to set up such tests.
    See this thread for the start of a discussion about what it would take to have divergent "t/lib-httpd/apache.conf" test setups.