summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/base/keygen_handler_win.cc124
-rw-r--r--net/http/des.cc108
2 files changed, 110 insertions, 122 deletions
diff --git a/net/base/keygen_handler_win.cc b/net/base/keygen_handler_win.cc
index 15d8583..6d30da6 100644
--- a/net/base/keygen_handler_win.cc
+++ b/net/base/keygen_handler_win.cc
@@ -17,6 +17,7 @@
#include "base/base64.h"
#include "base/basictypes.h"
#include "base/crypto/capi_util.h"
+#include "base/crypto/scoped_capi_types.h"
#include "base/logging.h"
#include "base/string_piece.h"
#include "base/string_util.h"
@@ -130,90 +131,93 @@ std::wstring GetNewKeyContainerId() {
return result;
}
-std::string KeygenHandler::GenKeyAndSignChallenge() {
- std::string 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;
+ base::CryptAcquireContextLocked(&provider, key_id_.c_str(), NULL,
+ PROV_RSA_FULL, CRYPT_SILENT | CRYPT_DELETEKEYSET);
+ }
+ }
+ }
- bool is_success = true;
- HCRYPTPROV prov = NULL;
- HCRYPTKEY key = NULL;
- DWORD flags = (key_size_in_bits_ << 16) | CRYPT_EXPORTABLE;
- std::string spkac;
+ base::ScopedHCRYPTPROV provider_;
+ std::wstring key_id_;
- std::wstring new_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;
- BOOL ok = FALSE;
- for (int attempt = 0; attempt < kMaxAttempts; ++attempt) {
+ 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.
- new_key_id = GetNewKeyContainerId();
- if (new_key_id.empty())
- return result;
+ 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.
- ok = base::CryptAcquireContextLocked(&prov, new_key_id.c_str(), NULL,
- PROV_RSA_FULL,
- CRYPT_SILENT | CRYPT_NEWKEYSET);
-
- if (ok || GetLastError() != NTE_BAD_KEYSET)
+ if (base::CryptAcquireContextLocked(key_container.provider_.receive(),
+ key_container.key_id_.c_str(), NULL, PROV_RSA_FULL,
+ CRYPT_SILENT | CRYPT_NEWKEYSET))
break;
- }
- if (!ok) {
- LOG(ERROR) << "Couldn't acquire a CryptoAPI provider context: "
- << GetLastError();
- is_success = false;
- goto failure;
- }
- if (!CryptGenKey(prov, CALG_RSA_KEYX, flags, &key)) {
- LOG(ERROR) << "Couldn't generate an RSA key";
- is_success = false;
- goto failure;
+ if (GetLastError() != NTE_BAD_KEYSET) {
+ LOG(ERROR) << "Keygen failed: Couldn't acquire a CryptoAPI provider "
+ "context: " << GetLastError();
+ return std::string();
+ }
}
-
- if (!GetSignedPublicKeyAndChallenge(prov, challenge_, &spkac)) {
- LOG(ERROR) << "Couldn't generate the signed public key and challenge";
- is_success = false;
- goto failure;
+ if (attempt == kMaxAttempts) {
+ LOG(ERROR) << "Keygen failed: Couldn't acquire a CryptoAPI provider "
+ "context: Max retries exceeded";
+ return std::string();
}
- if (!base::Base64Encode(spkac, &result)) {
- LOG(ERROR) << "Couldn't convert signed key into base64";
- is_success = false;
- goto failure;
- }
+ {
+ base::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();
+ }
- failure:
- if (!is_success)
- LOG(ERROR) << "SSL Keygen failed";
- else
- VLOG(1) << "SSL Key succeeded";
- if (key) {
- // Securely destroys the handle, but leaves the underlying key alone. The
- // key can be obtained again by resolving the key location. If
- // |stores_key_| is false, the underlying key will be destroyed below.
- CryptDestroyKey(key);
- }
+ 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();
+ }
- if (prov) {
- CryptReleaseContext(prov, 0);
- prov = NULL;
- if (!stores_key_) {
- // Fully destroys any of the keys that were created and releases prov.
- base::CryptAcquireContextLocked(&prov, new_key_id.c_str(), NULL,
- PROV_RSA_FULL,
- CRYPT_SILENT | CRYPT_DELETEKEYSET);
+ std::string result;
+ if (!base::Base64Encode(spkac, &result)) {
+ LOG(ERROR) << "Keygen failed: Couldn't convert signed key into base64";
+ return std::string();
}
- }
- return result;
+ VLOG(1) << "Keygen succeeded";
+ return result;
+ }
}
} // namespace net
diff --git a/net/http/des.cc b/net/http/des.cc
index 0ca12b9..775f902 100644
--- a/net/http/des.cc
+++ b/net/http/des.cc
@@ -1,22 +1,21 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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/http/des.h"
+#include "base/logging.h"
+
#if defined(USE_NSS)
#include <nss.h>
#include <pk11pub.h>
+#include "base/nss_util.h"
#elif defined(OS_MACOSX)
#include <CommonCrypto/CommonCryptor.h>
#elif defined(OS_WIN)
#include <windows.h>
#include <wincrypt.h>
-#endif
-
-#include "base/logging.h"
-#if defined(USE_NSS)
-#include "base/nss_util.h"
+#include "base/crypto/scoped_capi_types.h"
#endif
// The Mac and Windows (CryptoAPI) versions of DESEncrypt are our own code.
@@ -156,63 +155,48 @@ void DESEncrypt(const uint8* key, const uint8* src, uint8* hash) {
#elif defined(OS_WIN)
void DESEncrypt(const uint8* key, const uint8* src, uint8* hash) {
- HCRYPTPROV provider;
- HCRYPTKEY hkey = NULL;
-
- if (!CryptAcquireContext(&provider, NULL, NULL,
- PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
- provider = NULL;
- goto done;
+ base::ScopedHCRYPTPROV provider;
+ if (!CryptAcquireContext(provider.receive(), NULL, NULL, PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT))
+ return;
+
+ {
+ // Import the DES key.
+ struct KeyBlob {
+ BLOBHEADER header;
+ DWORD key_size;
+ BYTE key_data[8];
+ };
+ KeyBlob key_blob;
+ key_blob.header.bType = PLAINTEXTKEYBLOB;
+ key_blob.header.bVersion = CUR_BLOB_VERSION;
+ key_blob.header.reserved = 0;
+ key_blob.header.aiKeyAlg = CALG_DES;
+ key_blob.key_size = 8; // 64 bits
+ memcpy(key_blob.key_data, key, 8);
+
+ base::ScopedHCRYPTKEY key;
+ BOOL import_ok = CryptImportKey(provider,
+ reinterpret_cast<BYTE*>(&key_blob),
+ sizeof key_blob, 0, 0, key.receive());
+ // Destroy the copy of the key.
+ SecureZeroMemory(key_blob.key_data, sizeof key_blob.key_data);
+ if (!import_ok)
+ return;
+
+ // No initialization vector required.
+ DWORD cipher_mode = CRYPT_MODE_ECB;
+ if (!CryptSetKeyParam(key, KP_MODE, reinterpret_cast<BYTE*>(&cipher_mode),
+ 0))
+ return;
+
+ // CryptoAPI requires us to copy the plaintext to the output buffer first.
+ CopyMemory(hash, src, 8);
+ // Pass a 'Final' of FALSE, otherwise CryptEncrypt appends one additional
+ // block of padding to the data.
+ DWORD hash_len = 8;
+ CryptEncrypt(key, 0, FALSE, 0, hash, &hash_len, 8);
}
-
- // Import the DES key.
- // This code doesn't work on Win2k because PLAINTEXTKEYBLOB is not supported
- // on Windows 2000. PLAINTEXTKEYBLOB allows the import of an unencrypted
- // key. For Win2k support, a cubmbersome exponent-of-one key procedure must
- // be used:
- // http://support.microsoft.com/kb/228786/en-us
-
- struct KeyBlob {
- BLOBHEADER header;
- DWORD key_size;
- BYTE key_data[8];
- };
- KeyBlob key_blob;
- key_blob.header.bType = PLAINTEXTKEYBLOB;
- key_blob.header.bVersion = CUR_BLOB_VERSION;
- key_blob.header.reserved = 0;
- key_blob.header.aiKeyAlg = CALG_DES;
- key_blob.key_size = 8; // 64 bits
- memcpy(key_blob.key_data, key, 8);
-
- if (!CryptImportKey(provider, reinterpret_cast<BYTE*>(&key_blob),
- sizeof(key_blob), 0, 0, &hkey)) {
- hkey = NULL;
- goto done;
- }
-
- // Destroy the copy of the key.
- SecureZeroMemory(key_blob.key_data, sizeof(key_blob.key_data));
-
- // No initialization vector required.
- DWORD cipher_mode = CRYPT_MODE_ECB;
- if (!CryptSetKeyParam(hkey, KP_MODE,
- reinterpret_cast<BYTE*>(&cipher_mode), 0))
- goto done;
-
- // CryptoAPI requires us to copy the plaintext to the output buffer first.
- CopyMemory(hash, src, 8);
- // Pass a 'Final' of FALSE, otherwise CryptEncrypt appends one additional
- // block of padding to the data.
- DWORD hash_len = 8;
- if (!CryptEncrypt(hkey, NULL, FALSE, 0, hash, &hash_len, 8))
- goto done;
-
- done:
- if (hkey)
- CryptDestroyKey(hkey);
- if (provider)
- CryptReleaseContext(provider, 0);
}
#endif