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.
(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:
After WinHttpOpen but before WinHttpConnect, setup a callback for when requests are sent:
WinHttpSetStatusCallback(hSession, &callbackFunc, WINHTTP_CALLBACK_SENDING_REQUEST, NULL);
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);
Then if doing full certificate pinning, compare sha1(pCert->pbCertEncoded)
against a known good certificate SHA1 thumbprint.
-Or- if doing public key pinning instead, compare sha1(pCert->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData)
against a known good SHA1 of a server public key.