ssl_platform_key_win.cc 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. // Copyright 2015 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "net/ssl/ssl_platform_key_win.h"
  5. #include <algorithm>
  6. #include <memory>
  7. #include <string>
  8. #include <utility>
  9. #include <vector>
  10. #include "base/logging.h"
  11. #include "base/strings/utf_string_conversions.h"
  12. #include "crypto/openssl_util.h"
  13. #include "crypto/scoped_capi_types.h"
  14. #include "net/base/net_errors.h"
  15. #include "net/cert/x509_certificate.h"
  16. #include "net/ssl/ssl_platform_key_util.h"
  17. #include "net/ssl/ssl_private_key.h"
  18. #include "net/ssl/threaded_ssl_private_key.h"
  19. #include "third_party/boringssl/src/include/openssl/bn.h"
  20. #include "third_party/boringssl/src/include/openssl/ecdsa.h"
  21. #include "third_party/boringssl/src/include/openssl/evp.h"
  22. #include "third_party/boringssl/src/include/openssl/ssl.h"
  23. namespace net {
  24. namespace {
  25. std::string GetCAPIProviderName(HCRYPTPROV provider) {
  26. DWORD name_len;
  27. if (!CryptGetProvParam(provider, PP_NAME, nullptr, &name_len, 0)) {
  28. return "(error getting name)";
  29. }
  30. std::vector<BYTE> name(name_len);
  31. if (!CryptGetProvParam(provider, PP_NAME, name.data(), &name_len, 0)) {
  32. return "(error getting name)";
  33. }
  34. // Per Microsoft's documentation, PP_NAME is NUL-terminated. However,
  35. // smartcard drivers are notoriously buggy, so check this.
  36. auto nul = std::find(name.begin(), name.end(), 0);
  37. if (nul != name.end()) {
  38. name_len = nul - name.begin();
  39. }
  40. return std::string(reinterpret_cast<const char*>(name.data()), name_len);
  41. }
  42. class SSLPlatformKeyCAPI : public ThreadedSSLPrivateKey::Delegate {
  43. public:
  44. // Takes ownership of |provider|.
  45. SSLPlatformKeyCAPI(crypto::ScopedHCRYPTPROV provider, DWORD key_spec)
  46. : provider_name_(GetCAPIProviderName(provider.get())),
  47. provider_(std::move(provider)),
  48. key_spec_(key_spec) {}
  49. SSLPlatformKeyCAPI(const SSLPlatformKeyCAPI&) = delete;
  50. SSLPlatformKeyCAPI& operator=(const SSLPlatformKeyCAPI&) = delete;
  51. ~SSLPlatformKeyCAPI() override = default;
  52. std::string GetProviderName() override { return "CAPI: " + provider_name_; }
  53. std::vector<uint16_t> GetAlgorithmPreferences() override {
  54. // If the key is in CAPI, assume conservatively that the CAPI service
  55. // provider may only be able to sign pre-TLS-1.2 and SHA-1 hashes.
  56. // Prioritize SHA-1, but if the server doesn't advertise it, leave the other
  57. // algorithms enabled to try.
  58. return {
  59. SSL_SIGN_RSA_PKCS1_SHA1,
  60. SSL_SIGN_RSA_PKCS1_SHA256,
  61. SSL_SIGN_RSA_PKCS1_SHA384,
  62. SSL_SIGN_RSA_PKCS1_SHA512,
  63. };
  64. }
  65. Error Sign(uint16_t algorithm,
  66. base::span<const uint8_t> input,
  67. std::vector<uint8_t>* signature) override {
  68. const EVP_MD* md = SSL_get_signature_algorithm_digest(algorithm);
  69. uint8_t digest[EVP_MAX_MD_SIZE];
  70. unsigned digest_len;
  71. if (!md || !EVP_Digest(input.data(), input.size(), digest, &digest_len, md,
  72. nullptr)) {
  73. return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
  74. }
  75. ALG_ID hash_alg;
  76. switch (EVP_MD_type(md)) {
  77. case NID_md5_sha1:
  78. hash_alg = CALG_SSL3_SHAMD5;
  79. break;
  80. case NID_sha1:
  81. hash_alg = CALG_SHA1;
  82. break;
  83. case NID_sha256:
  84. hash_alg = CALG_SHA_256;
  85. break;
  86. case NID_sha384:
  87. hash_alg = CALG_SHA_384;
  88. break;
  89. case NID_sha512:
  90. hash_alg = CALG_SHA_512;
  91. break;
  92. default:
  93. NOTREACHED();
  94. return ERR_FAILED;
  95. }
  96. crypto::ScopedHCRYPTHASH hash_handle;
  97. if (!CryptCreateHash(
  98. provider_.get(), hash_alg, 0, 0,
  99. crypto::ScopedHCRYPTHASH::Receiver(hash_handle).get())) {
  100. PLOG(ERROR) << "CreateCreateHash failed";
  101. return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
  102. }
  103. DWORD hash_len;
  104. DWORD arg_len = sizeof(hash_len);
  105. if (!CryptGetHashParam(hash_handle.get(), HP_HASHSIZE,
  106. reinterpret_cast<BYTE*>(&hash_len), &arg_len, 0)) {
  107. PLOG(ERROR) << "CryptGetHashParam HP_HASHSIZE failed";
  108. return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
  109. }
  110. if (hash_len != digest_len)
  111. return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
  112. if (!CryptSetHashParam(hash_handle.get(), HP_HASHVAL,
  113. const_cast<BYTE*>(digest), 0)) {
  114. PLOG(ERROR) << "CryptSetHashParam HP_HASHVAL failed";
  115. return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
  116. }
  117. DWORD signature_len = 0;
  118. if (!CryptSignHash(hash_handle.get(), key_spec_, nullptr, 0, nullptr,
  119. &signature_len)) {
  120. PLOG(ERROR) << "CryptSignHash failed";
  121. return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
  122. }
  123. signature->resize(signature_len);
  124. if (!CryptSignHash(hash_handle.get(), key_spec_, nullptr, 0,
  125. signature->data(), &signature_len)) {
  126. PLOG(ERROR) << "CryptSignHash failed";
  127. return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
  128. }
  129. signature->resize(signature_len);
  130. // CryptoAPI signs in little-endian, so reverse it.
  131. std::reverse(signature->begin(), signature->end());
  132. return OK;
  133. }
  134. private:
  135. std::string provider_name_;
  136. crypto::ScopedHCRYPTPROV provider_;
  137. DWORD key_spec_;
  138. };
  139. class ScopedNCRYPT_PROV_HANDLE {
  140. public:
  141. ScopedNCRYPT_PROV_HANDLE() {}
  142. ScopedNCRYPT_PROV_HANDLE(const ScopedNCRYPT_PROV_HANDLE&) = delete;
  143. ScopedNCRYPT_PROV_HANDLE& operator=(const ScopedNCRYPT_PROV_HANDLE&) = delete;
  144. ~ScopedNCRYPT_PROV_HANDLE() {
  145. if (prov_) {
  146. NCryptFreeObject(prov_);
  147. }
  148. }
  149. NCRYPT_PROV_HANDLE get() const { return prov_; }
  150. NCRYPT_PROV_HANDLE* InitializeInto() { return &prov_; }
  151. private:
  152. NCRYPT_PROV_HANDLE prov_ = 0;
  153. };
  154. std::wstring GetCNGProviderName(NCRYPT_KEY_HANDLE key) {
  155. ScopedNCRYPT_PROV_HANDLE prov;
  156. DWORD prov_len = 0;
  157. SECURITY_STATUS status = NCryptGetProperty(
  158. key, NCRYPT_PROVIDER_HANDLE_PROPERTY,
  159. reinterpret_cast<BYTE*>(prov.InitializeInto()),
  160. sizeof(*prov.InitializeInto()), &prov_len, NCRYPT_SILENT_FLAG);
  161. if (FAILED(status)) {
  162. return L"(error getting provider)";
  163. }
  164. DCHECK_EQ(sizeof(NCRYPT_PROV_HANDLE), prov_len);
  165. // NCRYPT_NAME_PROPERTY is a NUL-terminated Unicode string, which means an
  166. // array of wchar_t, however NCryptGetProperty works in bytes, so lengths must
  167. // be converted.
  168. DWORD name_len = 0;
  169. status = NCryptGetProperty(prov.get(), NCRYPT_NAME_PROPERTY, nullptr, 0,
  170. &name_len, NCRYPT_SILENT_FLAG);
  171. if (FAILED(status) || name_len % sizeof(wchar_t) != 0) {
  172. return L"(error getting provider name)";
  173. }
  174. std::vector<wchar_t> name;
  175. name.reserve(name_len / sizeof(wchar_t));
  176. status = NCryptGetProperty(
  177. prov.get(), NCRYPT_NAME_PROPERTY, reinterpret_cast<BYTE*>(name.data()),
  178. name.size() * sizeof(wchar_t), &name_len, NCRYPT_SILENT_FLAG);
  179. if (FAILED(status)) {
  180. return L"(error getting provider name)";
  181. }
  182. name.resize(name_len / sizeof(wchar_t));
  183. // Per Microsoft's documentation, the name is NUL-terminated. However,
  184. // smartcard drivers are notoriously buggy, so check this.
  185. auto nul = std::find(name.begin(), name.end(), 0);
  186. if (nul != name.end()) {
  187. name.erase(nul, name.end());
  188. }
  189. return std::wstring(name.begin(), name.end());
  190. }
  191. class SSLPlatformKeyCNG : public ThreadedSSLPrivateKey::Delegate {
  192. public:
  193. // Takes ownership of |key|.
  194. SSLPlatformKeyCNG(NCRYPT_KEY_HANDLE key, int type, size_t max_length)
  195. : provider_name_(GetCNGProviderName(key)),
  196. key_(key),
  197. type_(type),
  198. max_length_(max_length) {}
  199. SSLPlatformKeyCNG(const SSLPlatformKeyCNG&) = delete;
  200. SSLPlatformKeyCNG& operator=(const SSLPlatformKeyCNG&) = delete;
  201. ~SSLPlatformKeyCNG() override { NCryptFreeObject(key_); }
  202. std::string GetProviderName() override {
  203. return "CNG: " + base::WideToUTF8(provider_name_);
  204. }
  205. std::vector<uint16_t> GetAlgorithmPreferences() override {
  206. // Per TLS 1.3 (RFC 8446), the RSA-PSS code points in TLS correspond to
  207. // RSA-PSS with salt length equal to the digest length. TPM 2.0's
  208. // TPM_ALG_RSAPSS algorithm, however, uses the maximum possible salt length.
  209. // The TPM provider will fail signing requests for other salt lengths and
  210. // thus cannot generate TLS-compatible PSS signatures.
  211. //
  212. // However, as of TPM revision 1.16, TPMs which follow FIPS 186-4 will
  213. // instead interpret TPM_ALG_RSAPSS using salt length equal to the digest
  214. // length. Those TPMs can generate TLS-compatible PSS signatures. As a
  215. // result, if this is a TPM-based key, we only report PSS as supported if
  216. // the salt length will match the digest length.
  217. bool supports_pss = true;
  218. if (provider_name_ == MS_PLATFORM_KEY_STORAGE_PROVIDER) {
  219. DWORD salt_size = 0;
  220. DWORD size_of_salt_size = sizeof(salt_size);
  221. HRESULT status =
  222. NCryptGetProperty(key_, NCRYPT_PCP_PSS_SALT_SIZE_PROPERTY,
  223. reinterpret_cast<PBYTE>(&salt_size),
  224. size_of_salt_size, &size_of_salt_size, 0);
  225. if (FAILED(status) || salt_size != NCRYPT_TPM_PSS_SALT_SIZE_HASHSIZE) {
  226. supports_pss = false;
  227. }
  228. }
  229. // If this is an under 1024-bit RSA key, conservatively prefer to sign SHA-1
  230. // hashes. Older Estonian ID cards can only sign SHA-1 hashes. Prioritize
  231. // SHA-1, but if the server doesn't advertise it, leave the other algorithms
  232. // enabled to try.
  233. if (type_ == EVP_PKEY_RSA && max_length_ <= 1024 / 8) {
  234. std::vector<uint16_t> ret = {
  235. SSL_SIGN_RSA_PKCS1_SHA1,
  236. SSL_SIGN_RSA_PKCS1_SHA256,
  237. SSL_SIGN_RSA_PKCS1_SHA384,
  238. SSL_SIGN_RSA_PKCS1_SHA512,
  239. };
  240. if (supports_pss) {
  241. // 1024-bit keys are too small for SSL_SIGN_RSA_PSS_SHA512.
  242. ret.push_back(SSL_SIGN_RSA_PSS_SHA256);
  243. ret.push_back(SSL_SIGN_RSA_PSS_SHA384);
  244. }
  245. return ret;
  246. }
  247. return SSLPrivateKey::DefaultAlgorithmPreferences(type_, supports_pss);
  248. }
  249. Error Sign(uint16_t algorithm,
  250. base::span<const uint8_t> input,
  251. std::vector<uint8_t>* signature) override {
  252. crypto::OpenSSLErrStackTracer tracer(FROM_HERE);
  253. const EVP_MD* md = SSL_get_signature_algorithm_digest(algorithm);
  254. uint8_t digest[EVP_MAX_MD_SIZE];
  255. unsigned digest_len;
  256. if (!md || !EVP_Digest(input.data(), input.size(), digest, &digest_len, md,
  257. nullptr)) {
  258. return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
  259. }
  260. BCRYPT_PKCS1_PADDING_INFO pkcs1_padding_info = {nullptr};
  261. BCRYPT_PSS_PADDING_INFO pss_padding_info = {nullptr};
  262. void* padding_info = nullptr;
  263. DWORD flags = 0;
  264. if (SSL_get_signature_algorithm_key_type(algorithm) == EVP_PKEY_RSA) {
  265. const WCHAR* hash_alg;
  266. switch (EVP_MD_type(md)) {
  267. case NID_md5_sha1:
  268. hash_alg = nullptr;
  269. break;
  270. case NID_sha1:
  271. hash_alg = BCRYPT_SHA1_ALGORITHM;
  272. break;
  273. case NID_sha256:
  274. hash_alg = BCRYPT_SHA256_ALGORITHM;
  275. break;
  276. case NID_sha384:
  277. hash_alg = BCRYPT_SHA384_ALGORITHM;
  278. break;
  279. case NID_sha512:
  280. hash_alg = BCRYPT_SHA512_ALGORITHM;
  281. break;
  282. default:
  283. NOTREACHED();
  284. return ERR_FAILED;
  285. }
  286. if (SSL_is_signature_algorithm_rsa_pss(algorithm)) {
  287. pss_padding_info.pszAlgId = hash_alg;
  288. pss_padding_info.cbSalt = EVP_MD_size(md);
  289. padding_info = &pss_padding_info;
  290. flags |= BCRYPT_PAD_PSS;
  291. } else {
  292. pkcs1_padding_info.pszAlgId = hash_alg;
  293. padding_info = &pkcs1_padding_info;
  294. flags |= BCRYPT_PAD_PKCS1;
  295. }
  296. }
  297. DWORD signature_len;
  298. SECURITY_STATUS status =
  299. NCryptSignHash(key_, padding_info, const_cast<BYTE*>(digest),
  300. digest_len, nullptr, 0, &signature_len, flags);
  301. if (FAILED(status)) {
  302. LOG(ERROR) << "NCryptSignHash failed: " << status;
  303. return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
  304. }
  305. signature->resize(signature_len);
  306. status = NCryptSignHash(key_, padding_info, const_cast<BYTE*>(digest),
  307. digest_len, signature->data(), signature_len,
  308. &signature_len, flags);
  309. if (FAILED(status)) {
  310. LOG(ERROR) << "NCryptSignHash failed: " << status;
  311. return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
  312. }
  313. signature->resize(signature_len);
  314. // CNG emits raw ECDSA signatures, but BoringSSL expects a DER-encoded
  315. // ECDSA-Sig-Value.
  316. if (type_ == EVP_PKEY_EC) {
  317. if (signature->size() % 2 != 0) {
  318. LOG(ERROR) << "Bad signature length";
  319. return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
  320. }
  321. size_t order_len = signature->size() / 2;
  322. // Convert the RAW ECDSA signature to a DER-encoded ECDSA-Sig-Value.
  323. bssl::UniquePtr<ECDSA_SIG> sig(ECDSA_SIG_new());
  324. if (!sig || !BN_bin2bn(signature->data(), order_len, sig->r) ||
  325. !BN_bin2bn(signature->data() + order_len, order_len, sig->s)) {
  326. return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
  327. }
  328. int len = i2d_ECDSA_SIG(sig.get(), nullptr);
  329. if (len <= 0)
  330. return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
  331. signature->resize(len);
  332. uint8_t* ptr = signature->data();
  333. len = i2d_ECDSA_SIG(sig.get(), &ptr);
  334. if (len <= 0)
  335. return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
  336. signature->resize(len);
  337. }
  338. return OK;
  339. }
  340. private:
  341. std::wstring provider_name_;
  342. NCRYPT_KEY_HANDLE key_;
  343. int type_;
  344. size_t max_length_;
  345. };
  346. } // namespace
  347. scoped_refptr<SSLPrivateKey> WrapCAPIPrivateKey(
  348. const X509Certificate* certificate,
  349. crypto::ScopedHCRYPTPROV prov,
  350. DWORD key_spec) {
  351. return base::MakeRefCounted<ThreadedSSLPrivateKey>(
  352. std::make_unique<SSLPlatformKeyCAPI>(std::move(prov), key_spec),
  353. GetSSLPlatformKeyTaskRunner());
  354. }
  355. scoped_refptr<SSLPrivateKey> WrapCNGPrivateKey(
  356. const X509Certificate* certificate,
  357. NCRYPT_KEY_HANDLE key) {
  358. // Rather than query the private key for metadata, extract the public key from
  359. // the certificate without using Windows APIs. CNG does not consistently work
  360. // depending on the system. See https://crbug.com/468345.
  361. int key_type;
  362. size_t max_length;
  363. if (!GetClientCertInfo(certificate, &key_type, &max_length)) {
  364. NCryptFreeObject(key);
  365. return nullptr;
  366. }
  367. return base::MakeRefCounted<ThreadedSSLPrivateKey>(
  368. std::make_unique<SSLPlatformKeyCNG>(key, key_type, max_length),
  369. GetSSLPlatformKeyTaskRunner());
  370. }
  371. scoped_refptr<SSLPrivateKey> FetchClientCertPrivateKey(
  372. const X509Certificate* certificate,
  373. PCCERT_CONTEXT cert_context) {
  374. HCRYPTPROV_OR_NCRYPT_KEY_HANDLE prov_or_key = 0;
  375. DWORD key_spec = 0;
  376. BOOL must_free = FALSE;
  377. DWORD flags = CRYPT_ACQUIRE_PREFER_NCRYPT_KEY_FLAG;
  378. if (!CryptAcquireCertificatePrivateKey(cert_context, flags, nullptr,
  379. &prov_or_key, &key_spec, &must_free)) {
  380. PLOG(WARNING) << "Could not acquire private key";
  381. return nullptr;
  382. }
  383. // Should never get a cached handle back - ownership must always be
  384. // transferred.
  385. CHECK_EQ(must_free, TRUE);
  386. if (key_spec == CERT_NCRYPT_KEY_SPEC) {
  387. return WrapCNGPrivateKey(certificate, prov_or_key);
  388. } else {
  389. return WrapCAPIPrivateKey(certificate,
  390. crypto::ScopedHCRYPTPROV(prov_or_key), key_spec);
  391. }
  392. }
  393. } // namespace net