]> git.saurik.com Git - apple/security.git/blob - SecurityServer/key.cpp
Security-54.tar.gz
[apple/security.git] / SecurityServer / key.cpp
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
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
8 * using this file.
9 *
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.
16 */
17
18
19 //
20 // key - representation of SecurityServer key objects
21 //
22 #include "key.h"
23 #include "server.h"
24 #include "xdatabase.h"
25 #include <Security/acl_any.h>
26
27
28 //
29 // Create a Key object from a database-encoded blob.
30 // Note that this doesn't decode the blob (yet).
31 //
32 Key::Key(Database &db, const KeyBlob *blob)
33 : SecurityServerAcl(keyAcl, CssmAllocator::standard())
34 {
35 // perform basic validation on the incoming blob
36 assert(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:
41 break;
42 #endif
43 case blob->version_MacOS_10_1:
44 break;
45 default:
46 CssmError::throwMe(CSSMERR_APPLEDL_INCOMPATIBLE_KEY_BLOB);
47 }
48
49 // set it up
50 mDatabase = &db;
51 mBlob = blob->copy(CssmAllocator::standard());
52 mAttributes = 0;
53 mValidBlob = true;
54 mValidKey = false;
55 mValidUID = false;
56 debug("SSkey", "%p created from blob version %lx", this, blob->version);
57 }
58
59
60 //
61 // Create a Key from an explicit CssmKey.
62 //
63 Key::Key(Database *db, const CssmKey &newKey, uint32 moreAttributes,
64 const AclEntryPrototype *owner)
65 : SecurityServerAcl(keyAcl, CssmAllocator::standard())
66 {
67 if (moreAttributes & CSSM_KEYATTR_PERMANENT) {
68 // better have a database to make it permanent in...
69 if (!db)
70 CssmError::throwMe(CSSMERR_CSP_MISSING_ATTR_DL_DB_HANDLE);
71 } else {
72 // non-permanent; ignore database
73 db = NULL;
74 }
75
76 mDatabase = db;
77 mValidKey = true;
78 mBlob = NULL;
79 mValidBlob = false;
80 mValidUID = false;
81 setup(newKey, moreAttributes);
82
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
86 else
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);
90 }
91
92
93 //
94 // Set up the CssmKey part of this Key according to instructions.
95 //
96 void Key::setup(const CssmKey &newKey, uint32 moreAttributes)
97 {
98 CssmKey::Header &header = mKey.header();
99
100 // copy key header
101 header = newKey.header();
102 mAttributes = header.attributes() | moreAttributes;
103
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;
109
110 // verify internal/external attribute separation
111 assert(!(header.attributes() & managedAttributes));
112
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();
115 }
116
117
118 Key::~Key()
119 {
120 CssmAllocator::standard().free(mBlob);
121 if (mValidKey)
122 Server::csp()->freeKey(mKey);
123 debug("SSkey", "%p destroyed", this);
124 }
125
126
127 //
128 // Form a KeySpec with checking and masking
129 //
130 Key::KeySpec::KeySpec(uint32 usage, uint32 attrs)
131 : CssmClient::KeySpec(usage, attrs & ~managedAttributes)
132 {
133 if (attrs & generatedAttributes)
134 CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK);
135 }
136
137 Key::KeySpec::KeySpec(uint32 usage, uint32 attrs, const CssmData &label)
138 : CssmClient::KeySpec(usage, attrs & ~managedAttributes, label)
139 {
140 if (attrs & generatedAttributes)
141 CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK);
142 }
143
144
145 //
146 // Retrieve the actual CssmKey value for the key object.
147 // This will decode its blob if needed (and appropriate).
148 //
149 CssmKey &Key::keyValue()
150 {
151 decode();
152 return mKey;
153 }
154
155
156 //
157 // Ensure that a key is fully decoded.
158 // This makes the mKey key value available for use, as well as its ACL.
159 //
160 void Key::decode()
161 {
162 if (!mValidKey) {
163 assert(mDatabase); // have to have a database (to decode the blob)
164 assert(mValidBlob); // must have a blob to decode
165
166 // decode the key
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);
172
173 // extract managed attribute bits
174 mAttributes = mKey.attributes() & managedAttributes;
175 mKey.clearAttribute(managedAttributes);
176
177 // key is valid now
178 mValidKey = true;
179 }
180 }
181
182
183 //
184 // Retrieve the header (only) of a key.
185 // This is taking the clear header from the blob *without* verifying it.
186 //
187 CssmKey::Header &Key::keyHeader()
188 {
189 if (mValidKey) {
190 return mKey.header();
191 } else {
192 assert(mValidBlob);
193 return mBlob->header;
194 }
195 }
196
197
198 //
199 // Return a key's handle and header in external form
200 //
201 void Key::returnKey(Handle &h, CssmKey::Header &hdr)
202 {
203 // return handle
204 h = handle();
205
206 // return header with external attributes merged
207 hdr = keyHeader();
208 hdr.setAttribute(mAttributes);
209 }
210
211
212 //
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.
216 //
217 KeyBlob *Key::blob()
218 {
219 if (mDatabase == NULL) // can't encode independent keys
220 CssmError::throwMe(CSSMERR_DL_INVALID_DB_HANDLE);
221 if (!mValidBlob) {
222 assert(mValidKey); // must have valid key to encode
223 //@@@ release mBlob memory here
224
225 // export Key ACL to blob form
226 CssmData pubAcl, privAcl;
227 exportBlob(pubAcl, privAcl);
228
229 // assemble external key form
230 CssmKey externalKey = mKey;
231 externalKey.setAttribute(mAttributes);
232
233 // encode the key and replace blob
234 KeyBlob *newBlob = database()->encodeKey(externalKey, pubAcl, privAcl);
235 CssmAllocator::standard().free(mBlob);
236 mBlob = newBlob;
237 mValidBlob = true;
238
239 // clean up and go
240 database()->allocator.free(pubAcl);
241 database()->allocator.free(privAcl);
242 }
243 return mBlob;
244 }
245
246
247 //
248 // Return the UID of a key (the hash of its bits)
249 //
250 KeyUID &Key::uid()
251 {
252 if (!mValidUID) {
253 //@@@ calculate UID here
254 memset(&mUID, 0, sizeof(mUID));
255 mValidUID = true;
256 }
257 return mUID;
258 }
259
260
261 //
262 // Intercept ACL change requests and reset blob validity
263 //
264 void Key::instantiateAcl()
265 {
266 decode();
267 }
268
269 void Key::noticeAclChange()
270 {
271 mValidBlob = false;
272 }
273
274 const Database *Key::relatedDatabase() const
275 { return database(); }