blob: 8198b601c78f5acc3b7458eb5d3de891eab0ad55 [file] [log] [blame]
Mark Mentovaib4e1bfc2022-02-10 14:43:341// Copyright (c) 2012 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 "crypto/apple_keychain.h"
6
7#include "base/synchronization/lock.h"
8#include "crypto/mac_security_services_lock.h"
9
10namespace {
11
12// Supports the pattern where a function F(T* out) allows |out| to be nullptr
13// but its implementation requires a T variable even in the absence of |out|.
14// Such a function can maintain a local OptionalOutParameter<T> to provide the
15// internal T value, assigning its value to *out on destruction if possible.
16template <typename T>
17class OptionalOutParameter {
18 public:
19 OptionalOutParameter(const OptionalOutParameter&) = delete;
20 OptionalOutParameter& operator=(const OptionalOutParameter&) = delete;
21
22 OptionalOutParameter(T* out, T value = T()) : out_(out), value_(value) {}
23
24 ~OptionalOutParameter() {
25 if (out_) {
26 *out_ = value_;
27 }
28 }
29
30 OptionalOutParameter& operator=(T value) {
31 value_ = value;
32 return *this;
33 }
34 operator T() const { return value_; }
35
36 private:
37 T* const out_;
38 T value_;
39};
40
41} // namespace
42
43namespace crypto {
44
45AppleKeychain::AppleKeychain() = default;
46
47AppleKeychain::~AppleKeychain() = default;
48
49OSStatus AppleKeychain::FindGenericPassword(
50 UInt32 service_name_length,
51 const char* service_name,
52 UInt32 account_name_length,
53 const char* account_name,
54 UInt32* password_length,
55 void** password_data,
56 AppleSecKeychainItemRef* item) const {
57 base::AutoLock lock(GetMacSecurityServicesLock());
58 return SecKeychainFindGenericPassword(
59 nullptr, service_name_length, service_name, account_name_length,
60 account_name, password_length, password_data, item);
61}
62
63OSStatus AppleKeychain::ItemFreeContent(void* data) const {
64 base::AutoLock lock(GetMacSecurityServicesLock());
65 return SecKeychainItemFreeContent(nullptr, data);
66}
67
68OSStatus AppleKeychain::AddGenericPassword(
69 UInt32 service_name_length,
70 const char* service_name,
71 UInt32 account_name_length,
72 const char* account_name,
73 UInt32 password_length,
74 const void* password_data,
75 AppleSecKeychainItemRef* item) const {
76 base::AutoLock lock(GetMacSecurityServicesLock());
77 return SecKeychainAddGenericPassword(
78 nullptr, service_name_length, service_name, account_name_length,
79 account_name, password_length, password_data, item);
80}
81
82OSStatus AppleKeychain::ItemDelete(AppleSecKeychainItemRef item) const {
83 base::AutoLock lock(GetMacSecurityServicesLock());
84 return SecKeychainItemDelete(item);
85}
86
87ScopedKeychainUserInteractionAllowed::ScopedKeychainUserInteractionAllowed(
88 Boolean allowed,
89 OSStatus* status) {
90 Boolean was_allowed;
91 OptionalOutParameter<OSStatus> local_status(
92 status, SecKeychainGetUserInteractionAllowed(&was_allowed));
93 if (local_status != noErr) {
94 return;
95 }
96
97 local_status = SecKeychainSetUserInteractionAllowed(allowed);
98 if (local_status != noErr) {
99 return;
100 }
101
102 was_allowed_ = was_allowed;
103}
104
105ScopedKeychainUserInteractionAllowed::~ScopedKeychainUserInteractionAllowed() {
106 if (was_allowed_) {
107 SecKeychainSetUserInteractionAllowed(*was_allowed_);
108 }
109}
110
111} // namespace crypto