2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
20 // key - representation of SecurityServer key objects
24 #include "xdatabase.h"
25 #include <Security/acl_any.h>
29 // Create a Key object from a database-encoded blob.
30 // Note that this doesn't decode the blob (yet).
32 Key::Key(Database
&db
, const KeyBlob
*blob
)
33 : SecurityServerAcl(keyAcl
, CssmAllocator::standard())
35 // perform basic validation on the incoming blob
37 blob
->validate(CSSMERR_APPLEDL_INVALID_KEY_BLOB
);
38 switch (blob
->version
) {
39 #if defined(COMPAT_OSX_10_0)
40 case blob
->version_MacOS_10_0
:
43 case blob
->version_MacOS_10_1
:
46 CssmError::throwMe(CSSMERR_APPLEDL_INCOMPATIBLE_KEY_BLOB
);
51 mBlob
= blob
->copy(CssmAllocator::standard());
56 debug("SSkey", "%p created from blob version %lx", this, blob
->version
);
61 // Create a Key from an explicit CssmKey.
63 Key::Key(Database
*db
, const CssmKey
&newKey
, uint32 moreAttributes
,
64 const AclEntryPrototype
*owner
)
65 : SecurityServerAcl(keyAcl
, CssmAllocator::standard())
67 if (moreAttributes
& CSSM_KEYATTR_PERMANENT
) {
68 // better have a database to make it permanent in...
70 CssmError::throwMe(CSSMERR_CSP_MISSING_ATTR_DL_DB_HANDLE
);
72 // non-permanent; ignore database
81 setup(newKey
, moreAttributes
);
83 // establish initial ACL; reinterpret empty (null-list) owner as NULL for resilence's sake
84 if (owner
&& !owner
->subject().empty())
85 cssmSetInitial(*owner
); // specified
87 cssmSetInitial(new AnyAclSubject()); // defaulted
88 debug("SSkey", "%p created from key alg=%ld use=0x%lx attr=0x%lx db=%p",
89 this, mKey
.algorithm(), mKey
.usage(), mAttributes
, db
);
94 // Set up the CssmKey part of this Key according to instructions.
96 void Key::setup(const CssmKey
&newKey
, uint32 moreAttributes
)
98 CssmKey::Header
&header
= mKey
.header();
101 header
= newKey
.header();
102 mAttributes
= header
.attributes() | moreAttributes
;
104 // apply initial values of derived attributes (these are all in managedAttributes)
105 if (!(mAttributes
& CSSM_KEYATTR_EXTRACTABLE
))
106 mAttributes
|= CSSM_KEYATTR_NEVER_EXTRACTABLE
;
107 if (mAttributes
& CSSM_KEYATTR_SENSITIVE
)
108 mAttributes
|= CSSM_KEYATTR_ALWAYS_SENSITIVE
;
110 // verify internal/external attribute separation
111 assert(!(header
.attributes() & managedAttributes
));
113 // copy key data field, using the CSP's allocator (so the release operation works later)
114 mKey
.KeyData
= CssmAutoData(Server::csp().allocator(), newKey
).release();
120 CssmAllocator::standard().free(mBlob
);
122 Server::csp()->freeKey(mKey
);
123 debug("SSkey", "%p destroyed", this);
128 // Form a KeySpec with checking and masking
130 Key::KeySpec::KeySpec(uint32 usage
, uint32 attrs
)
131 : CssmClient::KeySpec(usage
, attrs
& ~managedAttributes
)
133 if (attrs
& generatedAttributes
)
134 CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK
);
137 Key::KeySpec::KeySpec(uint32 usage
, uint32 attrs
, const CssmData
&label
)
138 : CssmClient::KeySpec(usage
, attrs
& ~managedAttributes
, label
)
140 if (attrs
& generatedAttributes
)
141 CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK
);
146 // Retrieve the actual CssmKey value for the key object.
147 // This will decode its blob if needed (and appropriate).
149 CssmKey
&Key::keyValue()
157 // Ensure that a key is fully decoded.
158 // This makes the mKey key value available for use, as well as its ACL.
163 assert(mDatabase
); // have to have a database (to decode the blob)
164 assert(mValidBlob
); // must have a blob to decode
167 void *publicAcl
, *privateAcl
;
168 database()->decodeKey(mBlob
, mKey
, publicAcl
, privateAcl
);
169 importBlob(publicAcl
, privateAcl
);
170 // publicAcl points into the blob; privateAcl was allocated for us
171 CssmAllocator::standard().free(privateAcl
);
173 // extract managed attribute bits
174 mAttributes
= mKey
.attributes() & managedAttributes
;
175 mKey
.clearAttribute(managedAttributes
);
184 // Retrieve the header (only) of a key.
185 // This is taking the clear header from the blob *without* verifying it.
187 CssmKey::Header
&Key::keyHeader()
190 return mKey
.header();
193 return mBlob
->header
;
199 // Return a key's handle and header in external form
201 void Key::returnKey(Handle
&h
, CssmKey::Header
&hdr
)
206 // return header with external attributes merged
208 hdr
.setAttribute(mAttributes
);
213 // Encode a key into a blob.
214 // We'll have to ask our Database to do this - we don't have its keys.
215 // Note that this returns memory we own and keep.
219 if (mDatabase
== NULL
) // can't encode independent keys
220 CssmError::throwMe(CSSMERR_DL_INVALID_DB_HANDLE
);
222 assert(mValidKey
); // must have valid key to encode
223 //@@@ release mBlob memory here
225 // export Key ACL to blob form
226 CssmData pubAcl
, privAcl
;
227 exportBlob(pubAcl
, privAcl
);
229 // assemble external key form
230 CssmKey externalKey
= mKey
;
231 externalKey
.setAttribute(mAttributes
);
233 // encode the key and replace blob
234 KeyBlob
*newBlob
= database()->encodeKey(externalKey
, pubAcl
, privAcl
);
235 CssmAllocator::standard().free(mBlob
);
240 database()->allocator
.free(pubAcl
);
241 database()->allocator
.free(privAcl
);
248 // Return the UID of a key (the hash of its bits)
253 //@@@ calculate UID here
254 memset(&mUID
, 0, sizeof(mUID
));
262 // Intercept ACL change requests and reset blob validity
264 void Key::instantiateAcl()
269 void Key::noticeAclChange()
274 const Database
*Key::relatedDatabase() const
275 { return database(); }