]> git.saurik.com Git - apple/security.git/blob - securityd/src/kcdatabase.h
Security-59306.11.20.tar.gz
[apple/security.git] / securityd / src / kcdatabase.h
1 /*
2 * Copyright (c) 2000-2008,2012-2013 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25 //
26 // kcdatabase - software database container implementation.
27 //
28 // A KeychainDatabase is a software storage container,
29 // implemented in cooperation by the AppleCSLDP CDSA plugin and this daemon.
30 //
31 #ifndef _H_KCDATABASE
32 #define _H_KCDATABASE
33
34 #include "localdatabase.h"
35 #include <securityd_client/ss_types.h>
36 #include "agentclient.h"
37
38 class KeychainDatabase;
39 class KeychainDbCommon;
40 class KeychainKey;
41
42
43 //
44 // We identify KeychainDatabases uniquely by a combination of
45 // a DLDbIdentifier and a database (blob) identifier. Equivalence
46 // by DbIdentifier is the criterion for parent-side merging.
47 //
48 class DbIdentifier {
49 public:
50 DbIdentifier(const DLDbIdentifier &id, DbBlob::Signature sig)
51 : mIdent(id), mSig(sig) { }
52
53 const DLDbIdentifier &dlDbIdentifier() const { return mIdent; }
54 const DbBlob::Signature &signature() const { return mSig; }
55 operator const DLDbIdentifier &() const { return dlDbIdentifier(); }
56 operator const DbBlob::Signature &() const { return signature(); }
57 const char *dbName() const { return mIdent.dbName(); }
58
59 bool operator < (const DbIdentifier &id) const // simple lexicographic
60 {
61 if (mIdent < id.mIdent) return true;
62 if (id.mIdent < mIdent) return false;
63 return mSig < id.mSig;
64 }
65
66 bool operator == (const DbIdentifier &id) const
67 { return mIdent == id.mIdent && mSig == id.mSig; }
68
69 private:
70 DLDbIdentifier mIdent;
71 DbBlob::Signature mSig;
72 };
73
74
75 //
76 // A vestigal system-global database instance
77 // We don't (yet) use it for anything. Perhaps it should carry our ACL...
78 //
79 class KeychainDbGlobal : public PerGlobal {
80 public:
81 KeychainDbGlobal(const DbIdentifier &id);
82 ~KeychainDbGlobal();
83
84 const DbIdentifier &identifier() const { return mIdentifier; }
85
86 private:
87 DbIdentifier mIdentifier; // database external identifier [const]
88 };
89
90
91 //
92 // KeychainDatabase DbCommons
93 //
94 class KeychainDbCommon : public LocalDbCommon,
95 public DatabaseCryptoCore, public MachServer::Timer {
96 public:
97 KeychainDbCommon(Session &ssn, const DbIdentifier &id, uint32 requestedVersion = CommonBlob::version_none);
98 KeychainDbCommon(Session &ssn, const DbIdentifier &id, KeychainDbCommon& toClone);
99 ~KeychainDbCommon();
100
101 // If you have an existing KeychainDbCommon, and want to make it look a lot like that one
102 void cloneFrom(KeychainDbCommon& toClone, uint32 requestedVersion = CommonBlob::version_none);
103
104 // finishes the initialization of this KeychainDbCommon. Do not call this
105 // while holding the mCommon lock, or you may get a multiprocess deadlock.
106 void initializeKeybag();
107
108 void kill(); // remove from commonSet
109
110 KeychainDbGlobal &global() const;
111
112 bool unlockDb(DbBlob *blob, void **privateAclBlob = NULL);
113 void lockDb(); // make locked (if currently unlocked)
114 bool isLocked() { return mIsLocked; } // lock status
115 void setUnlocked();
116 void invalidateBlob() { version++; }
117
118 void activity(); // reset lock timeout
119
120 void makeNewSecrets();
121
122 const DbIdentifier &identifier() const {return mIdentifier; }
123 const DLDbIdentifier &dlDbIdent() const { return identifier(); }
124 const char *dbName() const { return dlDbIdent().dbName(); }
125 uint32 dbVersion() { return DatabaseCryptoCore::mBlobVersion; }
126 bool isLoginKeychain() const { return mLoginKeychain; }
127
128 DbBlob *encode(KeychainDatabase &db);
129
130 void notify(NotificationEvent event) { DbCommon::notify(event, identifier()); }
131
132 void sleepProcessing();
133 void lockProcessing();
134
135 bool belongsToSystem() const;
136 bool isDefaultSystemKeychain() const;
137
138 public:
139 // debugging
140 IFDUMP(void dumpNode());
141
142 protected:
143 void action(); // timer queue action to lock keychain
144
145 // lifetime management for our Timer personality
146 void select();
147 void unselect();
148
149 public:
150 // all following data locked with object lock
151 uint32 sequence; // change sequence number
152 DBParameters mParams; // database parameters (arbitrated copy)
153
154 uint32 version; // version stamp for change tracking
155
156 private:
157 DbIdentifier mIdentifier; // database external identifier [const]
158 // all following data protected by object lock
159 bool mIsLocked; // logically locked
160 bool mValidParams; // mParams has been set
161 bool mLoginKeychain;
162
163 public:
164 void insert(); // insert into commonSet
165 static bool find(const DbIdentifier &ident, Session &session, RefPointer<KeychainDbCommon> &common,
166 uint32 requestedVersion = CommonBlob::version_none, KeychainDbCommon* cloneFrom = NULL); // find in commonSet
167
168 private:
169 void insertHoldingLock(); // Does the guts of insert(); you must hold a write lock on mRWCommonLock when calling this
170
171 // global set of KeychainDbCommons for name unification
172 typedef std::set<KeychainDbCommon *> CommonSet;
173 static CommonSet mCommonSet;
174 static ReadWriteLock mRWCommonLock; //protects only mCommonSet
175 };
176
177
178 //
179 // A Database object represents an Apple CSP/DL open database (DL/DB) object.
180 // It maintains its protected semantic state (including keys) and provides controlled
181 // access.
182 //
183 class KeychainDatabase : public LocalDatabase, private virtual SecurityServerAcl {
184 friend class KeychainDbCommon;
185 public:
186 KeychainDatabase(const DLDbIdentifier &id, const DBParameters &params, Process &proc,
187 const AccessCredentials *cred, const AclEntryPrototype *owner);
188 KeychainDatabase(const DLDbIdentifier &id, const DbBlob *blob, Process &proc,
189 const AccessCredentials *cred);
190
191 // keychain synchronization recode to a specfic blob:
192 KeychainDatabase(KeychainDatabase &src, Process &proc, DbHandle dbToClone);
193
194 // Clone another database, but to a new DLDb identifier
195 KeychainDatabase(const DLDbIdentifier &id, KeychainDatabase &src, Process &proc);
196
197 // Copy another database, but with new secrets.
198 // To use this, you must provide the version you want to end up with.
199 KeychainDatabase(uint32 requestedVersion, KeychainDatabase &src, Process &proc);
200 virtual ~KeychainDatabase();
201
202 KeychainDbCommon &common() const;
203 const char *dbName() const;
204 bool transient() const;
205
206 KeychainDbGlobal &global() const { return common().global(); }
207
208 public:
209 static const int maxUnlockTryCount = 3;
210
211 public:
212 const DbIdentifier &identifier() const { return common().identifier(); }
213
214 public:
215 // encoding/decoding databases
216 DbBlob *blob();
217
218 void authenticate(CSSM_DB_ACCESS_TYPE mode, const AccessCredentials *cred);
219 bool checkCredentials(const AccessCredentials* creds);
220 void changePassphrase(const AccessCredentials *cred);
221 RefPointer<Key> extractMasterKey(Database &db, const AccessCredentials *cred,
222 const AclEntryPrototype *owner, uint32 usage, uint32 attrs);
223 void commitSecretsForSync(KeychainDatabase &cloneDb);
224
225 // lock/unlock processing
226 void lockDb(); // unconditional lock
227 void unlockDb(bool unlockKeybag); // full-feature unlock
228 void unlockDb(const CssmData &passphrase, bool unlockKeybag); // unlock with passphrase
229
230 void stashDbCheck(); // check AppleKeyStore for master key
231 void stashDb(); // stash master key in AppleKeyStore
232
233 bool decode(); // unlock given established master key
234 bool decode(const CssmData &passphrase); // set master key from PP, try unlock
235
236 bool validatePassphrase(const CssmData &passphrase) const; // nonthrowing validation
237 bool isLocked() { return common().isLocked(); } // lock status
238 void notify(NotificationEvent event) { return common().notify(event); }
239 void activity() const { common().activity(); } // reset timeout clock
240
241 // encoding/decoding keys
242 void decodeKey(KeyBlob *blob, CssmKey &key, void * &pubAcl, void * &privAcl);
243 KeyBlob *encodeKey(const CssmKey &key, const CssmData &pubAcl, const CssmData &privAcl);
244 KeyBlob *recodeKey(KeychainKey &oldKey);
245 bool validBlob() const { return mBlob && version == common().version; }
246
247 // manage database parameters
248 void setParameters(const DBParameters &params);
249 void getParameters(DBParameters &params);
250
251 // where's my (database) ACL?
252 SecurityServerAcl &acl();
253
254 AclKind aclKind() const;
255 Database *relatedDatabase();
256
257 // ACL state management hooks
258 void instantiateAcl();
259 void changedAcl();
260
261 // miscellaneous utilities
262 static void validateBlob(const DbBlob *blob);
263
264 bool isRecoding();
265
266 // Notify ourselves that the keychain recode/migration has finished
267 void recodeFinished();
268
269 // debugging
270 IFDUMP(void dumpNode());
271
272 protected:
273 RefPointer<Key> makeKey(const CssmKey &newKey, uint32 moreAttributes, const AclEntryPrototype *owner);
274 RefPointer<Key> makeKey(Database &db, const CssmKey &newKey, uint32 moreAttributes, const AclEntryPrototype *owner);
275
276 void makeUnlocked(bool unlockKeybag); // interior version of unlock()
277 void makeUnlocked(const AccessCredentials *cred, bool unlockKeybag); // like () with explicit cred
278 void makeUnlocked(const CssmData &passphrase, bool unlockKeybag); // interior version of unlock(CssmData)
279
280 void establishOldSecrets(const AccessCredentials *creds);
281 bool establishNewSecrets(const AccessCredentials *creds, SecurityAgent::Reason reason, bool change);
282
283 bool interactiveUnlock();
284
285 CssmClient::Key keyFromCreds(const TypedList &sample, unsigned int requiredLength);
286 CssmClient::Key keyFromKeybag(const TypedList &sample);
287 CssmClient::Key makeRawKey(void *data, size_t length, CSSM_ALGORITHMS algid, CSSM_KEYUSE usage);
288
289 void encode(); // (re)generate mBlob if needed
290
291 // Counts the number of total interactive unlocks attempted by securityd
292 static uint32_t interactiveUnlockAttempts;
293
294 public:
295 static uint32_t getInteractiveUnlockAttempts();
296
297 private:
298 // all following data is locked by the common lock
299 bool mValidData; // valid ACL and params (blob decoded)
300 CssmAutoData mSecret;
301 bool mSaveSecret;
302
303 uint32 version; // version stamp for blob validity
304 DbBlob *mBlob; // database blob (encoded)
305
306 AccessCredentials *mCred; // local access credentials (always valid)
307
308 RefPointer<KeychainDatabase> mRecodingSource; // keychain synchronization ONLY; should not require accessors
309 bool mRecoded; // true once a recode completes, until recodeFinished is called
310 };
311
312 #endif //_H_KCDATABASE