| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 "base/hmac.h" | 5 #include "base/hmac.h" |
| 6 | 6 |
| 7 #include <windows.h> | 7 #include <windows.h> |
| 8 #include <wincrypt.h> | 8 #include <wincrypt.h> |
| 9 | 9 |
| 10 #include <algorithm> | 10 #include <algorithm> |
| 11 #include <vector> | 11 #include <vector> |
| 12 | 12 |
| 13 #include "base/logging.h" | 13 #include "base/logging.h" |
| 14 | 14 |
| 15 namespace base { | 15 namespace base { |
| 16 | 16 |
| 17 struct HMACPlatformData { | 17 struct HMACPlatformData { |
| 18 // Windows Crypt API resources. | 18 // Windows Crypt API resources. |
| 19 HCRYPTPROV provider_; | 19 HCRYPTPROV provider_; |
| 20 HCRYPTHASH hash_; | 20 HCRYPTHASH hash_; |
| 21 HCRYPTKEY hkey_; | 21 HCRYPTKEY hkey_; |
| 22 }; | 22 }; |
| 23 | 23 |
| 24 HMAC::HMAC(HashAlgorithm hash_alg, const unsigned char* key, int key_length) | 24 HMAC::HMAC(HashAlgorithm hash_alg) |
| 25 : hash_alg_(hash_alg), plat_(new HMACPlatformData()) { | 25 : hash_alg_(hash_alg), plat_(new HMACPlatformData()) { |
| 26 // Only SHA-1 digest is supported now. |
| 27 DCHECK(hash_alg_ == SHA1); |
| 28 } |
| 29 |
| 30 bool HMAC::Init(const unsigned char *key, int key_length) { |
| 31 if (plat_->provider_ || plat_->hkey_) { |
| 32 // Init must not be called more than once on the same HMAC object. |
| 33 NOTREACHED(); |
| 34 return false; |
| 35 } |
| 36 |
| 26 if (!CryptAcquireContext(&plat_->provider_, NULL, NULL, | 37 if (!CryptAcquireContext(&plat_->provider_, NULL, NULL, |
| 27 PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) | 38 PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { |
| 39 NOTREACHED(); |
| 28 plat_->provider_ = NULL; | 40 plat_->provider_ = NULL; |
| 41 return false; |
| 42 } |
| 29 | 43 |
| 30 // This code doesn't work on Win2k because PLAINTEXTKEYBLOB and | 44 // This code doesn't work on Win2k because PLAINTEXTKEYBLOB and |
| 31 // CRYPT_IPSEC_HMAC_KEY are not supported on Windows 2000. PLAINTEXTKEYBLOB | 45 // CRYPT_IPSEC_HMAC_KEY are not supported on Windows 2000. PLAINTEXTKEYBLOB |
| 32 // allows the import of an unencrypted key. For Win2k support, a cubmbersome | 46 // allows the import of an unencrypted key. For Win2k support, a cubmbersome |
| 33 // exponent-of-one key procedure must be used: | 47 // exponent-of-one key procedure must be used: |
| 34 // http://support.microsoft.com/kb/228786/en-us | 48 // http://support.microsoft.com/kb/228786/en-us |
| 35 // CRYPT_IPSEC_HMAC_KEY allows keys longer than 16 bytes. | 49 // CRYPT_IPSEC_HMAC_KEY allows keys longer than 16 bytes. |
| 36 | 50 |
| 37 struct KeyBlob { | 51 struct KeyBlob { |
| 38 BLOBHEADER header; | 52 BLOBHEADER header; |
| 39 DWORD key_size; | 53 DWORD key_size; |
| 40 BYTE key_data[1]; | 54 BYTE key_data[1]; |
| 41 }; | 55 }; |
| 42 size_t key_blob_size = std::max(offsetof(KeyBlob, key_data) + key_length, | 56 size_t key_blob_size = std::max(offsetof(KeyBlob, key_data) + key_length, |
| 43 sizeof(KeyBlob)); | 57 sizeof(KeyBlob)); |
| 44 std::vector<BYTE> key_blob_storage = std::vector<BYTE>(key_blob_size); | 58 std::vector<BYTE> key_blob_storage = std::vector<BYTE>(key_blob_size); |
| 45 KeyBlob* key_blob = reinterpret_cast<KeyBlob*>(&key_blob_storage[0]); | 59 KeyBlob* key_blob = reinterpret_cast<KeyBlob*>(&key_blob_storage[0]); |
| 46 key_blob->header.bType = PLAINTEXTKEYBLOB; | 60 key_blob->header.bType = PLAINTEXTKEYBLOB; |
| 47 key_blob->header.bVersion = CUR_BLOB_VERSION; | 61 key_blob->header.bVersion = CUR_BLOB_VERSION; |
| 48 key_blob->header.reserved = 0; | 62 key_blob->header.reserved = 0; |
| 49 key_blob->header.aiKeyAlg = CALG_RC2; | 63 key_blob->header.aiKeyAlg = CALG_RC2; |
| 50 key_blob->key_size = key_length; | 64 key_blob->key_size = key_length; |
| 51 memcpy(key_blob->key_data, key, key_length); | 65 memcpy(key_blob->key_data, key, key_length); |
| 52 | 66 |
| 53 if (!CryptImportKey(plat_->provider_, &key_blob_storage[0], | 67 if (!CryptImportKey(plat_->provider_, &key_blob_storage[0], |
| 54 key_blob_storage.size(), 0, CRYPT_IPSEC_HMAC_KEY, | 68 key_blob_storage.size(), 0, CRYPT_IPSEC_HMAC_KEY, |
| 55 &plat_->hkey_)) { | 69 &plat_->hkey_)) { |
| 70 NOTREACHED(); |
| 56 plat_->hkey_ = NULL; | 71 plat_->hkey_ = NULL; |
| 72 return false; |
| 57 } | 73 } |
| 58 | 74 |
| 59 // Destroy the copy of the key. | 75 // Destroy the copy of the key. |
| 60 SecureZeroMemory(key_blob->key_data, key_length); | 76 SecureZeroMemory(key_blob->key_data, key_length); |
| 77 |
| 78 return true; |
| 61 } | 79 } |
| 62 | 80 |
| 63 HMAC::~HMAC() { | 81 HMAC::~HMAC() { |
| 64 if (plat_->hkey_) | 82 BOOL ok; |
| 65 CryptDestroyKey(plat_->hkey_); | 83 if (plat_->hkey_) { |
| 66 if (plat_->hash_) | 84 ok = CryptDestroyKey(plat_->hkey_); |
| 67 CryptDestroyHash(plat_->hash_); | 85 DCHECK(ok); |
| 68 if (plat_->provider_) | 86 } |
| 69 CryptReleaseContext(plat_->provider_, 0); | 87 if (plat_->hash_) { |
| 88 ok = CryptDestroyHash(plat_->hash_); |
| 89 DCHECK(ok); |
| 90 } |
| 91 if (plat_->provider_) { |
| 92 ok = CryptReleaseContext(plat_->provider_, 0); |
| 93 DCHECK(ok); |
| 94 } |
| 70 } | 95 } |
| 71 | 96 |
| 72 bool HMAC::Sign(const std::string& data, | 97 bool HMAC::Sign(const std::string& data, |
| 73 unsigned char* digest, | 98 unsigned char* digest, |
| 74 int digest_length) { | 99 int digest_length) { |
| 75 if (!plat_->provider_ || !plat_->hkey_) | 100 if (!plat_->provider_ || !plat_->hkey_) |
| 76 return false; | 101 return false; |
| 77 | 102 |
| 78 if (hash_alg_ != SHA1) { | 103 if (hash_alg_ != SHA1) { |
| 79 NOTREACHED(); | 104 NOTREACHED(); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 97 return false; | 122 return false; |
| 98 | 123 |
| 99 DWORD sha1_size = digest_length; | 124 DWORD sha1_size = digest_length; |
| 100 if (!CryptGetHashParam(plat_->hash_, HP_HASHVAL, digest, &sha1_size, 0)) | 125 if (!CryptGetHashParam(plat_->hash_, HP_HASHVAL, digest, &sha1_size, 0)) |
| 101 return false; | 126 return false; |
| 102 | 127 |
| 103 return true; | 128 return true; |
| 104 } | 129 } |
| 105 | 130 |
| 106 } // namespace base | 131 } // namespace base |
| OLD | NEW |