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 |
| 7 #include <algorithm> |
| 8 #include <vector> |
| 9 |
6 #include "base/logging.h" | 10 #include "base/logging.h" |
7 | 11 |
| 12 namespace base { |
| 13 |
8 HMAC::HMAC(HashAlgorithm hash_alg, const unsigned char* key, int key_length) | 14 HMAC::HMAC(HashAlgorithm hash_alg, const unsigned char* key, int key_length) |
9 : hash_alg_(hash_alg), | 15 : hash_alg_(hash_alg), |
10 provider_(NULL), | 16 provider_(NULL), |
11 hash_(NULL), | 17 hash_(NULL), |
12 hkey_(NULL) { | 18 hkey_(NULL) { |
13 if (!CryptAcquireContext(&provider_, NULL, NULL, | 19 if (!CryptAcquireContext(&provider_, NULL, NULL, |
14 PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) | 20 PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) |
15 provider_ = NULL; | 21 provider_ = NULL; |
16 ImportKey(key, key_length); | 22 ImportKey(key, key_length); |
17 } | 23 } |
(...skipping 16 matching lines...) Expand all Loading... |
34 switch (hash_alg_) { | 40 switch (hash_alg_) { |
35 case SHA1: | 41 case SHA1: |
36 return SignWithSHA1(data, digest, digest_length); | 42 return SignWithSHA1(data, digest, digest_length); |
37 default: | 43 default: |
38 NOTREACHED(); | 44 NOTREACHED(); |
39 return false; | 45 return false; |
40 } | 46 } |
41 } | 47 } |
42 | 48 |
43 void HMAC::ImportKey(const unsigned char* key, int key_length) { | 49 void HMAC::ImportKey(const unsigned char* key, int key_length) { |
44 if (key_length > kMaxKeySize) { | 50 // This code doesn't work on Win2k because PLAINTEXTKEYBLOB and |
45 NOTREACHED(); | 51 // CRYPT_IPSEC_HMAC_KEY are not supported on Windows 2000. PLAINTEXTKEYBLOB |
46 return; | 52 // allows the import of an unencrypted key. For Win2k support, a cubmbersome |
| 53 // exponent-of-one key procedure must be used: |
| 54 // http://support.microsoft.com/kb/228786/en-us |
| 55 // CRYPT_IPSEC_HMAC_KEY allows keys longer than 16 bytes. |
| 56 |
| 57 struct KeyBlob { |
| 58 BLOBHEADER header; |
| 59 DWORD key_size; |
| 60 BYTE key_data[1]; |
| 61 }; |
| 62 size_t key_blob_size = std::max(offsetof(KeyBlob, key_data) + key_length, |
| 63 sizeof(KeyBlob)); |
| 64 std::vector<BYTE> key_blob_storage = std::vector<BYTE>(key_blob_size); |
| 65 KeyBlob* key_blob = reinterpret_cast<KeyBlob*>(&key_blob_storage[0]); |
| 66 key_blob->header.bType = PLAINTEXTKEYBLOB; |
| 67 key_blob->header.bVersion = CUR_BLOB_VERSION; |
| 68 key_blob->header.reserved = 0; |
| 69 key_blob->header.aiKeyAlg = CALG_RC2; |
| 70 key_blob->key_size = key_length; |
| 71 memcpy(key_blob->key_data, key, key_length); |
| 72 |
| 73 if (!CryptImportKey(provider_, &key_blob_storage[0], key_blob_storage.size(), |
| 74 0, CRYPT_IPSEC_HMAC_KEY, &hkey_)) { |
| 75 hkey_ = NULL; |
47 } | 76 } |
48 | 77 |
49 struct { | |
50 BLOBHEADER header; | |
51 DWORD key_size; | |
52 BYTE key_data[kMaxKeySize]; | |
53 } key_blob; | |
54 key_blob.header.bType = PLAINTEXTKEYBLOB; | |
55 key_blob.header.bVersion = CUR_BLOB_VERSION; | |
56 key_blob.header.reserved = 0; | |
57 key_blob.header.aiKeyAlg = CALG_RC2; | |
58 key_blob.key_size = key_length; | |
59 memcpy(key_blob.key_data, key, key_length); | |
60 | |
61 if (!CryptImportKey(provider_, | |
62 reinterpret_cast<const BYTE *>(&key_blob), | |
63 sizeof(key_blob), 0, 0, &hkey_)) | |
64 hkey_ = NULL; | |
65 | |
66 // Destroy the copy of the key. | 78 // Destroy the copy of the key. |
67 SecureZeroMemory(key_blob.key_data, key_length); | 79 SecureZeroMemory(key_blob->key_data, key_length); |
68 } | 80 } |
69 | 81 |
70 bool HMAC::SignWithSHA1(const std::string& data, | 82 bool HMAC::SignWithSHA1(const std::string& data, |
71 unsigned char* digest, | 83 unsigned char* digest, |
72 int digest_length) { | 84 int digest_length) { |
73 DCHECK(provider_); | 85 DCHECK(provider_); |
74 DCHECK(hkey_); | 86 DCHECK(hkey_); |
75 | 87 |
76 if (!CryptCreateHash(provider_, CALG_HMAC, hkey_, 0, &hash_)) | 88 if (!CryptCreateHash(provider_, CALG_HMAC, hkey_, 0, &hash_)) |
77 return false; | 89 return false; |
(...skipping 10 matching lines...) Expand all Loading... |
88 static_cast<DWORD>(data.size()), 0)) | 100 static_cast<DWORD>(data.size()), 0)) |
89 return false; | 101 return false; |
90 | 102 |
91 DWORD sha1_size = digest_length; | 103 DWORD sha1_size = digest_length; |
92 if (!CryptGetHashParam(hash_, HP_HASHVAL, digest, &sha1_size, 0)) | 104 if (!CryptGetHashParam(hash_, HP_HASHVAL, digest, &sha1_size, 0)) |
93 return false; | 105 return false; |
94 | 106 |
95 return true; | 107 return true; |
96 } | 108 } |
97 | 109 |
| 110 } // namespace base |
OLD | NEW |