2  * Copyright (c) 2000-2008,2011-2013 Apple Inc. All Rights Reserved. 
   4  * @APPLE_LICENSE_HEADER_START@ 
   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 
  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. 
  21  * @APPLE_LICENSE_HEADER_END@ 
  26 // ssclient - SecurityServer client interface library 
  28 // This interface is private to the Security system. It is not a public interface, 
  29 // and it may change at any time. You have been warned. 
  35 #include <Security/Authorization.h> 
  36 #include <Security/AuthSession.h> 
  37 #include <Security/SecCodeHost.h> 
  41 #include <security_utilities/osxcode.h> 
  42 #include <security_utilities/unix++.h> 
  43 #include <security_utilities/globalizer.h> 
  44 #include <security_cdsa_utilities/cssmerrors.h> 
  49 namespace SecurityServer 
{ 
  55 // Unique-identifier blobs for key objects 
  57 typedef struct KeyUID 
{ 
  63 // Maximum length of hash (digest) arguments (bytes) 
  65 #define maxUcspHashLength 64 
  69 // Authorization blobs 
  71 typedef struct AuthorizationBlob 
{ 
  75         bool operator < (const AuthorizationBlob 
&other
) const 
  76         { return memcmp(data
, other
.data
, sizeof(data
)) < 0; } 
  78         bool operator == (const AuthorizationBlob 
&other
) const 
  79         { return memcmp(data
, other
.data
, sizeof(data
)) == 0; } 
  81     size_t hash() const {       //@@@ revisit this hash 
  82         return data
[0] ^ data
[1] << 3; 
  89 // Initial-setup data for versioning etc. 
  96 #define SSPROTOVERSION 20000 
 100 // Database parameter structure 
 103         uint32_t idleTimeout
;                           // seconds idle timout lock 
 104         uint8_t lockOnSleep
;                            // lock keychain when system sleeps 
 112 // A client connection (session) 
 114 class ClientSession 
: public ClientCommon 
{ 
 116         ClientSession(Allocator 
&standard 
= Allocator::standard(), 
 117                 Allocator 
&returning 
= Allocator::standard()); 
 118         virtual ~ClientSession(); 
 125         // use this only if you know what you're doing... 
 126         void contactName(const char *name
); 
 127         const char *contactName() const; 
 129     static GenericHandle 
toIPCHandle(CSSM_HANDLE h
) { 
 130         // implementation subject to change 
 131         if (h 
& (CSSM_HANDLE(~0) ^ GenericHandle(~0))) 
 132             CssmError::throwMe(CSSM_ERRCODE_INVALID_CONTEXT_HANDLE
); 
 133         return h 
& GenericHandle(~0); 
 139         // common database interface 
 141         void authenticateDb(DbHandle db
, CSSM_DB_ACCESS_TYPE type
, const AccessCredentials 
*cred
); 
 142         void releaseDb(DbHandle db
); 
 145         // External database interface 
 147         DbHandle 
openToken(uint32 ssid
, const AccessCredentials 
*cred
, const char *name 
= NULL
); 
 149         RecordHandle 
insertRecord(DbHandle db
, 
 150                                           CSSM_DB_RECORDTYPE recordType
, 
 151                                           const CssmDbRecordAttributeData 
*attributes
, 
 152                                           const CssmData 
*data
); 
 153         void deleteRecord(DbHandle db
, RecordHandle record
); 
 154         void modifyRecord(DbHandle db
, RecordHandle 
&record
, 
 155                                           CSSM_DB_RECORDTYPE recordType
, 
 156                                           const CssmDbRecordAttributeData 
*attributesToBeModified
, 
 157                                           const CssmData 
*dataToBeModified
, 
 158                                           CSSM_DB_MODIFY_MODE modifyMode
); 
 160         RecordHandle 
findFirst(DbHandle db
, 
 161                                                 const CssmQuery 
&query
, 
 162                                                 SearchHandle 
&outSearchHandle
, 
 163                                                 CssmDbRecordAttributeData 
*inOutAttributes
, 
 164                                                 CssmData 
*outData
, KeyHandle 
&key
); 
 165         RecordHandle 
findNext(SearchHandle searchHandle
, 
 166                                            CssmDbRecordAttributeData 
*inOutAttributes
, 
 167                                            CssmData 
*inOutData
, KeyHandle 
&key
); 
 168         void findRecordHandle(RecordHandle record
, 
 169                                                  CssmDbRecordAttributeData 
*inOutAttributes
, 
 170                                                  CssmData 
*inOutData
, KeyHandle 
&key
); 
 171         void releaseSearch(SearchHandle searchHandle
); 
 172         void releaseRecord(RecordHandle record
); 
 174         void getDbName(DbHandle db
, std::string 
&name
); 
 175         void setDbName(DbHandle db
, const std::string 
&name
); 
 178         // Internal database interface 
 180         DbHandle 
createDb(const DLDbIdentifier 
&dbId
, 
 181         const AccessCredentials 
*cred
, const AclEntryInput 
*owner
, 
 182         const DBParameters 
¶ms
); 
 183         DbHandle 
cloneDbForSync(const CssmData 
&secretsBlob
, DbHandle srcDb
,  
 184                                                         const CssmData 
&agentData
); 
 185         DbHandle 
recodeDbForSync(DbHandle dbToClone
, DbHandle srcDb
); 
 186         DbHandle 
authenticateDbsForSync(const CssmData 
&dbHandleArray
, const CssmData 
&agentData
); 
 187     void commitDbForSync(DbHandle srcDb
, DbHandle cloneDb
, CssmData 
&blob
, Allocator 
&alloc
); 
 188         DbHandle 
decodeDb(const DLDbIdentifier 
&dbId
, 
 189         const AccessCredentials 
*cred
, const CssmData 
&blob
); 
 190         void encodeDb(DbHandle db
, CssmData 
&blob
, Allocator 
&alloc
); 
 191     void encodeDb(DbHandle db
, CssmData 
&blob
) { return encodeDb(db
, blob
, returnAllocator
); } 
 192         void setDbParameters(DbHandle db
, const DBParameters 
¶ms
); 
 193         void getDbParameters(DbHandle db
, DBParameters 
¶ms
); 
 194     void changePassphrase(DbHandle db
, const AccessCredentials 
*cred
); 
 195     void lock(DbHandle db
); 
 196     void lockAll(bool forSleep
); 
 197     void unlock(DbHandle db
); 
 198     void unlock(DbHandle db
, const CssmData 
&passPhrase
); 
 199     void stashDb(DbHandle db
); 
 200     void stashDbCheck(DbHandle db
); 
 201     bool isLocked(DbHandle db
); 
 202     void verifyKeyStorePassphrase(uint32_t retries
); 
 203     void resetKeyStorePassphrase(const CssmData 
&passphrase
); 
 204     void changeKeyStorePassphrase(); 
 210         void encodeKey(KeyHandle key
, CssmData 
&blob
, KeyUID 
*uid
, Allocator 
&alloc
); 
 211         void encodeKey(KeyHandle key
, CssmData 
&blob
, KeyUID 
*uid 
= NULL
) 
 212     { return encodeKey(key
, blob
, uid
, returnAllocator
); } 
 213         KeyHandle 
decodeKey(DbHandle db
, const CssmData 
&blob
, CssmKey::Header 
&header
); 
 214         void recodeKey(DbHandle oldDb
, KeyHandle key
, DbHandle newDb
, CssmData 
&blob
); 
 215         void releaseKey(KeyHandle key
); 
 217         CssmKeySize 
queryKeySizeInBits(KeyHandle key
); 
 218     uint32 
getOutputSize(const Security::Context 
&context
, KeyHandle key
, 
 219         uint32 inputSize
, bool encrypt 
= true); 
 221         void getKeyDigest(KeyHandle key
, CssmData 
&digest
, Allocator 
&alloc
); 
 222         void getKeyDigest(KeyHandle key
, CssmData 
&digest
) 
 223         { return getKeyDigest(key
, digest
, returnAllocator
); } 
 226     // key wrapping and unwrapping 
 227         void wrapKey(const Security::Context 
&context
, KeyHandle key
, KeyHandle keyToBeWrapped
, 
 228                 const AccessCredentials 
*cred
, 
 229                 const CssmData 
*descriptiveData
, CssmWrappedKey 
&wrappedKey
, Allocator 
&alloc
); 
 230         void wrapKey(const Security::Context 
&context
, KeyHandle key
, KeyHandle keyToBeWrapped
, 
 231                 const AccessCredentials 
*cred
, 
 232                 const CssmData 
*descriptiveData
, CssmWrappedKey 
&wrappedKey
) 
 233     { return wrapKey(context
, key
, keyToBeWrapped
, cred
, 
 234         descriptiveData
, wrappedKey
, returnAllocator
); } 
 236         void unwrapKey(DbHandle db
, const Security::Context 
&context
, KeyHandle key
, KeyHandle publicKey
, 
 237                 const CssmWrappedKey 
&wrappedKey
, uint32 keyUsage
, uint32 keyAttr
, 
 238                 const AccessCredentials 
*cred
, const AclEntryInput 
*owner
, 
 239                 CssmData 
&data
, KeyHandle 
&newKey
, CssmKey::Header 
&newKeyHeader
, Allocator 
&alloc
); 
 240         void unwrapKey(DbHandle db
, const Security::Context 
&context
, KeyHandle key
, KeyHandle publicKey
, 
 241                 const CssmWrappedKey 
&wrappedKey
, uint32 keyUsage
, uint32 keyAttr
, 
 242                 const AccessCredentials 
*cred
, const AclEntryInput 
*owner
, CssmData 
&data
, 
 243         KeyHandle 
&newKey
, CssmKey::Header 
&newKeyHeader
) 
 244     { return unwrapKey(db
, context
, key
, publicKey
, wrappedKey
, keyUsage
, keyAttr
, 
 245       cred
, owner
, data
, newKey
, newKeyHeader
, returnAllocator
); } 
 247     // key generation and derivation 
 248         void generateKey(DbHandle db
, const Security::Context 
&context
, uint32 keyUsage
, uint32 keyAttr
, 
 249                 const AccessCredentials 
*cred
, const AclEntryInput 
*owner
, 
 250         KeyHandle 
&newKey
, CssmKey::Header 
&newHeader
); 
 251         void generateKey(DbHandle db
, const Security::Context 
&context
, 
 252                 uint32 pubKeyUsage
, uint32 pubKeyAttr
, 
 253                 uint32 privKeyUsage
, uint32 privKeyAttr
, 
 254                 const AccessCredentials 
*cred
, const AclEntryInput 
*owner
, 
 255                 KeyHandle 
&pubKey
, CssmKey::Header 
&pubHeader
, 
 256         KeyHandle 
&privKey
, CssmKey::Header 
&privHeader
); 
 257         void deriveKey(DbHandle db
, const Security::Context 
&context
, KeyHandle baseKey
, 
 258         uint32 keyUsage
, uint32 keyAttr
, CssmData 
¶m
, 
 259                 const AccessCredentials 
*cred
, const AclEntryInput 
*owner
, 
 260         KeyHandle 
&newKey
, CssmKey::Header 
&newHeader
, Allocator 
&alloc
); 
 261         void deriveKey(DbHandle db
, const Security::Context 
&context
, KeyHandle baseKey
, 
 262         uint32 keyUsage
, uint32 keyAttr
, CssmData 
¶m
, 
 263                 const AccessCredentials 
*cred
, const AclEntryInput 
*owner
, 
 264         KeyHandle 
&newKey
, CssmKey::Header 
&newHeader
) 
 265     { return deriveKey(db
, context
, baseKey
, keyUsage
, keyAttr
, param
, cred
, owner
, newKey
, newHeader
, returnAllocator
); } 
 266         //void generateAlgorithmParameters();   // not implemented 
 268         void generateRandom(const Security::Context 
&context
, CssmData 
&data
, Allocator 
&alloc
); 
 269         void generateRandom(const Security::Context 
&context
, CssmData 
&data
) 
 270         { return generateRandom(context
, data
, returnAllocator
); } 
 273         void encrypt(const Security::Context 
&context
, KeyHandle key
, 
 274         const CssmData 
&in
, CssmData 
&out
, Allocator 
&alloc
); 
 275         void encrypt(const Security::Context 
&context
, KeyHandle key
, const CssmData 
&in
, CssmData 
&out
) 
 276     { return encrypt(context
, key
, in
, out
, returnAllocator
); } 
 277         void decrypt(const Security::Context 
&context
, KeyHandle key
, 
 278         const CssmData 
&in
, CssmData 
&out
, Allocator 
&alloc
); 
 279         void decrypt(const Security::Context 
&context
, KeyHandle key
, const CssmData 
&in
, CssmData 
&out
) 
 280     { return decrypt(context
, key
, in
, out
, returnAllocator
); } 
 283         void generateSignature(const Security::Context 
&context
, KeyHandle key
, 
 284         const CssmData 
&data
, CssmData 
&signature
, Allocator 
&alloc
, 
 285         CSSM_ALGORITHMS signOnlyAlgorithm 
= CSSM_ALGID_NONE
); 
 286         void generateSignature(const Security::Context 
&context
, KeyHandle key
, 
 287                 const CssmData 
&data
, CssmData 
&signature
, CSSM_ALGORITHMS signOnlyAlgorithm 
= CSSM_ALGID_NONE
) 
 288     { return generateSignature(context
, key
, data
, signature
, returnAllocator
, signOnlyAlgorithm
); } 
 289         void verifySignature(const Security::Context 
&context
, KeyHandle key
, 
 290                 const CssmData 
&data
, const CssmData 
&signature
, 
 291         CSSM_ALGORITHMS verifyOnlyAlgorithm 
= CSSM_ALGID_NONE
); 
 294         void generateMac(const Security::Context 
&context
, KeyHandle key
, 
 295                 const CssmData 
&data
, CssmData 
&mac
, Allocator 
&alloc
); 
 296         void generateMac(const Security::Context 
&context
, KeyHandle key
, 
 297                 const CssmData 
&data
, CssmData 
&mac
) 
 298     { return generateMac(context
, key
, data
, mac
, returnAllocator
); } 
 299         void verifyMac(const Security::Context 
&context
, KeyHandle key
, 
 300                 const CssmData 
&data
, const CssmData 
&mac
); 
 302     // key ACL management 
 303         void getKeyAcl(KeyHandle key
, const char *tag
, 
 304         uint32 
&count
, AclEntryInfo 
* &info
, Allocator 
&alloc
); 
 305         void getKeyAcl(KeyHandle key
, const char *tag
, 
 306         uint32 
&count
, AclEntryInfo 
* &info
) 
 307     { return getKeyAcl(key
, tag
, count
, info
, returnAllocator
); } 
 308         void changeKeyAcl(KeyHandle key
, const AccessCredentials 
&cred
, const AclEdit 
&edit
); 
 309         void getKeyOwner(KeyHandle key
, AclOwnerPrototype 
&owner
, Allocator 
&alloc
); 
 310         void getKeyOwner(KeyHandle key
, AclOwnerPrototype 
&owner
) 
 311     { return getKeyOwner(key
, owner
, returnAllocator
); } 
 312         void changeKeyOwner(KeyHandle key
, const AccessCredentials 
&cred
, 
 313                 const AclOwnerPrototype 
&edit
); 
 315     // database ACL management 
 316         void getDbAcl(DbHandle db
, const char *tag
, 
 317         uint32 
&count
, AclEntryInfo 
* &info
, Allocator 
&alloc
); 
 318         void getDbAcl(DbHandle db
, const char *tag
, 
 319         uint32 
&count
, AclEntryInfo 
* &info
) 
 320     { return getDbAcl(db
, tag
, count
, info
, returnAllocator
); } 
 321         void changeDbAcl(DbHandle db
, const AccessCredentials 
&cred
, const AclEdit 
&edit
); 
 322         void getDbOwner(DbHandle db
, AclOwnerPrototype 
&owner
, Allocator 
&alloc
); 
 323         void getDbOwner(DbHandle db
, AclOwnerPrototype 
&owner
) 
 324     { return getDbOwner(db
, owner
, returnAllocator
); } 
 325     void changeDbOwner(DbHandle db
, const AccessCredentials 
&cred
, 
 326                 const AclOwnerPrototype 
&edit
); 
 328         // database key manipulations 
 329         void extractMasterKey(DbHandle db
, const Context 
&context
, DbHandle sourceDb
, 
 330         uint32 keyUsage
, uint32 keyAttr
, 
 331                 const AccessCredentials 
*cred
, const AclEntryInput 
*owner
, 
 332         KeyHandle 
&newKey
, CssmKey::Header 
&newHeader
, Allocator 
&alloc
); 
 333         void extractMasterKey(DbHandle db
, const Context 
&context
, DbHandle sourceDb
, 
 334         uint32 keyUsage
, uint32 keyAttr
, 
 335                 const AccessCredentials 
*cred
, const AclEntryInput 
*owner
, 
 336         KeyHandle 
&newKey
, CssmKey::Header 
&newHeader
) 
 337         { return extractMasterKey(db
, context
, sourceDb
, keyUsage
, keyAttr
, cred
, owner
, 
 338                 newKey
, newHeader
, returnAllocator
); } 
 341         // Authorization API support 
 342         void authCreate(const AuthorizationItemSet 
*rights
,     const AuthorizationItemSet 
*environment
,  
 343                 AuthorizationFlags flags
,AuthorizationBlob 
&result
); 
 344         void authRelease(const AuthorizationBlob 
&auth
, AuthorizationFlags flags
); 
 345         void authCopyRights(const AuthorizationBlob 
&auth
, 
 346                 const AuthorizationItemSet 
*rights
, const AuthorizationItemSet 
*environment
, 
 347                 AuthorizationFlags flags
, AuthorizationItemSet 
**result
); 
 348         void authCopyInfo(const AuthorizationBlob 
&auth
, const char *tag
, AuthorizationItemSet 
* &info
); 
 349         void authExternalize(const AuthorizationBlob 
&auth
, AuthorizationExternalForm 
&extForm
); 
 350         void authInternalize(const AuthorizationExternalForm 
&extForm
, AuthorizationBlob 
&auth
); 
 353     // Session API support 
 354         void setSessionUserPrefs(SecuritySessionId sessionId
, uint32_t userPreferencesLength
, const void *userPreferences
); 
 357     // Notification core support 
 358     void postNotification(NotificationDomain domain
, NotificationEvent event
, const CssmData 
&data
); 
 360         // low-level callback (C form) 
 361     typedef OSStatus 
ConsumeNotification(NotificationDomain domain
, NotificationEvent event
, 
 362         const void *data
, size_t dataLength
, void *context
); 
 365         // AuthorizationDB API 
 366         void authorizationdbGet(const AuthorizationString rightname
, CssmData 
&rightDefinition
, Allocator 
&alloc
); 
 367         void authorizationdbSet(const AuthorizationBlob 
&auth
, const AuthorizationString rightname
, uint32_t rightdefinitionLength
, const void *rightdefinition
); 
 368         void authorizationdbRemove(const AuthorizationBlob 
&auth
, const AuthorizationString rightname
); 
 371         // securityd helper support 
 372         void childCheckIn(Port serverPort
, Port taskPort
); 
 375         // temporary hack to deal with "edit acl" pseudo-error returns 
 376         typedef void DidChangeKeyAclCallback(void *context
, ClientSession 
&clientSession
, 
 377                 KeyHandle key
, CSSM_ACL_AUTHORIZATION_TAG tag
); 
 378         void registerForAclEdits(DidChangeKeyAclCallback 
*callback
, void *context
); 
 381         // Code Signing hosting interface 
 382         void registerHosting(mach_port_t hostingPort
, SecCSFlags flags
); 
 383         mach_port_t 
hostingPort(pid_t pid
); 
 385         SecGuestRef 
createGuest(SecGuestRef host
, 
 386                 uint32_t status
, const char *path
, const CssmData 
&cdhash
, const CssmData 
&attributes
, SecCSFlags flags
); 
 387         void setGuestStatus(SecGuestRef guest
, uint32 status
, const CssmData 
&attributes
); 
 388         void removeGuest(SecGuestRef host
, SecGuestRef guest
); 
 390         void selectGuest(SecGuestRef guest
); 
 391         SecGuestRef 
selectedGuest() const;  
 394         static Port 
findSecurityd(); 
 395         void getAcl(AclKind kind
, GenericHandle key
, const char *tag
, 
 396                 uint32 
&count
, AclEntryInfo 
* &info
, Allocator 
&alloc
); 
 397         void changeAcl(AclKind kind
, GenericHandle key
, 
 398                 const AccessCredentials 
&cred
, const AclEdit 
&edit
); 
 399         void getOwner(AclKind kind
, GenericHandle key
, 
 400                 AclOwnerPrototype 
&owner
, Allocator 
&alloc
); 
 401         void changeOwner(AclKind kind
, GenericHandle key
, 
 402                 const AccessCredentials 
&cred
, const AclOwnerPrototype 
&edit
); 
 404         static OSStatus 
consumerDispatch(NotificationDomain domain
, NotificationEvent event
, 
 405                 const void *data
, size_t dataLength
, void *context
); 
 407         void notifyAclChange(KeyHandle key
, CSSM_ACL_AUTHORIZATION_TAG tag
); 
 409         void returnAttrsAndData(CssmDbRecordAttributeData 
*inOutAttributes
, 
 410                 CssmDbRecordAttributeData 
*attrs
, CssmDbRecordAttributeData 
*attrsBase
, mach_msg_type_number_t attrsLength
, 
 411                 CssmData 
*inOutData
, void *dataPtr
, mach_msg_type_number_t dataLength
); 
 413         DidChangeKeyAclCallback 
*mCallback
; 
 414         void *mCallbackContext
; 
 416         static UnixPlusPlus::StaticForkMonitor mHasForked
;      // global fork indicator 
 419                 Thread() : registered(false), notifySeq(0), 
 420                         currentGuest(kSecNoGuest
), lastGuest(kSecNoGuest
) { } 
 421                 operator bool() const { return registered
; } 
 423                 ReceivePort replyPort
;  // dedicated reply port (send right held by SecurityServer) 
 424         bool registered
;                // has been registered with SecurityServer 
 425                 uint32 notifySeq
; // notification sequence number 
 427                 SecGuestRef currentGuest
;       // last set guest path 
 428                 SecGuestRef lastGuest
;          // last transmitted guest path 
 434                 RefPointer
<OSXCode
> myself
; 
 435                 ThreadNexus
<Thread
> thread
; 
 438         static ModuleNexus
<Global
> mGlobal
; 
 439         static const char *mContactName
; 
 440         static SecGuestRef mDedicatedGuest
; 
 444 } // end namespace SecurityServer 
 445 } // end namespace Security