blob: 3b8543488d0bb0ae7c0996db70f9527bc5e34cd8 [file] [log] [blame]
[email protected]908cb9e2014-02-21 15:40:091// Copyright 2014 The Chromium Authors. All rights reserved.
[email protected]ecbf2892010-07-16 01:51:452// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]c523d202014-03-18 01:34:545#include "components/os_crypt/keychain_password_mac.h"
[email protected]ecbf2892010-07-16 01:51:456
7#import <Security/Security.h>
8
[email protected]b0cdc592012-02-22 03:39:209#include "base/base64.h"
[email protected]33b98202012-01-27 23:06:4910#include "base/mac/mac_logging.h"
Vasilii Sukhanov5bb3b4682018-12-04 12:00:0411#include "base/mac/scoped_cftyperef.h"
[email protected]b0cdc592012-02-22 03:39:2012#include "base/rand_util.h"
Nico Weber356b3042019-08-23 15:30:4113#include "build/branding_buildflags.h"
[email protected]982f1ab2012-08-30 13:03:4614#include "crypto/apple_keychain.h"
[email protected]ecbf2892010-07-16 01:51:4515
[email protected]982f1ab2012-08-30 13:03:4616using crypto::AppleKeychain;
[email protected]b9d3d002012-03-17 12:14:5017
[email protected]ecbf2892010-07-16 01:51:4518namespace {
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]982f1ab2012-08-30 13:03:4623std::string AddRandomPasswordToKeychain(const AppleKeychain& keychain,
[email protected]ecbf2892010-07-16 01:51:4524 const std::string& service_name,
25 const std::string& account_name) {
[email protected]b0cdc592012-02-22 03:39:2026 // 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]ecbf2892010-07-16 01:51:4530 void* password_data =
31 const_cast<void*>(static_cast<const void*>(password.data()));
32
Justin Cohen2db15692018-06-06 16:54:0333 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]ecbf2892010-07-16 01:51:4536
37 if (error != noErr) {
[email protected]33b98202012-01-27 23:06:4938 OSSTATUS_DLOG(ERROR, error) << "Keychain add failed";
[email protected]ecbf2892010-07-16 01:51:4539 return std::string();
40 }
41
42 return password;
43}
44
45} // namespace
46
kerrnele29cfa22017-03-03 19:35:3347// 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 Weber356b3042019-08-23 15:30:4150#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
kerrnele29cfa22017-03-03 19:35:3351const char KeychainPassword::service_name[] = "Chrome Safe Storage";
52const char KeychainPassword::account_name[] = "Chrome";
[email protected]51902c1c2014-04-03 20:20:1153#else
kerrnele29cfa22017-03-03 19:35:3354const char KeychainPassword::service_name[] = "Chromium Safe Storage";
55const char KeychainPassword::account_name[] = "Chromium";
[email protected]51902c1c2014-04-03 20:20:1156#endif
[email protected]ecbf2892010-07-16 01:51:4557
Vasilii Sukhanovd67cacc2020-01-17 12:52:3858KeychainPassword::KeychainPassword(const AppleKeychain& keychain)
59 : keychain_(keychain) {}
Tonko Sabolčec43615a92018-09-12 12:43:4160
61KeychainPassword::~KeychainPassword() = default;
62
kerrnele29cfa22017-03-03 19:35:3363std::string KeychainPassword::GetPassword() const {
[email protected]ecbf2892010-07-16 01:51:4564 UInt32 password_length = 0;
Vasilii Sukhanov5bb3b4682018-12-04 12:00:0465 void* password_data = nullptr;
kerrnele29cfa22017-03-03 19:35:3366 OSStatus error = keychain_.FindGenericPassword(
Justin Cohen2db15692018-06-06 16:54:0367 strlen(service_name), service_name, strlen(account_name), account_name,
Vasilii Sukhanov5bb3b4682018-12-04 12:00:0468 &password_length, &password_data, nullptr);
[email protected]ecbf2892010-07-16 01:51:4569
70 if (error == noErr) {
71 std::string password =
72 std::string(static_cast<char*>(password_data), password_length);
Justin Cohen2db15692018-06-06 16:54:0373 keychain_.ItemFreeContent(password_data);
[email protected]ecbf2892010-07-16 01:51:4574 return password;
[email protected]ecbf2892010-07-16 01:51:4575 }
Tonko Sabolčec43615a92018-09-12 12:43:4176
77 if (error == errSecItemNotFound) {
Tonko Sabolčec43615a92018-09-12 12:43:4178 std::string password =
79 AddRandomPasswordToKeychain(keychain_, service_name, account_name);
Tonko Sabolčec43615a92018-09-12 12:43:4180 return password;
81 }
82
83 OSSTATUS_DLOG(ERROR, error) << "Keychain lookup failed";
84 return std::string();
[email protected]ecbf2892010-07-16 01:51:4585}