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 37class KeychainDatabase; 38class KeychainDbCommon; 39class KeychainKey; 40 41 42// 43// We identify KeychainDatabases uniquely by a combination of 44// a DLDbIdentifier and a database (blob) identifier. Equivalence 45// by DbIdentifier is the criterion for parent-side merging. 46// 47class DbIdentifier { 48public: 49 DbIdentifier(const DLDbIdentifier &id, DbBlob::Signature sig) 50 : mIdent(id), mSig(sig) { } 51 52 const DLDbIdentifier &dlDbIdentifier() const { return mIdent; } 53 const DbBlob::Signature &signature() const { return mSig; } 54 operator const DLDbIdentifier &() const { return dlDbIdentifier(); } 55 operator const DbBlob::Signature &() const { return signature(); } 56 const char *dbName() const { return mIdent.dbName(); } 57 58 bool operator < (const DbIdentifier &id) const // simple lexicographic 59 { 60 if (mIdent < id.mIdent) return true; 61 if (id.mIdent < mIdent) return false; 62 return mSig < id.mSig; 63 } 64 65 bool operator == (const DbIdentifier &id) const 66 { return mIdent == id.mIdent && mSig == id.mSig; } 67 68private: 69 DLDbIdentifier mIdent; 70 DbBlob::Signature mSig; 71}; 72 73 74// 75// A vestigal system-global database instance 76// We don't (yet) use it for anything. Perhaps it should carry our ACL... 77// 78class KeychainDbGlobal : public PerGlobal { 79public: 80 KeychainDbGlobal(const DbIdentifier &id); 81 ~KeychainDbGlobal(); 82 83 const DbIdentifier &identifier() const { return mIdentifier; } 84 85private: 86 DbIdentifier mIdentifier; // database external identifier [const] 87}; 88 89 90// 91// KeychainDatabase DbCommons 92// 93class KeychainDbCommon : public LocalDbCommon, 94 public DatabaseCryptoCore, public MachServer::Timer { 95public: 96 KeychainDbCommon(Session &ssn, const DbIdentifier &id); 97 ~KeychainDbCommon(); 98 99 KeychainDbGlobal &global() const; 100 101 bool unlockDb(DbBlob *blob, void **privateAclBlob = NULL); 102 void lockDb(); // make locked (if currently unlocked) 103 bool isLocked() { return mIsLocked; } // lock status 104 void setUnlocked(); 105 void invalidateBlob() { version++; } 106 107 void activity(); // reset lock timeout 108 109 void makeNewSecrets(); 110 111 const DbIdentifier &identifier() const {return mIdentifier; } 112 const DLDbIdentifier &dlDbIdent() const { return identifier(); } 113 const char *dbName() const { return dlDbIdent().dbName(); } 114 bool isLoginKeychain() const { return mLoginKeychain; } 115 116 DbBlob *encode(KeychainDatabase &db); 117 118 void notify(NotificationEvent event) { DbCommon::notify(event, identifier()); } 119 120 void sleepProcessing(); 121 void lockProcessing(); 122 123 bool belongsToSystem() const; 124 125public: 126 // debugging 127 IFDUMP(void dumpNode()); 128 129protected: 130 void action(); // timer queue action to lock keychain 131 132 // lifetime management for our Timer personality 133 void select(); 134 void unselect(); 135 136public: 137 // all following data locked with object lock 138 uint32 sequence; // change sequence number 139 DBParameters mParams; // database parameters (arbitrated copy) 140 141 uint32 version; // version stamp for change tracking 142 143private: 144 DbIdentifier mIdentifier; // database external identifier [const] 145 // all following data protected by object lock 146 bool mIsLocked; // logically locked 147 bool mValidParams; // mParams has been set 148 bool mLoginKeychain; 149}; 150 151 152// 153// A Database object represents an Apple CSP/DL open database (DL/DB) object. 154// It maintains its protected semantic state (including keys) and provides controlled 155// access. 156// 157class KeychainDatabase : public LocalDatabase, private virtual SecurityServerAcl { 158 friend class KeychainDbCommon; 159public: 160 KeychainDatabase(const DLDbIdentifier &id, const DBParameters ¶ms, Process &proc, 161 const AccessCredentials *cred, const AclEntryPrototype *owner); 162 KeychainDatabase(const DLDbIdentifier &id, const DbBlob *blob, Process &proc, 163 const AccessCredentials *cred); 164 165 // keychain synchronization recode to a specfic blob: 166 KeychainDatabase(KeychainDatabase &src, Process &proc, DbHandle dbToClone); 167 virtual ~KeychainDatabase(); 168 169 KeychainDbCommon &common() const; 170 const char *dbName() const; 171 bool transient() const; 172 173 KeychainDbGlobal &global() const { return common().global(); } 174 175public: 176 static const int maxUnlockTryCount = 3; 177 178public: 179 const DbIdentifier &identifier() const { return common().identifier(); } 180 181public: 182 // encoding/decoding databases 183 DbBlob *blob(); 184 185 void authenticate(CSSM_DB_ACCESS_TYPE mode, const AccessCredentials *cred); 186 void changePassphrase(const AccessCredentials *cred); 187 RefPointer<Key> extractMasterKey(Database &db, const AccessCredentials *cred, 188 const AclEntryPrototype *owner, uint32 usage, uint32 attrs); 189 void commitSecretsForSync(KeychainDatabase &cloneDb); 190 191 // lock/unlock processing 192 void lockDb(); // unconditional lock 193 void unlockDb(); // full-feature unlock 194 void unlockDb(const CssmData &passphrase); // unlock with passphrase 195 196 void stashDbCheck(); // check AppleKeyStore for master key 197 void stashDb(); // stash master key in AppleKeyStore 198 199 bool decode(); // unlock given established master key 200 bool decode(const CssmData &passphrase); // set master key from PP, try unlock 201 202 bool validatePassphrase(const CssmData &passphrase) const; // nonthrowing validation 203 bool isLocked() { return common().isLocked(); } // lock status 204 void notify(NotificationEvent event) { return common().notify(event); } 205 void activity() const { common().activity(); } // reset timeout clock 206 207 // encoding/decoding keys 208 void decodeKey(KeyBlob *blob, CssmKey &key, void * &pubAcl, void * &privAcl); 209 KeyBlob *encodeKey(const CssmKey &key, const CssmData &pubAcl, const CssmData &privAcl); 210 KeyBlob *recodeKey(KeychainKey &oldKey); 211 bool validBlob() const { return mBlob && version == common().version; } 212 213 // manage database parameters 214 void setParameters(const DBParameters ¶ms); 215 void getParameters(DBParameters ¶ms); 216 217 // where's my (database) ACL? 218 SecurityServerAcl &acl(); 219 220 AclKind aclKind() const; 221 Database *relatedDatabase(); 222 223 // ACL state management hooks 224 void instantiateAcl(); 225 void changedAcl(); 226 227 // miscellaneous utilities 228 static void validateBlob(const DbBlob *blob); 229 230 // debugging 231 IFDUMP(void dumpNode()); 232 233protected: 234 RefPointer<Key> makeKey(const CssmKey &newKey, uint32 moreAttributes, const AclEntryPrototype *owner); 235 RefPointer<Key> makeKey(Database &db, const CssmKey &newKey, uint32 moreAttributes, const AclEntryPrototype *owner); 236 237 void makeUnlocked(); // interior version of unlock() 238 void makeUnlocked(const AccessCredentials *cred); // like () with explicit cred 239 void makeUnlocked(const CssmData &passphrase); // interior version of unlock(CssmData) 240 241 void establishOldSecrets(const AccessCredentials *creds); 242 void establishNewSecrets(const AccessCredentials *creds, SecurityAgent::Reason reason); 243 244 bool interactiveUnlock(); 245 246 CssmClient::Key keyFromCreds(const TypedList &sample, unsigned int requiredLength); 247 248 void encode(); // (re)generate mBlob if needed 249 250private: 251 // all following data is locked by the common lock 252 bool mValidData; // valid ACL and params (blob decoded) 253 CssmAutoData mSecret; 254 bool mSaveSecret; 255 256 uint32 version; // version stamp for blob validity 257 DbBlob *mBlob; // database blob (encoded) 258 259 AccessCredentials *mCred; // local access credentials (always valid) 260 261 RefPointer<KeychainDatabase> mRecodingSource; // keychain synchronization ONLY; should not require accessors 262}; 263 264#endif //_H_KCDATABASE 265