Home | History | Annotate | Download | only in crypto
      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!!!
     19 class 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