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