diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/base/keygen_handler_win.cc | 124 | ||||
-rw-r--r-- | net/http/des.cc | 108 |
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 |