1// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#ifndef CHROME_BROWSER_AUTOFILL_CRYPTO_RC4_DECRYPTOR_H_ 6#define CHROME_BROWSER_AUTOFILL_CRYPTO_RC4_DECRYPTOR_H_ 7 8#include <string> 9#include "base/basictypes.h" 10#include "base/memory/scoped_ptr.h" 11 12// This is modified RC4 decryption used for import of Toolbar autofill data 13// only. The difference from the Crypto Api implementation is twofold: 14// First, it uses a non-standard key size (160 bit), not supported by Microsoft 15// (it supports only 40 and 128 bit for RC4). Second, it codes 128 words with 16// value 0x0020 at the beginning of the code to enhance security. 17// This class used in chrome/browser/autofill/autofill_ie_toolbar_import_win.cc. 18// This class should not be used anywhere else!!! 19class RC4Decryptor { 20 public: 21 explicit RC4Decryptor(wchar_t const* password) { 22 PrepareKey(reinterpret_cast<const uint8 *>(password), 23 wcslen(password) * sizeof(wchar_t)); 24 std::wstring data; 25 // First 128 bytes should be spaces. 26 data.resize(128, L' '); 27 Run(data.c_str()); 28 } 29 30 // Run the algorithm 31 std::wstring Run(const std::wstring& data) { 32 int data_size = data.length() * sizeof(wchar_t); 33 34 scoped_array<wchar_t> buffer(new wchar_t[data.length() + 1]); 35 memset(buffer.get(), 0, (data.length() + 1) * sizeof(wchar_t)); 36 memcpy(buffer.get(), data.c_str(), data_size); 37 38 RunInternal(reinterpret_cast<uint8 *>(buffer.get()), data_size); 39 40 std::wstring result(buffer.get()); 41 42 // Clear the memory 43 memset(buffer.get(), 0, data_size); 44 return result; 45 } 46 47 private: 48 static const int kKeyDataSize = 256; 49 struct Rc4Key { 50 uint8 state[kKeyDataSize]; 51 uint8 x; 52 uint8 y; 53 }; 54 55 void SwapByte(uint8* byte1, uint8* byte2) { 56 uint8 temp = *byte1; 57 *byte1 = *byte2; 58 *byte2 = temp; 59 } 60 61 void PrepareKey(const uint8 *key_data, int key_data_len) { 62 uint8 index1 = 0; 63 uint8 index2 = 0; 64 uint8* state; 65 short counter; 66 67 state = &key_.state[0]; 68 for (counter = 0; counter < kKeyDataSize; ++counter) 69 state[counter] = static_cast<uint8>(counter); 70 71 key_.x = key_.y = 0; 72 73 for (counter = 0; counter < kKeyDataSize; counter++) { 74 index2 = (key_data[index1] + state[counter] + index2) % kKeyDataSize; 75 SwapByte(&state[counter], &state[index2]); 76 index1 = (index1 + 1) % key_data_len; 77 } 78 } 79 80 void RunInternal(uint8 *buffer, int buffer_len) { 81 uint8 x, y; 82 uint8 xor_index = 0; 83 uint8* state; 84 int counter; 85 86 x = key_.x; 87 y = key_.y; 88 state = &key_.state[0]; 89 for (counter = 0; counter < buffer_len; ++counter) { 90 x = (x + 1) % kKeyDataSize; 91 y = (state[x] + y) % kKeyDataSize; 92 SwapByte(&state[x], &state[y]); 93 xor_index = (state[x] + state[y]) % kKeyDataSize; 94 buffer[counter] ^= state[xor_index]; 95 } 96 key_.x = x; 97 key_.y = y; 98 } 99 100 Rc4Key key_; 101}; 102 103#endif // CHROME_BROWSER_AUTOFILL_CRYPTO_RC4_DECRYPTOR_H_ 104