2  * Copyright (c) 2000-2001,2004-2006,2008-2009 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 // key - representation of securityd key objects 
  31 #include <security_cdsa_utilities/acl_any.h> 
  32 #include <security_cdsa_utilities/cssmendian.h> 
  36 // Create a Key object from a database-encoded blob. 
  37 // Note that this doesn't decode the blob (yet). 
  39 KeychainKey::KeychainKey(Database 
&db
, const KeyBlob 
*blob
) 
  40         : LocalKey(db
, n2h(blob
->header
.attributes())) 
  42     // perform basic validation on the incoming blob 
  44     blob
->validate(CSSMERR_APPLEDL_INVALID_KEY_BLOB
); 
  45     if (blob
->startCryptoBlob 
> blob
->totalLength
) { 
  46         CssmError::throwMe(CSSMERR_APPLEDL_INVALID_KEY_BLOB
); 
  48     switch (blob
->version()) { 
  49 #if defined(COMPAT_OSX_10_0) 
  50     case KeyBlob::version_MacOS_10_0
: 
  53     case KeyBlob::version_MacOS_10_1
: 
  55     case KeyBlob::version_partition
: 
  58         CssmError::throwMe(CSSMERR_APPLEDL_INCOMPATIBLE_KEY_BLOB
); 
  62     mBlob 
= blob
->copy(Allocator::standard()); 
  64         db
.addReference(*this); 
  65     secinfo("SSkey", "%p (handle %#x) created from blob version %x", 
  66                 this, handle(), blob
->version()); 
  71 // Create a Key from an explicit CssmKey. 
  73 KeychainKey::KeychainKey(Database 
&db
, const CssmKey 
&newKey
, uint32 moreAttributes
, 
  74         const AclEntryPrototype 
*owner
) 
  75         : LocalKey(db
, newKey
, moreAttributes
) 
  77         assert(moreAttributes 
& CSSM_KEYATTR_PERMANENT
); 
  81         db
.addReference(*this); 
  85 KeychainKey::~KeychainKey() 
  87     Allocator::standard().free(mBlob
); 
  88     secinfo("SSkey", "%p destroyed", this); 
  92 KeychainDatabase 
&KeychainKey::database() const 
  94         return referent
<KeychainDatabase
>(); 
  99 // Retrieve the actual CssmKey value for the key object. 
 100 // This will decode its blob if needed (and appropriate). 
 102 void KeychainKey::getKey() 
 107 void KeychainKey::getHeader(CssmKey::Header 
&hdr
) 
 111         n2hi(hdr
);      // correct for endian-ness 
 116 // Ensure that a key is fully decoded. 
 117 // This makes the mKey key value available for use, as well as its ACL. 
 118 // Caller must hold the key object lock. 
 120 void KeychainKey::decode() 
 123                 assert(mValidBlob
);     // must have a blob to decode 
 126         void *publicAcl
, *privateAcl
; 
 128         database().decodeKey(mBlob
, key
, publicAcl
, privateAcl
); 
 129                 mKey 
= CssmClient::Key(Server::csp(), key
); 
 130         acl().importBlob(publicAcl
, privateAcl
); 
 131         // publicAcl points into the blob; privateAcl was allocated for us 
 132         Allocator::standard().free(privateAcl
); 
 134         // extract managed attribute bits 
 135         mAttributes 
= mKey
.header().attributes() & managedAttributes
; 
 136         mKey
.header().clearAttribute(managedAttributes
); 
 137                 mKey
.header().setAttribute(forcedAttributes
); 
 146 // Encode a key into a blob. 
 147 // We'll have to ask our Database to do this - we don't have its keys. 
 148 // Note that this returns memory we own and keep. 
 150 KeyBlob 
*KeychainKey::blob() 
 153         assert(mValidKey
);              // must have valid key to encode 
 155         // export Key ACL to blob form 
 156         CssmData pubAcl
, privAcl
; 
 157                 acl().exportBlob(pubAcl
, privAcl
); 
 159         // assemble external key form 
 160         CssmKey externalKey 
= mKey
; 
 161                 externalKey
.clearAttribute(forcedAttributes
); 
 162         externalKey
.setAttribute(mAttributes
); 
 164         // encode the key and replace blob 
 165         KeyBlob 
*newBlob 
= database().encodeKey(externalKey
, pubAcl
, privAcl
); 
 166         Allocator::standard().free(mBlob
); 
 171         acl().allocator
.free(pubAcl
); 
 172         acl().allocator
.free(privAcl
); 
 177 void KeychainKey::invalidateBlob() 
 184 // Override ACL-related methods and events. 
 185 // Decode the key before ACL activity; invalidate the stored blob on ACL edits; 
 186 // and return the key's database as "related". 
 188 void KeychainKey::instantiateAcl() 
 190         StLock
<Mutex
> _(*this); 
 194 void KeychainKey::changedAcl() 
 201 // Intercept Key validation and double-check that the keychain is (still) unlocked 
 203 void KeychainKey::validate(AclAuthorization auth
, const AccessCredentials 
*cred
, 
 204         Database 
*relatedDatabase
) 
 206         if(!mBlob
->isClearText()) { 
 207                 /* unlock not needed for cleartext keys */ 
 208                 if (KeychainDatabase 
*db 
= dynamic_cast<KeychainDatabase 
*>(relatedDatabase
)) 
 211         SecurityServerAcl::validate(auth
, cred
, relatedDatabase
); 
 213     // Need the common lock some more. unlockDb and validate (in validatePartition) also take it, so must be down here. 
 214     StMaybeLock
<Mutex
> lock(relatedDatabase 
&& relatedDatabase
->hasCommon() ? &(relatedDatabase
->common()) : NULL
); 
 215         database().activity();          // upon successful validation 
 222 AclKind 
KeychainKey::aclKind() const 
 228 Database 
*KeychainKey::relatedDatabase() 
 233 SecurityServerAcl 
&KeychainKey::acl()