blob: ee86ebde3526f2d2f9c53580c32aa844a15f41db [file] [log] [blame]
initial.commit3f4a7322008-07-27 06:49:38 +09001// Copyright 2008, Google Inc.
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8// * Redistributions of source code must retain the above copyright
9// notice, this list of conditions and the following disclaimer.
10// * Redistributions in binary form must reproduce the above
11// copyright notice, this list of conditions and the following disclaimer
12// in the documentation and/or other materials provided with the
13// distribution.
14// * Neither the name of Google Inc. nor the names of its
15// contributors may be used to endorse or promote products derived from
16// this software without specific prior written permission.
17//
18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30#include "base/hmac.h"
31#include "base/logging.h"
32
33HMAC::HMAC(HashAlgorithm hash_alg, const unsigned char* key, int key_length)
34 : hash_alg_(hash_alg),
35 provider_(NULL),
36 hash_(NULL),
37 hkey_(NULL) {
38 if (!CryptAcquireContext(&provider_, NULL, NULL,
39 PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
40 provider_ = NULL;
41 ImportKey(key, key_length);
42}
43
44HMAC::~HMAC() {
45 if (hkey_)
46 CryptDestroyKey(hkey_);
47 if (hash_)
48 CryptDestroyHash(hash_);
49 if (provider_)
50 CryptReleaseContext(provider_, 0);
51}
52
53bool HMAC::Sign(const std::string& data,
54 unsigned char* digest,
55 int digest_length) {
56 if (!provider_ || !hkey_)
57 return false;
58
59 switch (hash_alg_) {
60 case SHA1:
61 return SignWithSHA1(data, digest, digest_length);
62 default:
63 NOTREACHED();
64 return false;
65 }
66}
67
68void HMAC::ImportKey(const unsigned char* key, int key_length) {
69 if (key_length > kMaxKeySize) {
70 NOTREACHED();
71 return;
72 }
73
74 struct {
75 BLOBHEADER header;
76 DWORD key_size;
77 BYTE key_data[kMaxKeySize];
78 } key_blob;
79 key_blob.header.bType = PLAINTEXTKEYBLOB;
80 key_blob.header.bVersion = CUR_BLOB_VERSION;
81 key_blob.header.reserved = 0;
82 key_blob.header.aiKeyAlg = CALG_RC2;
83 key_blob.key_size = key_length;
84 memcpy(key_blob.key_data, key, key_length);
85
86 if (!CryptImportKey(provider_,
87 reinterpret_cast<const BYTE *>(&key_blob),
88 sizeof(key_blob), 0, 0, &hkey_))
89 hkey_ = NULL;
90
91 // Destroy the copy of the key.
92 SecureZeroMemory(key_blob.key_data, key_length);
93}
94
95bool HMAC::SignWithSHA1(const std::string& data,
96 unsigned char* digest,
97 int digest_length) {
98 DCHECK(provider_);
99 DCHECK(hkey_);
100
101 if (!CryptCreateHash(provider_, CALG_HMAC, hkey_, 0, &hash_))
102 return false;
103
104 HMAC_INFO hmac_info;
105 memset(&hmac_info, 0, sizeof(hmac_info));
106 hmac_info.HashAlgid = CALG_SHA1;
107 if (!CryptSetHashParam(hash_, HP_HMAC_INFO,
108 reinterpret_cast<BYTE*>(&hmac_info), 0))
109 return false;
110
111 if (!CryptHashData(hash_,
112 reinterpret_cast<const BYTE*>(data.data()),
113 static_cast<DWORD>(data.size()), 0))
114 return false;
115
116 DWORD sha1_size = digest_length;
117 if (!CryptGetHashParam(hash_, HP_HASHVAL, digest, &sha1_size, 0))
118 return false;
119
120 return true;
121}