[email protected] | 908cb9e | 2014-02-21 15:40:09 | [diff] [blame] | 1 | // Copyright 2014 The Chromium Authors. All rights reserved. |
[email protected] | ecbf289 | 2010-07-16 01:51:45 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
[email protected] | c523d20 | 2014-03-18 01:34:54 | [diff] [blame] | 5 | #include "components/os_crypt/keychain_password_mac.h" |
[email protected] | ecbf289 | 2010-07-16 01:51:45 | [diff] [blame] | 6 | |
| 7 | #import <Security/Security.h> |
| 8 | |
[email protected] | b0cdc59 | 2012-02-22 03:39:20 | [diff] [blame] | 9 | #include "base/base64.h" |
[email protected] | 33b9820 | 2012-01-27 23:06:49 | [diff] [blame] | 10 | #include "base/mac/mac_logging.h" |
Vasilii Sukhanov | 5bb3b468 | 2018-12-04 12:00:04 | [diff] [blame] | 11 | #include "base/mac/scoped_cftyperef.h" |
[email protected] | b0cdc59 | 2012-02-22 03:39:20 | [diff] [blame] | 12 | #include "base/rand_util.h" |
Nico Weber | 356b304 | 2019-08-23 15:30:41 | [diff] [blame] | 13 | #include "build/branding_buildflags.h" |
[email protected] | 982f1ab | 2012-08-30 13:03:46 | [diff] [blame] | 14 | #include "crypto/apple_keychain.h" |
[email protected] | ecbf289 | 2010-07-16 01:51:45 | [diff] [blame] | 15 | |
[email protected] | 982f1ab | 2012-08-30 13:03:46 | [diff] [blame] | 16 | using crypto::AppleKeychain; |
[email protected] | b9d3d00 | 2012-03-17 12:14:50 | [diff] [blame] | 17 | |
[email protected] | ecbf289 | 2010-07-16 01:51:45 | [diff] [blame] | 18 | namespace { |
| 19 | |
| 20 | // Generates a random password and adds it to the Keychain. The added password |
| 21 | // is returned from the function. If an error occurs, an empty password is |
| 22 | // returned. |
[email protected] | 982f1ab | 2012-08-30 13:03:46 | [diff] [blame] | 23 | std::string AddRandomPasswordToKeychain(const AppleKeychain& keychain, |
[email protected] | ecbf289 | 2010-07-16 01:51:45 | [diff] [blame] | 24 | const std::string& service_name, |
| 25 | const std::string& account_name) { |
[email protected] | b0cdc59 | 2012-02-22 03:39:20 | [diff] [blame] | 26 | // Generate a password with 128 bits of randomness. |
| 27 | const int kBytes = 128 / 8; |
| 28 | std::string password; |
| 29 | base::Base64Encode(base::RandBytesAsString(kBytes), &password); |
[email protected] | ecbf289 | 2010-07-16 01:51:45 | [diff] [blame] | 30 | void* password_data = |
| 31 | const_cast<void*>(static_cast<const void*>(password.data())); |
| 32 | |
Justin Cohen | 2db1569 | 2018-06-06 16:54:03 | [diff] [blame] | 33 | OSStatus error = keychain.AddGenericPassword( |
| 34 | service_name.size(), service_name.data(), account_name.size(), |
| 35 | account_name.data(), password.size(), password_data, NULL); |
[email protected] | ecbf289 | 2010-07-16 01:51:45 | [diff] [blame] | 36 | |
| 37 | if (error != noErr) { |
[email protected] | 33b9820 | 2012-01-27 23:06:49 | [diff] [blame] | 38 | OSSTATUS_DLOG(ERROR, error) << "Keychain add failed"; |
[email protected] | ecbf289 | 2010-07-16 01:51:45 | [diff] [blame] | 39 | return std::string(); |
| 40 | } |
| 41 | |
| 42 | return password; |
| 43 | } |
| 44 | |
| 45 | } // namespace |
| 46 | |
kerrnel | e29cfa2 | 2017-03-03 19:35:33 | [diff] [blame] | 47 | // These two strings ARE indeed user facing. But they are used to access |
| 48 | // the encryption keyword. So as to not lose encrypted data when system |
| 49 | // locale changes we DO NOT LOCALIZE. |
Nico Weber | 356b304 | 2019-08-23 15:30:41 | [diff] [blame] | 50 | #if BUILDFLAG(GOOGLE_CHROME_BRANDING) |
kerrnel | e29cfa2 | 2017-03-03 19:35:33 | [diff] [blame] | 51 | const char KeychainPassword::service_name[] = "Chrome Safe Storage"; |
| 52 | const char KeychainPassword::account_name[] = "Chrome"; |
[email protected] | 51902c1c | 2014-04-03 20:20:11 | [diff] [blame] | 53 | #else |
kerrnel | e29cfa2 | 2017-03-03 19:35:33 | [diff] [blame] | 54 | const char KeychainPassword::service_name[] = "Chromium Safe Storage"; |
| 55 | const char KeychainPassword::account_name[] = "Chromium"; |
[email protected] | 51902c1c | 2014-04-03 20:20:11 | [diff] [blame] | 56 | #endif |
[email protected] | ecbf289 | 2010-07-16 01:51:45 | [diff] [blame] | 57 | |
Vasilii Sukhanov | d67cacc | 2020-01-17 12:52:38 | [diff] [blame] | 58 | KeychainPassword::KeychainPassword(const AppleKeychain& keychain) |
| 59 | : keychain_(keychain) {} |
Tonko Sabolčec | 43615a9 | 2018-09-12 12:43:41 | [diff] [blame] | 60 | |
| 61 | KeychainPassword::~KeychainPassword() = default; |
| 62 | |
kerrnel | e29cfa2 | 2017-03-03 19:35:33 | [diff] [blame] | 63 | std::string KeychainPassword::GetPassword() const { |
[email protected] | ecbf289 | 2010-07-16 01:51:45 | [diff] [blame] | 64 | UInt32 password_length = 0; |
Vasilii Sukhanov | 5bb3b468 | 2018-12-04 12:00:04 | [diff] [blame] | 65 | void* password_data = nullptr; |
kerrnel | e29cfa2 | 2017-03-03 19:35:33 | [diff] [blame] | 66 | OSStatus error = keychain_.FindGenericPassword( |
Justin Cohen | 2db1569 | 2018-06-06 16:54:03 | [diff] [blame] | 67 | strlen(service_name), service_name, strlen(account_name), account_name, |
Vasilii Sukhanov | 5bb3b468 | 2018-12-04 12:00:04 | [diff] [blame] | 68 | &password_length, &password_data, nullptr); |
[email protected] | ecbf289 | 2010-07-16 01:51:45 | [diff] [blame] | 69 | |
| 70 | if (error == noErr) { |
| 71 | std::string password = |
| 72 | std::string(static_cast<char*>(password_data), password_length); |
Justin Cohen | 2db1569 | 2018-06-06 16:54:03 | [diff] [blame] | 73 | keychain_.ItemFreeContent(password_data); |
[email protected] | ecbf289 | 2010-07-16 01:51:45 | [diff] [blame] | 74 | return password; |
[email protected] | ecbf289 | 2010-07-16 01:51:45 | [diff] [blame] | 75 | } |
Tonko Sabolčec | 43615a9 | 2018-09-12 12:43:41 | [diff] [blame] | 76 | |
| 77 | if (error == errSecItemNotFound) { |
Tonko Sabolčec | 43615a9 | 2018-09-12 12:43:41 | [diff] [blame] | 78 | std::string password = |
| 79 | AddRandomPasswordToKeychain(keychain_, service_name, account_name); |
Tonko Sabolčec | 43615a9 | 2018-09-12 12:43:41 | [diff] [blame] | 80 | return password; |
| 81 | } |
| 82 | |
| 83 | OSSTATUS_DLOG(ERROR, error) << "Keychain lookup failed"; |
| 84 | return std::string(); |
[email protected] | ecbf289 | 2010-07-16 01:51:45 | [diff] [blame] | 85 | } |