OLD | NEW |
| (Empty) |
1 // Copyright 2008-2009 Google Inc. | |
2 // | |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
4 // you may not use this file except in compliance with the License. | |
5 // You may obtain a copy of the License at | |
6 // | |
7 // http://www.apache.org/licenses/LICENSE-2.0 | |
8 // | |
9 // Unless required by applicable law or agreed to in writing, software | |
10 // distributed under the License is distributed on an "AS IS" BASIS, | |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 // See the License for the specific language governing permissions and | |
13 // limitations under the License. | |
14 // ======================================================================== | |
15 | |
16 #include "omaha/net/cup_utils.h" | |
17 | |
18 #include <algorithm> | |
19 #include <vector> | |
20 #include "omaha/base/debug.h" | |
21 #include "omaha/base/security/b64.h" | |
22 #include "omaha/base/security/hmac.h" | |
23 #include "omaha/base/security/sha.h" | |
24 | |
25 namespace omaha { | |
26 | |
27 namespace cup_utils { | |
28 | |
29 std::vector<uint8> RsaPad(size_t rsa_key_size, | |
30 const void* data, size_t data_length) { | |
31 ASSERT1(rsa_key_size >= SHA_DIGEST_SIZE); | |
32 ASSERT1(data); | |
33 | |
34 // The result gets padded with zeros if the result size is greater than | |
35 // the size of the buffer provided by the caller. | |
36 const uint8* start = static_cast<const uint8*>(data); | |
37 std::vector<uint8> result(start, start + data_length); | |
38 result.resize(rsa_key_size - SHA_DIGEST_SIZE); | |
39 | |
40 // The input needs to be smaller than the RSA modulus, which has always the | |
41 // msb set. | |
42 result[0] &= 127; // Reset msb | |
43 result[0] |= 64; // Set second highest bit. | |
44 | |
45 uint8 digest[SHA_DIGEST_SIZE] = {0}; | |
46 SHA(&result.front(), result.size(), digest); | |
47 | |
48 result.insert(result.end(), digest, digest + SHA_DIGEST_SIZE); | |
49 ASSERT1(result.size() == rsa_key_size); | |
50 return result; | |
51 } | |
52 | |
53 CStringA B64Encode(const void* data, size_t data_length) { | |
54 ASSERT1(data); | |
55 | |
56 // After encoding the size grows a little bit, about 133%. We assume 150% | |
57 // bigger size for simplicity. Also, the output length is a multiple of | |
58 // 4 bytes, so the minimum buffer should be at least 5 chars to include | |
59 // space for the string terminator. | |
60 CStringA result; | |
61 const size_t kMinBuffer = 5; | |
62 int result_max_size = std::max(data_length * 3 / 2, kMinBuffer); | |
63 int result_size = B64_encode(static_cast<const uint8*>(data), | |
64 data_length, | |
65 CStrBufA(result, result_max_size), | |
66 result_max_size); | |
67 ASSERT1(result_size == result.GetLength()); | |
68 return result; | |
69 } | |
70 | |
71 CStringA B64Encode(const std::vector<uint8>& data) { | |
72 return B64Encode(&data.front(), data.size()); | |
73 } | |
74 | |
75 std::vector<uint8> Hash(const std::vector<uint8>& data) { | |
76 std::vector<uint8>result(SHA_DIGEST_SIZE); | |
77 SHA(data.empty() ? NULL : &data.front(), data.size(), &result.front()); | |
78 return result; | |
79 } | |
80 | |
81 std::vector<uint8> Hash(const CStringA& data) { | |
82 std::vector<uint8>result(SHA_DIGEST_SIZE); | |
83 SHA(data.GetString(), data.GetLength(), &result.front()); | |
84 return result; | |
85 } | |
86 | |
87 std::vector<uint8> HashBuffers(const void* buf1, size_t len1, | |
88 const void* buf2, size_t len2, | |
89 const void* buf3, size_t len3) { | |
90 SHA_CTX sha_ctx = {0}; | |
91 SHA_init(&sha_ctx); | |
92 const void* buffers[] = {buf1, buf2, buf3}; | |
93 const size_t lengths[] = {len1, len2, len3}; | |
94 for (size_t i = 0; i != arraysize(buffers); ++i) { | |
95 uint8 hash[SHA_DIGEST_SIZE] = {0}; | |
96 SHA(buffers[i], lengths[i], hash); | |
97 SHA_update(&sha_ctx, hash, sizeof(hash)); | |
98 } | |
99 std::vector<uint8> result(SHA_DIGEST_SIZE); | |
100 memcpy(&result.front(), SHA_final(&sha_ctx), result.size()); | |
101 return result; | |
102 } | |
103 | |
104 std::vector<uint8> SymSign(const std::vector<uint8>& key, | |
105 uint8 id, | |
106 const std::vector<uint8>* h1, | |
107 const std::vector<uint8>* h2, | |
108 const std::vector<uint8>* h3) { | |
109 HMAC_CTX hmac_ctx = {0}; | |
110 HMAC_SHA_init(&hmac_ctx, &key.front(), key.size()); | |
111 HMAC_update(&hmac_ctx, &id, sizeof(id)); | |
112 const std::vector<uint8>* args[] = {h1, h2, h3}; | |
113 for (size_t i = 0; i != arraysize(args); ++i) { | |
114 if (args[i]) { | |
115 ASSERT1(args[i]->size() == SHA_DIGEST_SIZE); | |
116 HMAC_update(&hmac_ctx, &args[i]->front(), args[i]->size()); | |
117 } | |
118 } | |
119 std::vector<uint8> result(SHA_DIGEST_SIZE); | |
120 memcpy(&result.front(), HMAC_final(&hmac_ctx), result.size()); | |
121 return result; | |
122 } | |
123 | |
124 // Looks for "c=", extracts a substring up to ';', which is the attribute | |
125 // delimiter, and trims the white spaces at the end. If found, it returns | |
126 // the string corresponding to "c=xxx", otherwise it returns an empty string. | |
127 CString ParseCupCookie(const CString& cookie_header) { | |
128 CString cookie; | |
129 int start = cookie_header.Find(_T("c=")); | |
130 if (start != -1) { | |
131 int end = cookie_header.Find(_T(';'), start); | |
132 if (end != -1) { | |
133 cookie = cookie_header.Mid(start, end - start); | |
134 } else { | |
135 cookie = cookie_header.Mid(start); | |
136 } | |
137 cookie.TrimRight(_T(' ')); | |
138 } | |
139 return cookie; | |
140 } | |
141 | |
142 } // namespace cup_utils | |
143 | |
144 } // namespace omaha | |
145 | |
OLD | NEW |