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()), mDigest(Server::csp().allocator())
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 secdebug("SSkey", "%p (handle 0x%lx) created from blob version %lx",
57 this, handle(), blob
->version());
62 // Create a Key from an explicit CssmKey.
64 Key::Key(Database
*db
, const CssmKey
&newKey
, uint32 moreAttributes
,
65 const AclEntryPrototype
*owner
)
66 : SecurityServerAcl(keyAcl
, CssmAllocator::standard()), mDigest(Server::csp().allocator())
68 if (moreAttributes
& CSSM_KEYATTR_PERMANENT
) {
69 // better have a database to make it permanent in...
71 CssmError::throwMe(CSSMERR_CSP_MISSING_ATTR_DL_DB_HANDLE
);
73 // non-permanent; ignore database
82 setup(newKey
, moreAttributes
);
84 // establish initial ACL; reinterpret empty (null-list) owner as NULL for resilence's sake
85 if (owner
&& !owner
->subject().empty())
86 cssmSetInitial(*owner
); // specified
88 cssmSetInitial(new AnyAclSubject()); // defaulted
89 secdebug("SSkey", "%p (handle 0x%lx) created from key alg=%ld use=0x%lx attr=0x%lx db=%p",
90 this, handle(), mKey
.header().algorithm(), mKey
.header().usage(), mAttributes
, db
);
95 // Set up the CssmKey part of this Key according to instructions.
97 void Key::setup(const CssmKey
&newKey
, uint32 moreAttributes
)
99 mKey
= CssmClient::Key(Server::csp(), newKey
, false);
100 CssmKey::Header
&header
= mKey
->header();
103 header
= newKey
.header();
104 mAttributes
= (header
.attributes() & ~forcedAttributes
) | moreAttributes
;
106 // apply initial values of derived attributes (these are all in managedAttributes)
107 if (!(mAttributes
& CSSM_KEYATTR_EXTRACTABLE
))
108 mAttributes
|= CSSM_KEYATTR_NEVER_EXTRACTABLE
;
109 if (mAttributes
& CSSM_KEYATTR_SENSITIVE
)
110 mAttributes
|= CSSM_KEYATTR_ALWAYS_SENSITIVE
;
112 // verify internal/external attribute separation
113 assert((header
.attributes() & managedAttributes
) == forcedAttributes
);
119 CssmAllocator::standard().free(mBlob
);
120 secdebug("SSkey", "%p destroyed", this);
125 // Form a KeySpec with checking and masking
127 Key::KeySpec::KeySpec(uint32 usage
, uint32 attrs
)
128 : CssmClient::KeySpec(usage
, (attrs
& ~managedAttributes
) | forcedAttributes
)
130 if (attrs
& generatedAttributes
)
131 CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK
);
134 Key::KeySpec::KeySpec(uint32 usage
, uint32 attrs
, const CssmData
&label
)
135 : CssmClient::KeySpec(usage
, (attrs
& ~managedAttributes
) | forcedAttributes
, label
)
137 if (attrs
& generatedAttributes
)
138 CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK
);
143 // Retrieve the actual CssmKey value for the key object.
144 // This will decode its blob if needed (and appropriate).
146 CssmClient::Key
Key::keyValue()
154 // Ensure that a key is fully decoded.
155 // This makes the mKey key value available for use, as well as its ACL.
160 assert(mDatabase
); // have to have a database (to decode the blob)
161 assert(mValidBlob
); // must have a blob to decode
164 void *publicAcl
, *privateAcl
;
166 database()->decodeKey(mBlob
, key
, publicAcl
, privateAcl
);
167 mKey
= CssmClient::Key(Server::csp(), key
);
168 importBlob(publicAcl
, privateAcl
);
169 // publicAcl points into the blob; privateAcl was allocated for us
170 CssmAllocator::standard().free(privateAcl
);
172 // extract managed attribute bits
173 mAttributes
= mKey
.header().attributes() & managedAttributes
;
174 mKey
.header().clearAttribute(managedAttributes
);
175 mKey
.header().setAttribute(forcedAttributes
);
184 // Return a key's handle and header in external form
186 void Key::returnKey(Handle
&h
, CssmKey::Header
&hdr
)
191 // obtain the key header, from the valid key or the blob if no valid key
197 n2hi(hdr
); // correct for endian-ness
200 // adjust for external attributes
201 hdr
.clearAttribute(forcedAttributes
);
202 hdr
.setAttribute(mAttributes
);
207 // Generate the canonical key digest.
208 // This is defined by a CSP feature that we invoke here.
210 const CssmData
&Key::canonicalDigest()
213 CssmClient::PassThrough
ctx(Server::csp());
215 CssmData
*digest
= NULL
;
216 ctx(CSSM_APPLECSP_KEYDIGEST
, (const void *)NULL
, &digest
);
218 mDigest
.set(*digest
); // takes ownership of digest data
219 Server::csp().allocator().free(digest
); // the CssmData itself
221 return mDigest
.get();
226 // Encode a key into a blob.
227 // We'll have to ask our Database to do this - we don't have its keys.
228 // Note that this returns memory we own and keep.
232 if (mDatabase
== NULL
) // can't encode independent keys
233 CssmError::throwMe(CSSMERR_DL_INVALID_DB_HANDLE
);
235 assert(mValidKey
); // must have valid key to encode
236 //@@@ release mBlob memory here
238 // export Key ACL to blob form
239 CssmData pubAcl
, privAcl
;
240 exportBlob(pubAcl
, privAcl
);
242 // assemble external key form
243 CssmKey externalKey
= mKey
;
244 externalKey
.clearAttribute(forcedAttributes
);
245 externalKey
.setAttribute(mAttributes
);
247 // encode the key and replace blob
248 KeyBlob
*newBlob
= database()->encodeKey(externalKey
, pubAcl
, privAcl
);
249 CssmAllocator::standard().free(mBlob
);
254 database()->allocator
.free(pubAcl
);
255 database()->allocator
.free(privAcl
);
262 // Return the UID of a key (the hash of its bits)
267 //@@@ calculate UID here
268 memset(&mUID
, 0, sizeof(mUID
));
276 // Intercept ACL change requests and reset blob validity
278 void Key::instantiateAcl()
283 void Key::changedAcl()
288 const Database
*Key::relatedDatabase() const
289 { return database(); }