1 // Copyright 2014 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 #include "components/os_crypt/keychain_password_mac.h" 6 7 #import <Security/Security.h> 8 9 #include "base/base64.h" 10 #include "base/mac/mac_logging.h" 11 #include "base/rand_util.h" 12 #include "crypto/apple_keychain.h" 13 14 using crypto::AppleKeychain; 15 16 namespace { 17 18 // Generates a random password and adds it to the Keychain. The added password 19 // is returned from the function. If an error occurs, an empty password is 20 // returned. 21 std::string AddRandomPasswordToKeychain(const AppleKeychain& keychain, 22 const std::string& service_name, 23 const std::string& account_name) { 24 // Generate a password with 128 bits of randomness. 25 const int kBytes = 128 / 8; 26 std::string password; 27 base::Base64Encode(base::RandBytesAsString(kBytes), &password); 28 void* password_data = 29 const_cast<void*>(static_cast<const void*>(password.data())); 30 31 OSStatus error = keychain.AddGenericPassword(NULL, 32 service_name.size(), 33 service_name.data(), 34 account_name.size(), 35 account_name.data(), 36 password.size(), 37 password_data, 38 NULL); 39 40 if (error != noErr) { 41 OSSTATUS_DLOG(ERROR, error) << "Keychain add failed"; 42 return std::string(); 43 } 44 45 return password; 46 } 47 48 } // namespace 49 50 std::string KeychainPassword::GetPassword() const { 51 // These two strings ARE indeed user facing. But they are used to access 52 // the encryption keyword. So as to not lose encrypted data when system 53 // locale changes we DO NOT LOCALIZE. 54 #if defined(OFFICIAL_BUILD) 55 const std::string service_name = "Chrome Safe Storage"; 56 const std::string account_name = "Chrome"; 57 #else 58 const std::string service_name = "Chromium Safe Storage"; 59 const std::string account_name = "Chromium"; 60 #endif 61 62 UInt32 password_length = 0; 63 void* password_data = NULL; 64 OSStatus error = keychain_.FindGenericPassword(NULL, 65 service_name.size(), 66 service_name.data(), 67 account_name.size(), 68 account_name.data(), 69 &password_length, 70 &password_data, 71 NULL); 72 73 if (error == noErr) { 74 std::string password = 75 std::string(static_cast<char*>(password_data), password_length); 76 keychain_.ItemFreeContent(NULL, password_data); 77 return password; 78 } else if (error == errSecItemNotFound) { 79 return AddRandomPasswordToKeychain(keychain_, service_name, account_name); 80 } else { 81 OSSTATUS_DLOG(ERROR, error) << "Keychain lookup failed"; 82 return std::string(); 83 } 84 } 85