1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 3513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// found in the LICENSE file. 4513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 5513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#ifndef CHROME_BROWSER_AUTOFILL_CRYPTO_RC4_DECRYPTOR_H_ 6513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#define CHROME_BROWSER_AUTOFILL_CRYPTO_RC4_DECRYPTOR_H_ 7513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 8513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include <string> 9513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/basictypes.h" 10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h" 11513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 12513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// This is modified RC4 decryption used for import of Toolbar autofill data 13513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// only. The difference from the Crypto Api implementation is twofold: 14513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// First, it uses a non-standard key size (160 bit), not supported by Microsoft 15513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// (it supports only 40 and 128 bit for RC4). Second, it codes 128 words with 16513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// value 0x0020 at the beginning of the code to enhance security. 17513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// This class used in chrome/browser/autofill/autofill_ie_toolbar_import_win.cc. 18513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// This class should not be used anywhere else!!! 19513209b27ff55e2841eac0e4120199c23acce758Ben Murdochclass RC4Decryptor { 20513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch public: 21513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch explicit RC4Decryptor(wchar_t const* password) { 22513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch PrepareKey(reinterpret_cast<const uint8 *>(password), 23513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch wcslen(password) * sizeof(wchar_t)); 24513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch std::wstring data; 25513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // First 128 bytes should be spaces. 26513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch data.resize(128, L' '); 27513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch Run(data.c_str()); 28513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 29513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 30513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Run the algorithm 31513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch std::wstring Run(const std::wstring& data) { 32513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch int data_size = data.length() * sizeof(wchar_t); 33513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 34513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch scoped_array<wchar_t> buffer(new wchar_t[data.length() + 1]); 35513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch memset(buffer.get(), 0, (data.length() + 1) * sizeof(wchar_t)); 36513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch memcpy(buffer.get(), data.c_str(), data_size); 37513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 38513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch RunInternal(reinterpret_cast<uint8 *>(buffer.get()), data_size); 39513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 40513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch std::wstring result(buffer.get()); 41513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 42513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Clear the memory 43513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch memset(buffer.get(), 0, data_size); 44513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return result; 45513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 46513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 47513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch private: 48513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch static const int kKeyDataSize = 256; 49513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch struct Rc4Key { 50513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch uint8 state[kKeyDataSize]; 51513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch uint8 x; 52513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch uint8 y; 53513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch }; 54513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 55513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch void SwapByte(uint8* byte1, uint8* byte2) { 56513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch uint8 temp = *byte1; 57513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch *byte1 = *byte2; 58513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch *byte2 = temp; 59513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 60513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 61513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch void PrepareKey(const uint8 *key_data, int key_data_len) { 62513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch uint8 index1 = 0; 63513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch uint8 index2 = 0; 64513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch uint8* state; 65513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch short counter; 66513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 67513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch state = &key_.state[0]; 68513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch for (counter = 0; counter < kKeyDataSize; ++counter) 69513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch state[counter] = static_cast<uint8>(counter); 70513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 71513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch key_.x = key_.y = 0; 72513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 73513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch for (counter = 0; counter < kKeyDataSize; counter++) { 74513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch index2 = (key_data[index1] + state[counter] + index2) % kKeyDataSize; 75513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch SwapByte(&state[counter], &state[index2]); 76513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch index1 = (index1 + 1) % key_data_len; 77513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 78513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 79513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 80513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch void RunInternal(uint8 *buffer, int buffer_len) { 81513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch uint8 x, y; 82513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch uint8 xor_index = 0; 83513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch uint8* state; 84513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch int counter; 85513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 86513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch x = key_.x; 87513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch y = key_.y; 88513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch state = &key_.state[0]; 89513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch for (counter = 0; counter < buffer_len; ++counter) { 90513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch x = (x + 1) % kKeyDataSize; 91513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch y = (state[x] + y) % kKeyDataSize; 92513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch SwapByte(&state[x], &state[y]); 93513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch xor_index = (state[x] + state[y]) % kKeyDataSize; 94513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch buffer[counter] ^= state[xor_index]; 95513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 96513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch key_.x = x; 97513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch key_.y = y; 98513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 99513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 100513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch Rc4Key key_; 101513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}; 102513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 103513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#endif // CHROME_BROWSER_AUTOFILL_CRYPTO_RC4_DECRYPTOR_H_ 104