Search code examples
cwinapisslwinhttp

Certificate pinning with WinHTTP API


Is it possible to implement certificate pinning using the Win32 WinHTTP API, and if so how? I.e. how can I check the returned server certificate against a 'known good' one, preferably without having to permanently write the cert into the local certificate store.


Solution

  • (inspired by jww's answer)

    Firstly I found this page to be excellent background reading about pinning and the choice between certificate and public key pinning.

    I implemented certificate pinning using WinHTTP API as follows:

    1. After WinHttpOpen but before WinHttpConnect, setup a callback for when requests are sent:

      WinHttpSetStatusCallback(hSession, &callbackFunc, WINHTTP_CALLBACK_SENDING_REQUEST, NULL);

    2. In the callback function, retrieve the raw certificate blob:

      PCCERT_CONTEXT pCert=NULL; DWORD dwSize=sizeof(pCert); WinHttpQueryOption(hInternet, WINHTTP_OPTION_SERVER_CERT_CONTEXT, &pCert, &dwSize);

    3. Then if doing full certificate pinning, compare sha1(pCert->pbCertEncoded) against a known good certificate SHA1 thumbprint.

    4. -Or- if doing public key pinning instead, compare sha1(pCert->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData) against a known good SHA1 of a server public key.