Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(61)

Side by Side Diff: net/base/keygen_handler_win.cc

Issue 2874002: Change the Windows CertDatabase behaviour to match Mac and NSS behaviour, whe... (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: '' Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/base/keygen_handler_unittest.cc ('k') | net/net.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/base/keygen_handler.h" 5 #include "net/base/keygen_handler.h"
6 6
7 #include <windows.h> 7 #include <windows.h>
8 #include <wincrypt.h> 8 #include <wincrypt.h>
9 #pragma comment(lib, "crypt32.lib") 9 #pragma comment(lib, "crypt32.lib")
10 #include <rpc.h> 10 #include <rpc.h>
11 #pragma comment(lib, "rpcrt4.lib") 11 #pragma comment(lib, "rpcrt4.lib")
12 12
13 #include <list> 13 #include <list>
14 #include <string> 14 #include <string>
15 #include <vector> 15 #include <vector>
16 16
17 #include "base/base64.h" 17 #include "base/base64.h"
18 #include "base/basictypes.h" 18 #include "base/basictypes.h"
19 #include "base/logging.h" 19 #include "base/logging.h"
20 #include "base/string_piece.h" 20 #include "base/string_piece.h"
21 #include "base/string_util.h" 21 #include "base/string_util.h"
22 #include "base/utf_string_conversions.h" 22 #include "base/utf_string_conversions.h"
23 23
24 namespace net { 24 namespace net {
25 25
26 bool EncodeAndAppendType(LPCSTR type, const void* to_encode,
27 std::vector<BYTE>* output) {
28 BOOL ok;
29 DWORD size = 0;
30 ok = CryptEncodeObject(X509_ASN_ENCODING, type, to_encode, NULL, &size);
31 DCHECK(ok);
32 if (!ok)
33 return false;
34
35 std::vector<BYTE>::size_type old_size = output->size();
36 output->resize(old_size + size);
37
38 ok = CryptEncodeObject(X509_ASN_ENCODING, type, to_encode,
39 &(*output)[old_size], &size);
40 DCHECK(ok);
41 if (!ok)
42 return false;
43
44 // Sometimes the initial call to CryptEncodeObject gave a generous estimate
45 // of the size, so shrink back to what was actually used.
46 output->resize(old_size + size);
47
48 return true;
49 }
50
51 // Assigns the contents of a CERT_PUBLIC_KEY_INFO structure for the signing 26 // Assigns the contents of a CERT_PUBLIC_KEY_INFO structure for the signing
52 // key in |prov| to |output|. Returns true if encoding was successful. 27 // key in |prov| to |output|. Returns true if encoding was successful.
53 bool GetSubjectPublicKeyInfo(HCRYPTPROV prov, std::vector<BYTE>* output) { 28 bool GetSubjectPublicKeyInfo(HCRYPTPROV prov, std::vector<BYTE>* output) {
54 BOOL ok; 29 BOOL ok;
55 DWORD size = 0; 30 DWORD size = 0;
56 31
57 // From the private key stored in HCRYPTPROV, obtain the public key, stored 32 // From the private key stored in HCRYPTPROV, obtain the public key, stored
58 // as a CERT_PUBLIC_KEY_INFO structure. Currently, only RSA public keys are 33 // as a CERT_PUBLIC_KEY_INFO structure. Currently, only RSA public keys are
59 // supported. 34 // supported.
60 ok = CryptExportPublicKeyInfoEx(prov, AT_KEYEXCHANGE, X509_ASN_ENCODING, 35 ok = CryptExportPublicKeyInfoEx(prov, AT_KEYEXCHANGE, X509_ASN_ENCODING,
(...skipping 11 matching lines...) Expand all
72 &size); 47 &size);
73 DCHECK(ok); 48 DCHECK(ok);
74 if (!ok) 49 if (!ok)
75 return false; 50 return false;
76 51
77 output->resize(size); 52 output->resize(size);
78 53
79 return true; 54 return true;
80 } 55 }
81 56
82 // Appends a DER SubjectPublicKeyInfo structure for the signing key in |prov|
83 // to |output|.
84 // Returns true if encoding was successful.
85 bool EncodeSubjectPublicKeyInfo(HCRYPTPROV prov, std::vector<BYTE>* output) {
86 std::vector<BYTE> public_key_info;
87 if (!GetSubjectPublicKeyInfo(prov, &public_key_info))
88 return false;
89
90 return EncodeAndAppendType(X509_PUBLIC_KEY_INFO, &public_key_info[0],
91 output);
92 }
93
94 // Generates a DER encoded SignedPublicKeyAndChallenge structure from the 57 // Generates a DER encoded SignedPublicKeyAndChallenge structure from the
95 // signing key of |prov| and the specified ASCII |challenge| string and 58 // signing key of |prov| and the specified ASCII |challenge| string and
96 // appends it to |output|. 59 // appends it to |output|.
97 // True if the encoding was successfully generated. 60 // True if the encoding was successfully generated.
98 bool GetSignedPublicKeyAndChallenge(HCRYPTPROV prov, 61 bool GetSignedPublicKeyAndChallenge(HCRYPTPROV prov,
99 const std::string& challenge, 62 const std::string& challenge,
100 std::string* output) { 63 std::string* output) {
101 std::wstring wide_challenge = ASCIIToWide(challenge); 64 std::wstring wide_challenge = ASCIIToWide(challenge);
102 std::vector<BYTE> spki; 65 std::vector<BYTE> spki;
103 66
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
159 return result; 122 return result;
160 123
161 // RPC_WSTR is unsigned short*. wchar_t is a built-in type of Visual C++, 124 // RPC_WSTR is unsigned short*. wchar_t is a built-in type of Visual C++,
162 // so the type cast is necessary. 125 // so the type cast is necessary.
163 result.assign(reinterpret_cast<wchar_t*>(rpc_string)); 126 result.assign(reinterpret_cast<wchar_t*>(rpc_string));
164 RpcStringFree(&rpc_string); 127 RpcStringFree(&rpc_string);
165 128
166 return result; 129 return result;
167 } 130 }
168 131
169 void StoreKeyLocationInCache(HCRYPTPROV prov) {
170 BOOL ok;
171 DWORD size = 0;
172
173 // Though it is known the container and provider name, as they are supplied
174 // during GenKeyAndSignChallenge, explicitly resolving them via
175 // CryptGetProvParam ensures that any defaults (such as provider name being
176 // NULL) or any CSP modifications to the container name are properly
177 // reflected.
178
179 // Find the container name. Though the MSDN documentation states it will
180 // return the exact same value as supplied when the provider was aquired, it
181 // also notes the return type will be CHAR, /not/ WCHAR.
182 ok = CryptGetProvParam(prov, PP_CONTAINER, NULL, &size, 0);
183 if (!ok)
184 return;
185
186 std::vector<BYTE> buffer(size);
187 ok = CryptGetProvParam(prov, PP_CONTAINER, &buffer[0], &size, 0);
188 if (!ok)
189 return;
190
191 KeygenHandler::KeyLocation key_location;
192 UTF8ToWide(reinterpret_cast<char*>(&buffer[0]), size,
193 &key_location.container_name);
194
195 // Get the provider name. This will always resolve, even if NULL (indicating
196 // the default provider) was supplied to the CryptAcquireContext.
197 size = 0;
198 ok = CryptGetProvParam(prov, PP_NAME, NULL, &size, 0);
199 if (!ok)
200 return;
201
202 buffer.resize(size);
203 ok = CryptGetProvParam(prov, PP_NAME, &buffer[0], &size, 0);
204 if (!ok)
205 return;
206
207 UTF8ToWide(reinterpret_cast<char*>(&buffer[0]), size,
208 &key_location.provider_name);
209
210 std::vector<BYTE> public_key_info;
211 if (!EncodeSubjectPublicKeyInfo(prov, &public_key_info))
212 return;
213
214 KeygenHandler::Cache* cache = KeygenHandler::Cache::GetInstance();
215 cache->Insert(std::string(public_key_info.begin(), public_key_info.end()),
216 key_location);
217 }
218
219 bool KeygenHandler::KeyLocation::Equals(
220 const KeygenHandler::KeyLocation& location) const {
221 return container_name == location.container_name &&
222 provider_name == location.provider_name;
223 }
224
225 std::string KeygenHandler::GenKeyAndSignChallenge() { 132 std::string KeygenHandler::GenKeyAndSignChallenge() {
226 std::string result; 133 std::string result;
227 134
228 bool is_success = true; 135 bool is_success = true;
229 HCRYPTPROV prov = NULL; 136 HCRYPTPROV prov = NULL;
230 HCRYPTKEY key = NULL; 137 HCRYPTKEY key = NULL;
231 DWORD flags = (key_size_in_bits_ << 16) | CRYPT_EXPORTABLE; 138 DWORD flags = (key_size_in_bits_ << 16) | CRYPT_EXPORTABLE;
232 std::string spkac; 139 std::string spkac;
233 140
234 std::wstring new_key_id; 141 std::wstring new_key_id;
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 is_success = false; 181 is_success = false;
275 goto failure; 182 goto failure;
276 } 183 }
277 184
278 if (!base::Base64Encode(spkac, &result)) { 185 if (!base::Base64Encode(spkac, &result)) {
279 LOG(ERROR) << "Couldn't convert signed key into base64"; 186 LOG(ERROR) << "Couldn't convert signed key into base64";
280 is_success = false; 187 is_success = false;
281 goto failure; 188 goto failure;
282 } 189 }
283 190
284 StoreKeyLocationInCache(prov);
285
286 failure: 191 failure:
287 if (!is_success) { 192 if (!is_success) {
288 LOG(ERROR) << "SSL Keygen failed"; 193 LOG(ERROR) << "SSL Keygen failed";
289 } else { 194 } else {
290 LOG(INFO) << "SSL Key succeeded"; 195 LOG(INFO) << "SSL Key succeeded";
291 } 196 }
292 if (key) { 197 if (key) {
293 // Securely destroys the handle, but leaves the underlying key alone. The 198 // Securely destroys the handle, but leaves the underlying key alone. The
294 // key can be obtained again by resolving the key location. If 199 // key can be obtained again by resolving the key location. If
295 // |stores_key_| is false, the underlying key will be destroyed below. 200 // |stores_key_| is false, the underlying key will be destroyed below.
296 CryptDestroyKey(key); 201 CryptDestroyKey(key);
297 } 202 }
298 203
299 if (prov) { 204 if (prov) {
300 CryptReleaseContext(prov, 0); 205 CryptReleaseContext(prov, 0);
301 prov = NULL; 206 prov = NULL;
302 if (!stores_key_) { 207 if (!stores_key_) {
303 // Fully destroys any of the keys that were created and releases prov. 208 // Fully destroys any of the keys that were created and releases prov.
304 CryptAcquireContext(&prov, new_key_id.c_str(), NULL, PROV_RSA_FULL, 209 CryptAcquireContext(&prov, new_key_id.c_str(), NULL, PROV_RSA_FULL,
305 CRYPT_SILENT | CRYPT_DELETEKEYSET); 210 CRYPT_SILENT | CRYPT_DELETEKEYSET);
306 } 211 }
307 } 212 }
308 213
309 return result; 214 return result;
310 } 215 }
311 216
312 } // namespace net 217 } // namespace net
OLDNEW
« no previous file with comments | « net/base/keygen_handler_unittest.cc ('k') | net/net.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698