| 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 |