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