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