Index: net/base/keygen_handler_win.cc |
diff --git a/net/base/keygen_handler_win.cc b/net/base/keygen_handler_win.cc |
deleted file mode 100644 |
index f88e7e12579d899bd6b7c24275f06a3638a8d84a..0000000000000000000000000000000000000000 |
--- a/net/base/keygen_handler_win.cc |
+++ /dev/null |
@@ -1,218 +0,0 @@ |
-// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "net/base/keygen_handler.h" |
- |
-#include <windows.h> |
-#include <rpc.h> |
- |
-#include <list> |
-#include <string> |
-#include <vector> |
- |
-#include "base/base64.h" |
-#include "base/logging.h" |
-#include "base/strings/string_piece.h" |
-#include "base/strings/string_util.h" |
-#include "base/strings/utf_string_conversions.h" |
-#include "crypto/capi_util.h" |
-#include "crypto/scoped_capi_types.h" |
-#include "crypto/wincrypt_shim.h" |
- |
-namespace net { |
- |
-// Assigns the contents of a CERT_PUBLIC_KEY_INFO structure for the signing |
-// key in |prov| to |output|. Returns true if encoding was successful. |
-bool GetSubjectPublicKeyInfo(HCRYPTPROV prov, std::vector<BYTE>* output) { |
- BOOL ok; |
- DWORD size = 0; |
- |
- // From the private key stored in HCRYPTPROV, obtain the public key, stored |
- // as a CERT_PUBLIC_KEY_INFO structure. Currently, only RSA public keys are |
- // supported. |
- ok = CryptExportPublicKeyInfoEx(prov, AT_KEYEXCHANGE, X509_ASN_ENCODING, |
- const_cast<char*>(szOID_RSA_RSA), 0, NULL, |
- NULL, &size); |
- DCHECK(ok); |
- if (!ok) |
- return false; |
- |
- output->resize(size); |
- |
- PCERT_PUBLIC_KEY_INFO public_key_casted = |
- reinterpret_cast<PCERT_PUBLIC_KEY_INFO>(&(*output)[0]); |
- ok = CryptExportPublicKeyInfoEx(prov, AT_KEYEXCHANGE, X509_ASN_ENCODING, |
- const_cast<char*>(szOID_RSA_RSA), 0, NULL, |
- public_key_casted, &size); |
- DCHECK(ok); |
- if (!ok) |
- return false; |
- |
- output->resize(size); |
- |
- return true; |
-} |
- |
-// Generates a DER encoded SignedPublicKeyAndChallenge structure from the |
-// signing key of |prov| and the specified ASCII |challenge| string and |
-// appends it to |output|. |
-// True if the encoding was successfully generated. |
-bool GetSignedPublicKeyAndChallenge(HCRYPTPROV prov, |
- const std::string& challenge, |
- std::string* output) { |
- base::string16 challenge16 = base::ASCIIToUTF16(challenge); |
- std::vector<BYTE> spki; |
- |
- if (!GetSubjectPublicKeyInfo(prov, &spki)) |
- return false; |
- |
- // PublicKeyAndChallenge ::= SEQUENCE { |
- // spki SubjectPublicKeyInfo, |
- // challenge IA5STRING |
- // } |
- CERT_KEYGEN_REQUEST_INFO pkac; |
- pkac.dwVersion = CERT_KEYGEN_REQUEST_V1; |
- pkac.SubjectPublicKeyInfo = |
- *reinterpret_cast<PCERT_PUBLIC_KEY_INFO>(&spki[0]); |
- pkac.pwszChallengeString = const_cast<base::char16*>(challenge16.c_str()); |
- |
- CRYPT_ALGORITHM_IDENTIFIER sig_alg; |
- memset(&sig_alg, 0, sizeof(sig_alg)); |
- sig_alg.pszObjId = const_cast<char*>(szOID_RSA_MD5RSA); |
- |
- BOOL ok; |
- DWORD size = 0; |
- std::vector<BYTE> signed_pkac; |
- ok = CryptSignAndEncodeCertificate(prov, AT_KEYEXCHANGE, X509_ASN_ENCODING, |
- X509_KEYGEN_REQUEST_TO_BE_SIGNED, |
- &pkac, &sig_alg, NULL, |
- NULL, &size); |
- DCHECK(ok); |
- if (!ok) |
- return false; |
- |
- signed_pkac.resize(size); |
- ok = CryptSignAndEncodeCertificate(prov, AT_KEYEXCHANGE, X509_ASN_ENCODING, |
- X509_KEYGEN_REQUEST_TO_BE_SIGNED, |
- &pkac, &sig_alg, NULL, |
- &signed_pkac[0], &size); |
- DCHECK(ok); |
- if (!ok) |
- return false; |
- |
- output->assign(reinterpret_cast<char*>(&signed_pkac[0]), size); |
- return true; |
-} |
- |
-// Generates a unique name for the container which will store the key that is |
-// generated. The traditional Windows approach is to use a GUID here. |
-std::wstring GetNewKeyContainerId() { |
- RPC_STATUS status = RPC_S_OK; |
- std::wstring result; |
- |
- UUID id = { 0 }; |
- status = UuidCreateSequential(&id); |
- if (status != RPC_S_OK && status != RPC_S_UUID_LOCAL_ONLY) |
- return result; |
- |
- RPC_WSTR rpc_string = NULL; |
- status = UuidToString(&id, &rpc_string); |
- if (status != RPC_S_OK) |
- return result; |
- |
- // RPC_WSTR is unsigned short*. wchar_t is a built-in type of Visual C++, |
- // so the type cast is necessary. |
- result.assign(reinterpret_cast<wchar_t*>(rpc_string)); |
- RpcStringFree(&rpc_string); |
- |
- return result; |
-} |
- |
-// This is a helper struct designed to optionally delete a key after releasing |
-// the associated provider. |
-struct KeyContainer { |
- public: |
- explicit KeyContainer(bool delete_keyset) |
- : delete_keyset_(delete_keyset) {} |
- |
- ~KeyContainer() { |
- if (provider_) { |
- provider_.reset(); |
- if (delete_keyset_ && !key_id_.empty()) { |
- HCRYPTPROV provider; |
- crypto::CryptAcquireContextLocked(&provider, key_id_.c_str(), NULL, |
- PROV_RSA_FULL, CRYPT_SILENT | CRYPT_DELETEKEYSET); |
- } |
- } |
- } |
- |
- crypto::ScopedHCRYPTPROV provider_; |
- std::wstring key_id_; |
- |
- private: |
- bool delete_keyset_; |
-}; |
- |
-std::string KeygenHandler::GenKeyAndSignChallenge() { |
- KeyContainer key_container(!stores_key_); |
- |
- // TODO(rsleevi): Have the user choose which provider they should use, which |
- // needs to be filtered by those providers which can provide the key type |
- // requested or the key size requested. This is especially important for |
- // generating certificates that will be stored on smart cards. |
- const int kMaxAttempts = 5; |
- int attempt; |
- for (attempt = 0; attempt < kMaxAttempts; ++attempt) { |
- // Per MSDN documentation for CryptAcquireContext, if applications will be |
- // creating their own keys, they should ensure unique naming schemes to |
- // prevent overlap with any other applications or consumers of CSPs, and |
- // *should not* store new keys within the default, NULL key container. |
- key_container.key_id_ = GetNewKeyContainerId(); |
- if (key_container.key_id_.empty()) |
- return std::string(); |
- |
- // Only create new key containers, so that existing key containers are not |
- // overwritten. |
- if (crypto::CryptAcquireContextLocked(key_container.provider_.receive(), |
- key_container.key_id_.c_str(), NULL, PROV_RSA_FULL, |
- CRYPT_SILENT | CRYPT_NEWKEYSET)) |
- break; |
- |
- if (GetLastError() != static_cast<DWORD>(NTE_BAD_KEYSET)) { |
- LOG(ERROR) << "Keygen failed: Couldn't acquire a CryptoAPI provider " |
- "context: " << GetLastError(); |
- return std::string(); |
- } |
- } |
- if (attempt == kMaxAttempts) { |
- LOG(ERROR) << "Keygen failed: Couldn't acquire a CryptoAPI provider " |
- "context: Max retries exceeded"; |
- return std::string(); |
- } |
- |
- { |
- crypto::ScopedHCRYPTKEY key; |
- if (!CryptGenKey(key_container.provider_, CALG_RSA_KEYX, |
- (key_size_in_bits_ << 16) | CRYPT_EXPORTABLE, key.receive())) { |
- LOG(ERROR) << "Keygen failed: Couldn't generate an RSA key"; |
- return std::string(); |
- } |
- |
- std::string spkac; |
- if (!GetSignedPublicKeyAndChallenge(key_container.provider_, challenge_, |
- &spkac)) { |
- LOG(ERROR) << "Keygen failed: Couldn't generate the signed public key " |
- "and challenge"; |
- return std::string(); |
- } |
- |
- std::string result; |
- base::Base64Encode(spkac, &result); |
- |
- VLOG(1) << "Keygen succeeded"; |
- return result; |
- } |
-} |
- |
-} // namespace net |