1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Copyright 2014 The Chromium Authors. All rights reserved.
2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Use of this source code is governed by a BSD-style license that can be
3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// found in the LICENSE file.
4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "components/os_crypt/os_crypt.h"
6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "base/logging.h"
8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "base/memory/scoped_ptr.h"
9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "base/strings/utf_string_conversions.h"
10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "crypto/encryptor.h"
11b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "crypto/symmetric_key.h"
12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
13b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgnamespace {
14b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
15b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Salt for Symmetric key derivation.
160de0049a4e555f347cab027c2fddd32e7f916ed3minyue@webrtc.orgconst char kSalt[] = "saltysalt";
17471ae72f18e7b23a96b245dbd508386fe139449cpbos@webrtc.org
18471ae72f18e7b23a96b245dbd508386fe139449cpbos@webrtc.org// Key size required for 128 bit AES.
19471ae72f18e7b23a96b245dbd508386fe139449cpbos@webrtc.orgconst size_t kDerivedKeySizeInBits = 128;
20471ae72f18e7b23a96b245dbd508386fe139449cpbos@webrtc.org
21471ae72f18e7b23a96b245dbd508386fe139449cpbos@webrtc.org// Constant for Symmetic key derivation.
22471ae72f18e7b23a96b245dbd508386fe139449cpbos@webrtc.orgconst size_t kEncryptionIterations = 1;
23471ae72f18e7b23a96b245dbd508386fe139449cpbos@webrtc.org
24471ae72f18e7b23a96b245dbd508386fe139449cpbos@webrtc.org// Size of initialization vector for AES 128-bit.
25471ae72f18e7b23a96b245dbd508386fe139449cpbos@webrtc.orgconst size_t kIVBlockSizeAES128 = 16;
26471ae72f18e7b23a96b245dbd508386fe139449cpbos@webrtc.org
27471ae72f18e7b23a96b245dbd508386fe139449cpbos@webrtc.org// Prefix for cypher text returned by obfuscation version.  We prefix the
28471ae72f18e7b23a96b245dbd508386fe139449cpbos@webrtc.org// cyphertext with this string so that future data migration can detect
29471ae72f18e7b23a96b245dbd508386fe139449cpbos@webrtc.org// this and migrate to full encryption without data loss.
30471ae72f18e7b23a96b245dbd508386fe139449cpbos@webrtc.orgconst char kObfuscationPrefix[] = "v10";
31471ae72f18e7b23a96b245dbd508386fe139449cpbos@webrtc.org
32471ae72f18e7b23a96b245dbd508386fe139449cpbos@webrtc.org// Generates a newly allocated SymmetricKey object based a hard-coded password.
338510750bf2847dcdca26d914974c6d51d1e311a7pbos@webrtc.org// Ownership of the key is passed to the caller.  Returns NULL key if a key
34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// generation error occurs.
358510750bf2847dcdca26d914974c6d51d1e311a7pbos@webrtc.orgcrypto::SymmetricKey* GetEncryptionKey() {
368510750bf2847dcdca26d914974c6d51d1e311a7pbos@webrtc.org  // We currently "obfuscate" by encrypting and decrypting with hard-coded
37b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // password.  We need to improve this password situation by moving a secure
38b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // password into a system-level key store.
39b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // http://crbug.com/25404 and http://crbug.com/49115
40b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  std::string password = "peanuts";
41b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  std::string salt(kSalt);
42b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
43b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Create an encryption key from our password and salt.
44b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  scoped_ptr<crypto::SymmetricKey> encryption_key(
45b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      crypto::SymmetricKey::DeriveKeyFromPassword(crypto::SymmetricKey::AES,
46b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                                  password,
47b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                                  salt,
48b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                                  kEncryptionIterations,
49b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                                  kDerivedKeySizeInBits));
50b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  DCHECK(encryption_key.get());
51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
52b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return encryption_key.release();
53b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
54b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
55fbb6e45a37e84d50313318b1ad1e94f4bf1322f3andrew@webrtc.org}  // namespace
56b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
57b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool OSCrypt::EncryptString16(const base::string16& plaintext,
58b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                              std::string* ciphertext) {
59b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return EncryptString(base::UTF16ToUTF8(plaintext), ciphertext);
60b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
61b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
62b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool OSCrypt::DecryptString16(const std::string& ciphertext,
63b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                              base::string16* plaintext) {
64b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  std::string utf8;
65b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (!DecryptString(ciphertext, &utf8))
66b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return false;
67b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
68b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  *plaintext = base::UTF8ToUTF16(utf8);
69b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return true;
70b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
710de0049a4e555f347cab027c2fddd32e7f916ed3minyue@webrtc.org
72b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool OSCrypt::EncryptString(const std::string& plaintext,
73b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            std::string* ciphertext) {
74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // This currently "obfuscates" by encrypting with hard-coded password.
75  // We need to improve this password situation by moving a secure password
76  // into a system-level key store.
77  // http://crbug.com/25404 and http://crbug.com/49115
78
79  if (plaintext.empty()) {
80    *ciphertext = std::string();
81    return true;
82  }
83
84  scoped_ptr<crypto::SymmetricKey> encryption_key(GetEncryptionKey());
85  if (!encryption_key.get())
86    return false;
87
88  std::string iv(kIVBlockSizeAES128, ' ');
89  crypto::Encryptor encryptor;
90  if (!encryptor.Init(encryption_key.get(), crypto::Encryptor::CBC, iv))
91    return false;
92
93  if (!encryptor.Encrypt(plaintext, ciphertext))
94    return false;
95
96  // Prefix the cypher text with version information.
97  ciphertext->insert(0, kObfuscationPrefix);
98  return true;
99}
100
101bool OSCrypt::DecryptString(const std::string& ciphertext,
102                            std::string* plaintext) {
103  // This currently "obfuscates" by encrypting with hard-coded password.
104  // We need to improve this password situation by moving a secure password
105  // into a system-level key store.
106  // http://crbug.com/25404 and http://crbug.com/49115
107
108  if (ciphertext.empty()) {
109    *plaintext = std::string();
110    return true;
111  }
112
113  // Check that the incoming cyphertext was indeed encrypted with the expected
114  // version.  If the prefix is not found then we'll assume we're dealing with
115  // old data saved as clear text and we'll return it directly.
116  // Credit card numbers are current legacy data, so false match with prefix
117  // won't happen.
118  if (ciphertext.find(kObfuscationPrefix) != 0) {
119    *plaintext = ciphertext;
120    return true;
121  }
122
123  // Strip off the versioning prefix before decrypting.
124  std::string raw_ciphertext = ciphertext.substr(strlen(kObfuscationPrefix));
125
126  scoped_ptr<crypto::SymmetricKey> encryption_key(GetEncryptionKey());
127  if (!encryption_key.get())
128    return false;
129
130  std::string iv(kIVBlockSizeAES128, ' ');
131  crypto::Encryptor encryptor;
132  if (!encryptor.Init(encryption_key.get(), crypto::Encryptor::CBC, iv))
133    return false;
134
135  if (!encryptor.Decrypt(raw_ciphertext, plaintext))
136    return false;
137
138  return true;
139}
140