]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 | 1 | /* |
d8f41ccd | 2 | * Copyright (c) 2000-2008,2011-2013 Apple Inc. All Rights Reserved. |
b1ab9ed8 A |
3 | * |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
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 | |
11 | * file. | |
12 | * | |
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. | |
20 | * | |
21 | * @APPLE_LICENSE_HEADER_END@ | |
22 | */ | |
23 | ||
24 | ||
25 | // | |
26 | // transition - SecurityServer client library transition code. | |
27 | // | |
28 | // These are the functions that implement CssmClient methods in terms of | |
29 | // MIG IPC client calls, plus their supporting machinery. | |
30 | // | |
31 | // WARNING! HERE BE DRAGONS! | |
32 | // This code involves moderately arcane magic including (but not limited to) | |
33 | // dancing macros paired off with self-maintaining stack objects. Don't take | |
34 | // anything for granted! Be very afraid of ALL-CAPS names. Your best bet is | |
35 | // probably to stick with the existing patterns. | |
36 | // | |
37 | // Dragons, the sequel. You just don't go killing of that kind of prose, so | |
38 | // we'll continue the saga here with a bit of an update. In transitioning | |
39 | // into securityd there are a couple of steps. The current setup is there | |
40 | // to allow Security.framework to have 32 and 64 bit clients and either | |
41 | // big or little endian. Data is packaged up as hand-generated XDR, which | |
42 | // means it's also in network byte-order. | |
43 | // | |
44 | // CSSM_HANDLEs have remained longs in the 64 bit transition to keep the | |
45 | // optimization option open to allow cssm modules to hand back pointers as | |
46 | // handles. Since we don't identify the client, handles across ipc will | |
47 | // remain 32 bit. Handles you see here are passed out by securityd, and | |
48 | // are clipped and expanded in this layer (high bits always zero). | |
49 | // | |
50 | #include "sstransit.h" | |
51 | #include <security_cdsa_client/cspclient.h> | |
b1ab9ed8 A |
52 | |
53 | #include <securityd_client/xdr_auth.h> | |
54 | #include <securityd_client/xdr_cssm.h> | |
55 | #include <securityd_client/xdr_dldb.h> | |
56 | ||
57 | namespace Security { | |
58 | namespace SecurityServer { | |
59 | ||
60 | using MachPlusPlus::check; | |
61 | using MachPlusPlus::VMGuard; | |
62 | ||
63 | // | |
64 | // Common database interface | |
65 | // | |
66 | void ClientSession::authenticateDb(DbHandle db, CSSM_DB_ACCESS_TYPE type, | |
67 | const AccessCredentials *cred) | |
68 | { | |
69 | // XXX/cs Leave it up to DatabaseAccessCredentials to rewrite it for now | |
70 | DatabaseAccessCredentials creds(cred, internalAllocator); | |
71 | CopyIn copy(creds.value(), reinterpret_cast<xdrproc_t>(xdr_CSSM_ACCESS_CREDENTIALS)); | |
72 | IPC(ucsp_client_authenticateDb(UCSP_ARGS, db, type, copy.data(), copy.length())); | |
73 | } | |
74 | ||
75 | ||
76 | void ClientSession::releaseDb(DbHandle db) | |
77 | { | |
78 | IPC(ucsp_client_releaseDb(UCSP_ARGS, db)); | |
79 | } | |
80 | ||
81 | ||
82 | // | |
83 | // External database interface | |
84 | // | |
85 | DbHandle ClientSession::openToken(uint32 ssid, const AccessCredentials *cred, | |
86 | const char *name) | |
87 | { | |
88 | DbHandle db; | |
89 | DatabaseAccessCredentials creds(cred, internalAllocator); | |
90 | CopyIn copycreds(creds.value(), reinterpret_cast<xdrproc_t>(xdr_CSSM_ACCESS_CREDENTIALS)); | |
91 | ||
92 | IPC(ucsp_client_openToken(UCSP_ARGS, ssid, name ? name : "", copycreds.data(), copycreds.length(), &db)); | |
93 | ||
94 | return db; | |
95 | } | |
96 | ||
97 | ||
98 | RecordHandle ClientSession::insertRecord(DbHandle db, | |
99 | CSSM_DB_RECORDTYPE recordType, | |
100 | const CssmDbRecordAttributeData *attributes, | |
101 | const CssmData *data) | |
102 | { | |
103 | RecordHandle record; | |
104 | CopyIn db_record_attr_data(attributes, reinterpret_cast<xdrproc_t>(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA)); | |
105 | ||
427c49bc | 106 | IPC(ucsp_client_insertRecord(UCSP_ARGS, db, recordType, db_record_attr_data.data(), (mach_msg_type_number_t)db_record_attr_data.length(), OPTIONALDATA(data), &record)); |
b1ab9ed8 A |
107 | |
108 | return record; | |
109 | } | |
110 | ||
111 | ||
112 | void ClientSession::deleteRecord(DbHandle db, RecordHandle record) | |
113 | { | |
114 | IPC(ucsp_client_deleteRecord(UCSP_ARGS, db, record)); | |
115 | } | |
116 | ||
117 | ||
118 | void ClientSession::modifyRecord(DbHandle db, RecordHandle &record, | |
119 | CSSM_DB_RECORDTYPE recordType, | |
120 | const CssmDbRecordAttributeData *attributes, | |
121 | const CssmData *data, | |
122 | CSSM_DB_MODIFY_MODE modifyMode) | |
123 | { | |
124 | CopyIn db_record_attr_data(attributes, reinterpret_cast<xdrproc_t>(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA)); | |
125 | ||
427c49bc | 126 | IPC(ucsp_client_modifyRecord(UCSP_ARGS, db, &record, recordType, db_record_attr_data.data(), (mach_msg_type_number_t)db_record_attr_data.length(), |
b1ab9ed8 A |
127 | data != NULL, OPTIONALDATA(data), modifyMode)); |
128 | } | |
129 | ||
427c49bc | 130 | static |
b1ab9ed8 A |
131 | void copy_back_attribute_return_data(CssmDbRecordAttributeData *dest_attrs, CssmDbRecordAttributeData *source_attrs, Allocator &returnAllocator) |
132 | { | |
133 | assert(dest_attrs->size() == source_attrs->size()); | |
134 | // global (per-record) fields | |
135 | dest_attrs->recordType(source_attrs->recordType()); | |
136 | dest_attrs->semanticInformation(source_attrs->semanticInformation()); | |
137 | ||
138 | // transfer data values (but not infos, which we keep in the original vector) | |
139 | for (uint32 n = 0; n < dest_attrs->size(); n++) | |
140 | dest_attrs->at(n).copyValues(source_attrs->at(n), returnAllocator); | |
141 | } | |
142 | ||
143 | RecordHandle ClientSession::findFirst(DbHandle db, | |
144 | const CssmQuery &inQuery, | |
145 | SearchHandle &hSearch, | |
146 | CssmDbRecordAttributeData *attributes, | |
147 | CssmData *data, KeyHandle &hKey) | |
148 | { | |
149 | CopyIn query(&inQuery, reinterpret_cast<xdrproc_t>(xdr_CSSM_QUERY)); | |
150 | CopyIn in_attr(attributes, reinterpret_cast<xdrproc_t>(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA)); | |
151 | void *out_attr_data = NULL, *out_data = NULL; | |
152 | mach_msg_size_t out_attr_length = 0, out_data_length = 0; | |
153 | RecordHandle ipcHRecord = 0; | |
154 | ||
155 | IPC(ucsp_client_findFirst(UCSP_ARGS, db, | |
156 | query.data(), query.length(), in_attr.data(), in_attr.length(), | |
157 | &out_attr_data, &out_attr_length, (data != NULL), &out_data, &out_data_length, | |
158 | &hKey, &hSearch, &ipcHRecord)); | |
159 | ||
160 | if (ipcHRecord != 0) | |
161 | { | |
162 | CopyOut out_attrs(out_attr_data, out_attr_length, reinterpret_cast<xdrproc_t>(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR), true); | |
163 | copy_back_attribute_return_data(attributes, reinterpret_cast<CssmDbRecordAttributeData*>(out_attrs.data()), returnAllocator); | |
164 | } | |
165 | ||
166 | // decode data from server as cssm_data or cssm_key (get data on keys returns cssm_key in data) | |
167 | CopyOut possible_key_in_data(out_data, out_data_length, reinterpret_cast<xdrproc_t>(xdr_CSSM_POSSIBLY_KEY_IN_DATA_PTR), true, data); | |
168 | ||
169 | return ipcHRecord; | |
170 | } | |
171 | ||
172 | ||
173 | RecordHandle ClientSession::findNext(SearchHandle hSearch, | |
174 | CssmDbRecordAttributeData *attributes, | |
175 | CssmData *data, KeyHandle &hKey) | |
176 | { | |
177 | CopyIn in_attr(attributes, reinterpret_cast<xdrproc_t>(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA)); | |
178 | void *out_attr_data = NULL, *out_data = NULL; | |
179 | mach_msg_size_t out_attr_length = 0, out_data_length = 0; | |
180 | //DataOutput out_data(data, returnAllocator); | |
181 | RecordHandle ipcHRecord = 0; | |
182 | ||
183 | IPC(ucsp_client_findNext(UCSP_ARGS, hSearch, | |
184 | in_attr.data(), in_attr.length(), &out_attr_data, &out_attr_length, | |
185 | (data != NULL), &out_data, &out_data_length, &hKey, &ipcHRecord)); | |
186 | ||
187 | if (ipcHRecord != 0) | |
188 | { | |
189 | CopyOut out_attrs(out_attr_data, out_attr_length, reinterpret_cast<xdrproc_t>(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR), true); | |
190 | copy_back_attribute_return_data(attributes, reinterpret_cast<CssmDbRecordAttributeData*>(out_attrs.data()), returnAllocator); | |
191 | } | |
192 | ||
193 | // decode data from server as cssm_data or cssm_key (get data on keys returns cssm_key in data) | |
194 | CopyOut possible_key_in_data(out_data, out_data_length, reinterpret_cast<xdrproc_t>(xdr_CSSM_POSSIBLY_KEY_IN_DATA_PTR), true, data); | |
195 | ||
196 | return ipcHRecord; | |
197 | } | |
198 | ||
199 | ||
200 | void ClientSession::findRecordHandle(RecordHandle hRecord, | |
201 | CssmDbRecordAttributeData *attributes, | |
202 | CssmData *data, KeyHandle &hKey) | |
203 | { | |
204 | CopyIn in_attr(attributes, reinterpret_cast<xdrproc_t>(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA)); | |
205 | void *out_attr_data = NULL, *out_data = NULL; | |
206 | mach_msg_size_t out_attr_length = 0, out_data_length = 0; | |
207 | IPC(ucsp_client_findRecordHandle(UCSP_ARGS, hRecord, | |
208 | in_attr.data(), in_attr.length(), &out_attr_data, &out_attr_length, | |
209 | data != NULL, &out_data, &out_data_length, &hKey)); | |
210 | ||
211 | if (hRecord != 0) | |
212 | { | |
213 | CopyOut out_attrs(out_attr_data, out_attr_length, reinterpret_cast<xdrproc_t>(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR), true); | |
214 | copy_back_attribute_return_data(attributes, reinterpret_cast<CssmDbRecordAttributeData*>(out_attrs.data()), returnAllocator); | |
215 | } | |
216 | ||
217 | // decode data from server as cssm_data or cssm_key (get data on keys returns cssm_key in data) | |
218 | CopyOut possible_key_in_data(out_data, out_data_length, reinterpret_cast<xdrproc_t>(xdr_CSSM_POSSIBLY_KEY_IN_DATA_PTR), true, data); | |
219 | } | |
220 | ||
221 | ||
222 | void ClientSession::releaseSearch(SearchHandle searchHandle) | |
223 | { | |
224 | IPC(ucsp_client_releaseSearch(UCSP_ARGS, searchHandle)); | |
225 | } | |
226 | ||
227 | ||
228 | void ClientSession::releaseRecord(RecordHandle record) | |
229 | { | |
230 | IPC(ucsp_client_releaseRecord(UCSP_ARGS, record)); | |
231 | } | |
232 | ||
233 | void ClientSession::getDbName(DbHandle db, string &name) | |
234 | { | |
235 | char result[PATH_MAX]; | |
236 | ||
237 | IPC(ucsp_client_getDbName(UCSP_ARGS, db, result)); | |
238 | ||
239 | name = result; | |
240 | } | |
241 | ||
242 | void ClientSession::setDbName(DbHandle db, const string &name) | |
243 | { | |
244 | IPC(ucsp_client_setDbName(UCSP_ARGS, db, name.c_str())); | |
245 | } | |
246 | ||
247 | ||
248 | // | |
249 | // Internal database management | |
250 | // | |
251 | DbHandle ClientSession::createDb(const DLDbIdentifier &dbId, | |
252 | const AccessCredentials *cred, const AclEntryInput *owner, | |
253 | const DBParameters ¶ms) | |
254 | { | |
255 | DatabaseAccessCredentials creds(cred, internalAllocator); | |
256 | CopyIn copycreds(creds.value(), reinterpret_cast<xdrproc_t>(xdr_CSSM_ACCESS_CREDENTIALS)); | |
257 | CopyIn proto(owner ? &owner->proto() : NULL, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACL_ENTRY_PROTOTYPE)); | |
258 | // XXX/64 make xdr routines translate directly between dldbident and flat rep | |
259 | DataWalkers::DLDbFlatIdentifier ident(dbId); | |
260 | CopyIn id(&ident, reinterpret_cast<xdrproc_t>(xdr_DLDbFlatIdentifier)); | |
261 | DbHandle db; | |
262 | ||
263 | IPC(ucsp_client_createDb(UCSP_ARGS, &db, id.data(), id.length(), copycreds.data(), copycreds.length(), proto.data(), proto.length(), params)); | |
264 | ||
265 | return db; | |
266 | } | |
267 | ||
268 | DbHandle ClientSession::recodeDbForSync(DbHandle dbToClone, | |
269 | DbHandle srcDb) | |
270 | { | |
271 | DbHandle newDb; | |
272 | ||
273 | IPC(ucsp_client_recodeDbForSync(UCSP_ARGS, dbToClone, srcDb, &newDb)); | |
274 | ||
275 | return newDb; | |
276 | } | |
277 | ||
278 | DbHandle ClientSession::authenticateDbsForSync(const CssmData &dbHandleArray, | |
279 | const CssmData &agentData) | |
280 | { | |
281 | DbHandle newDb; | |
282 | ||
283 | IPC(ucsp_client_authenticateDbsForSync(UCSP_ARGS, DATA(dbHandleArray), DATA(agentData), &newDb)); | |
284 | ||
285 | return newDb; | |
286 | } | |
287 | ||
288 | void ClientSession::commitDbForSync(DbHandle srcDb, DbHandle cloneDb, | |
289 | CssmData &blob, Allocator &alloc) | |
290 | { | |
291 | DataOutput outBlob(blob, alloc); | |
427c49bc | 292 | IPC(ucsp_client_commitDbForSync(UCSP_ARGS, srcDb, cloneDb, DATA_OUT(outBlob))); |
b1ab9ed8 A |
293 | } |
294 | ||
295 | DbHandle ClientSession::decodeDb(const DLDbIdentifier &dbId, | |
296 | const AccessCredentials *cred, const CssmData &blob) | |
297 | { | |
298 | // XXX/64 fold into one translation | |
299 | DatabaseAccessCredentials credentials(cred, internalAllocator); | |
300 | CopyIn creds(credentials.value(), reinterpret_cast<xdrproc_t>(xdr_CSSM_ACCESS_CREDENTIALS)); | |
301 | // XXX/64 fold into one translation | |
302 | DataWalkers::DLDbFlatIdentifier ident(dbId); | |
303 | CopyIn id(&ident, reinterpret_cast<xdrproc_t>(xdr_DLDbFlatIdentifier)); | |
304 | DbHandle db; | |
305 | ||
306 | IPC(ucsp_client_decodeDb(UCSP_ARGS, &db, id.data(), id.length(), creds.data(), creds.length(), DATA(blob))); | |
307 | ||
308 | return db; | |
309 | } | |
310 | ||
311 | void ClientSession::encodeDb(DbHandle db, CssmData &blob, Allocator &alloc) | |
312 | { | |
313 | DataOutput outBlob(blob, alloc); | |
427c49bc | 314 | IPC(ucsp_client_encodeDb(UCSP_ARGS, db, DATA_OUT(outBlob))); |
b1ab9ed8 A |
315 | } |
316 | ||
317 | void ClientSession::setDbParameters(DbHandle db, const DBParameters ¶ms) | |
318 | { | |
319 | IPC(ucsp_client_setDbParameters(UCSP_ARGS, db, params)); | |
320 | } | |
321 | ||
322 | void ClientSession::getDbParameters(DbHandle db, DBParameters ¶ms) | |
323 | { | |
324 | IPC(ucsp_client_getDbParameters(UCSP_ARGS, db, ¶ms)); | |
325 | } | |
326 | ||
327 | void ClientSession::changePassphrase(DbHandle db, const AccessCredentials *cred) | |
328 | { | |
329 | CopyIn creds(cred, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACCESS_CREDENTIALS)); | |
330 | IPC(ucsp_client_changePassphrase(UCSP_ARGS, db, creds.data(), creds.length())); | |
331 | } | |
332 | ||
333 | ||
334 | void ClientSession::lock(DbHandle db) | |
335 | { | |
336 | IPC(ucsp_client_authenticateDb(UCSP_ARGS, db, CSSM_DB_ACCESS_RESET, NULL, 0)); | |
337 | //@@@VIRTUAL IPC(ucsp_client_lockDb(UCSP_ARGS, db)); | |
338 | } | |
339 | ||
340 | void ClientSession::lockAll (bool forSleep) | |
341 | { | |
342 | IPC(ucsp_client_lockAll (UCSP_ARGS, forSleep)); | |
343 | } | |
344 | ||
345 | void ClientSession::unlock(DbHandle db) | |
346 | { | |
347 | IPC(ucsp_client_unlockDb(UCSP_ARGS, db)); | |
348 | } | |
349 | ||
350 | void ClientSession::unlock(DbHandle db, const CssmData &passphrase) | |
351 | { | |
352 | IPC(ucsp_client_unlockDbWithPassphrase(UCSP_ARGS, db, DATA(passphrase))); | |
353 | } | |
354 | ||
427c49bc A |
355 | void ClientSession::stashDb(DbHandle db) |
356 | { | |
357 | IPC(ucsp_client_stashDb(UCSP_ARGS, db)); | |
358 | } | |
359 | ||
360 | void ClientSession::stashDbCheck(DbHandle db) | |
361 | { | |
362 | IPC(ucsp_client_stashDbCheck(UCSP_ARGS, db)); | |
363 | } | |
364 | ||
b1ab9ed8 A |
365 | bool ClientSession::isLocked(DbHandle db) |
366 | { | |
367 | boolean_t locked; | |
368 | IPC(ucsp_client_isLocked(UCSP_ARGS, db, &locked)); | |
369 | return locked; | |
370 | } | |
371 | ||
427c49bc A |
372 | void ClientSession::verifyKeyStorePassphrase(uint32_t retries) |
373 | { | |
374 | IPC(ucsp_client_verifyKeyStorePassphrase(UCSP_ARGS, retries)); | |
375 | } | |
376 | ||
377 | void ClientSession::resetKeyStorePassphrase(const CssmData &passphrase) | |
378 | { | |
379 | IPC(ucsp_client_resetKeyStorePassphrase(UCSP_ARGS, DATA(passphrase))); | |
380 | } | |
381 | ||
382 | void ClientSession::changeKeyStorePassphrase() | |
383 | { | |
384 | IPC(ucsp_client_changeKeyStorePassphrase(UCSP_ARGS)); | |
385 | } | |
b1ab9ed8 A |
386 | |
387 | // | |
388 | // Key control | |
389 | // | |
390 | void ClientSession::encodeKey(KeyHandle key, CssmData &blob, | |
391 | KeyUID *uid, Allocator &alloc) | |
392 | { | |
393 | // Not really used as output | |
394 | DataOutput oBlob(blob, alloc); | |
395 | void *uidp; | |
396 | mach_msg_type_number_t uidLength; | |
397 | ||
398 | IPC(ucsp_client_encodeKey(UCSP_ARGS, key, oBlob.data(), oBlob.length(), | |
399 | (uid != NULL), &uidp, &uidLength)); | |
400 | ||
401 | // return key uid if requested | |
402 | if (uid) { | |
403 | assert(uidLength == sizeof(KeyUID)); | |
404 | memcpy(uid, uidp, sizeof(KeyUID)); | |
405 | } | |
406 | } | |
407 | ||
408 | KeyHandle ClientSession::decodeKey(DbHandle db, const CssmData &blob, CssmKey::Header &header) | |
409 | { | |
410 | KeyHandle key; | |
411 | void *keyHeaderData; | |
412 | mach_msg_type_number_t keyHeaderDataLength; | |
413 | ||
427c49bc | 414 | IPC(ucsp_client_decodeKey(UCSP_ARGS, &key, &keyHeaderData, &keyHeaderDataLength, db, blob.data(), (mach_msg_type_number_t)blob.length())); |
b1ab9ed8 A |
415 | |
416 | CopyOut wrappedKeyHeaderXDR(keyHeaderData, keyHeaderDataLength + sizeof(CSSM_KEYHEADER), reinterpret_cast<xdrproc_t>(xdr_CSSM_KEYHEADER_PTR), true); | |
417 | header = *static_cast<CssmKey::Header *>(reinterpret_cast<CSSM_KEYHEADER*>(wrappedKeyHeaderXDR.data())); | |
418 | ||
419 | return key; | |
420 | } | |
421 | ||
422 | // keychain synchronization | |
423 | void ClientSession::recodeKey(DbHandle oldDb, KeyHandle key, DbHandle newDb, | |
424 | CssmData &blob) | |
425 | { | |
426 | DataOutput outBlob(blob, returnAllocator); | |
427c49bc | 427 | IPC(ucsp_client_recodeKey(UCSP_ARGS, oldDb, key, newDb, DATA_OUT(outBlob))); |
b1ab9ed8 A |
428 | } |
429 | ||
430 | void ClientSession::releaseKey(KeyHandle key) | |
431 | { | |
432 | IPC(ucsp_client_releaseKey(UCSP_ARGS, key)); | |
433 | } | |
434 | ||
435 | ||
436 | CssmKeySize ClientSession::queryKeySizeInBits(KeyHandle key) | |
437 | { | |
438 | CssmKeySize length; | |
439 | IPC(ucsp_client_queryKeySizeInBits(UCSP_ARGS, key, &length)); | |
440 | return length; | |
441 | } | |
442 | ||
443 | ||
444 | uint32 ClientSession::getOutputSize(const Context &context, KeyHandle key, | |
445 | uint32 inputSize, bool encrypt) | |
446 | { | |
447 | CopyIn ctxcopy(&context, reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT)); | |
448 | uint32 outputSize; | |
449 | ||
450 | IPC(ucsp_client_getOutputSize(UCSP_ARGS, ctxcopy.data(), ctxcopy.length(), key, inputSize, encrypt, &outputSize)); | |
451 | return outputSize; | |
452 | } | |
453 | ||
454 | ||
455 | // | |
456 | // Random number generation. | |
457 | // This interfaces to the secure RNG inside the SecurityServer; it does not access | |
458 | // a PRNG in its CSP. If you need a reproducible PRNG, attach a local CSP and use it. | |
459 | // Note that this function does not allocate a buffer; it always fills the buffer provided. | |
460 | // | |
461 | void ClientSession::generateRandom(const Security::Context &context, CssmData &data, Allocator &alloc) | |
462 | { | |
463 | CopyIn ctxcopy(&context, reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT)); | |
464 | DataOutput result(data, alloc); | |
465 | ||
427c49bc | 466 | IPC(ucsp_client_generateRandom(UCSP_ARGS, 0, ctxcopy.data(), ctxcopy.length(), DATA_OUT(result))); |
b1ab9ed8 A |
467 | } |
468 | ||
469 | ||
470 | // | |
471 | // Signatures and MACs | |
472 | // | |
473 | void ClientSession::generateSignature(const Context &context, KeyHandle key, | |
474 | const CssmData &data, CssmData &signature, Allocator &alloc, CSSM_ALGORITHMS signOnlyAlgorithm) | |
475 | { | |
476 | CopyIn ctxcopy(&context, reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT)); | |
477 | DataOutput sig(signature, alloc); | |
478 | ||
479 | IPCKEY(ucsp_client_generateSignature(UCSP_ARGS, ctxcopy.data(), ctxcopy.length(), key, signOnlyAlgorithm, | |
427c49bc | 480 | DATA(data), DATA_OUT(sig)), |
b1ab9ed8 A |
481 | key, CSSM_ACL_AUTHORIZATION_SIGN); |
482 | } | |
483 | ||
484 | void ClientSession::verifySignature(const Context &context, KeyHandle key, | |
485 | const CssmData &data, const CssmData &signature, CSSM_ALGORITHMS verifyOnlyAlgorithm) | |
486 | { | |
487 | CopyIn ctxcopy(&context, reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT)); | |
488 | ||
489 | IPC(ucsp_client_verifySignature(UCSP_ARGS, ctxcopy.data(), ctxcopy.length(), key, verifyOnlyAlgorithm, DATA(data), DATA(signature))); | |
490 | } | |
491 | ||
492 | ||
493 | void ClientSession::generateMac(const Context &context, KeyHandle key, | |
494 | const CssmData &data, CssmData &signature, Allocator &alloc) | |
495 | { | |
496 | CopyIn ctxcopy(&context, reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT)); | |
497 | DataOutput sig(signature, alloc); | |
498 | ||
427c49bc | 499 | IPCKEY(ucsp_client_generateMac(UCSP_ARGS, ctxcopy.data(), ctxcopy.length(), key, DATA(data), DATA_OUT(sig)), |
b1ab9ed8 A |
500 | key, CSSM_ACL_AUTHORIZATION_MAC); |
501 | } | |
502 | ||
503 | void ClientSession::verifyMac(const Context &context, KeyHandle key, | |
504 | const CssmData &data, const CssmData &signature) | |
505 | { | |
506 | CopyIn ctxcopy(&context, reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT)); | |
507 | ||
508 | IPCKEY(ucsp_client_verifyMac(UCSP_ARGS, ctxcopy.data(), ctxcopy.length(), key, | |
509 | DATA(data), DATA(signature)), | |
510 | key, CSSM_ACL_AUTHORIZATION_MAC); | |
511 | } | |
512 | ||
513 | ||
514 | // | |
515 | // Encryption/Decryption | |
516 | // | |
517 | ||
518 | void ClientSession::encrypt(const Context &context, KeyHandle key, | |
519 | const CssmData &clear, CssmData &cipher, Allocator &alloc) | |
520 | { | |
521 | CopyIn ctxcopy(&context, reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT)); | |
522 | DataOutput cipherOut(cipher, alloc); | |
427c49bc | 523 | IPCKEY(ucsp_client_encrypt(UCSP_ARGS, ctxcopy.data(), ctxcopy.length(), key, DATA(clear), DATA_OUT(cipherOut)), |
b1ab9ed8 A |
524 | key, CSSM_ACL_AUTHORIZATION_ENCRYPT); |
525 | } | |
526 | ||
527 | void ClientSession::decrypt(const Context &context, KeyHandle key, | |
528 | const CssmData &cipher, CssmData &clear, Allocator &alloc) | |
529 | { | |
530 | CopyIn ctxcopy(&context, reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT)); | |
531 | DataOutput clearOut(clear, alloc); | |
532 | ||
427c49bc | 533 | IPCKEY(ucsp_client_decrypt(UCSP_ARGS, ctxcopy.data(), ctxcopy.length(), key, DATA(cipher), DATA_OUT(clearOut)), |
b1ab9ed8 A |
534 | key, CSSM_ACL_AUTHORIZATION_DECRYPT); |
535 | } | |
536 | ||
537 | ||
538 | // | |
539 | // Key generation | |
540 | // | |
541 | void ClientSession::generateKey(DbHandle db, const Context &context, uint32 keyUsage, uint32 keyAttr, | |
542 | const AccessCredentials *cred, const AclEntryInput *owner, | |
543 | KeyHandle &newKey, CssmKey::Header &newHeader) | |
544 | { | |
545 | CopyIn ctxcopy(&context, reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT)); | |
546 | CopyIn creds(cred, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACCESS_CREDENTIALS)); | |
547 | CopyIn proto(owner ? &owner->proto() : NULL, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACL_ENTRY_PROTOTYPE)); | |
548 | void *keyHeaderData; | |
549 | mach_msg_type_number_t keyHeaderDataLength; | |
550 | ||
551 | IPC(ucsp_client_generateKey(UCSP_ARGS, db, ctxcopy.data(), ctxcopy.length(), | |
552 | creds.data(), creds.length(), proto.data(), proto.length(), | |
553 | keyUsage, keyAttr, &newKey, &keyHeaderData, &keyHeaderDataLength)); | |
554 | ||
555 | CopyOut wrappedKeyHeaderXDR(keyHeaderData, keyHeaderDataLength + sizeof(CSSM_KEYHEADER), reinterpret_cast<xdrproc_t>(xdr_CSSM_KEYHEADER_PTR), true); | |
556 | newHeader = *static_cast<CssmKey::Header *>(reinterpret_cast<CSSM_KEYHEADER*>(wrappedKeyHeaderXDR.data())); | |
557 | } | |
558 | ||
559 | void ClientSession::generateKey(DbHandle db, const Context &context, | |
560 | uint32 pubKeyUsage, uint32 pubKeyAttr, | |
561 | uint32 privKeyUsage, uint32 privKeyAttr, | |
562 | const AccessCredentials *cred, const AclEntryInput *owner, | |
563 | KeyHandle &pubKey, CssmKey::Header &pubHeader, | |
564 | KeyHandle &privKey, CssmKey::Header &privHeader) | |
565 | { | |
566 | CopyIn ctxcopy(&context, reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT)); | |
567 | CopyIn creds(cred, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACCESS_CREDENTIALS)); | |
568 | CopyIn proto(owner ? &owner->proto() : NULL, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACL_ENTRY_PROTOTYPE)); | |
569 | void *pubKeyHeaderData, *privKeyHeaderData; | |
570 | mach_msg_type_number_t pubKeyHeaderDataLength, privKeyHeaderDataLength; | |
571 | ||
572 | IPC(ucsp_client_generateKeyPair(UCSP_ARGS, db, ctxcopy.data(), ctxcopy.length(), | |
573 | creds.data(), creds.length(), proto.data(), proto.length(), | |
574 | pubKeyUsage, pubKeyAttr, privKeyUsage, privKeyAttr, | |
575 | &pubKey, &pubKeyHeaderData, &pubKeyHeaderDataLength, | |
576 | &privKey, &privKeyHeaderData, &privKeyHeaderDataLength)); | |
577 | ||
578 | CopyOut wrappedPubKeyHeaderXDR(pubKeyHeaderData, pubKeyHeaderDataLength + sizeof(CSSM_KEYHEADER), reinterpret_cast<xdrproc_t>(xdr_CSSM_KEYHEADER_PTR), true); | |
579 | pubHeader = *static_cast<CssmKey::Header *>(reinterpret_cast<CSSM_KEYHEADER*>(wrappedPubKeyHeaderXDR.data())); | |
580 | CopyOut wrappedPrivKeyHeaderXDR(privKeyHeaderData, privKeyHeaderDataLength + sizeof(CSSM_KEYHEADER), reinterpret_cast<xdrproc_t>(xdr_CSSM_KEYHEADER_PTR), true); | |
581 | privHeader = *static_cast<CssmKey::Header *>(reinterpret_cast<CSSM_KEYHEADER*>(wrappedPrivKeyHeaderXDR.data())); | |
582 | ||
583 | } | |
584 | ||
585 | ||
586 | // | |
587 | // Key derivation | |
588 | // This is a bit strained; the incoming 'param' value may have structure, | |
589 | // and we use a synthetic CssmDeriveData structure (with ad-hoc walker) to | |
590 | // handle that. Param also is input/output, which is always a pain (not to mention | |
591 | // ill-defined by the CDSA standard). | |
592 | // | |
593 | // If you're here because an algorithm of yours requires structured parameter | |
594 | // input, go to security_cdsa_utilities/cssmwalkers.h and add a case to the | |
595 | // CssmDeriveData walker. | |
596 | // | |
597 | void ClientSession::deriveKey(DbHandle db, const Context &context, KeyHandle baseKey, | |
598 | CSSM_KEYUSE usage, CSSM_KEYATTR_FLAGS attrs, CssmData ¶m, | |
599 | const AccessCredentials *cred, const AclEntryInput *owner, | |
600 | KeyHandle &newKey, CssmKey::Header &newHeader, Allocator &allocator) | |
601 | { | |
602 | CopyIn ctxcopy(&context, reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT)); | |
603 | CopyIn creds(cred, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACCESS_CREDENTIALS)); | |
604 | CopyIn proto(owner ? &owner->proto() : NULL, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACL_ENTRY_PROTOTYPE)); | |
605 | CSSM_DERIVE_DATA inParamForm = { context.algorithm(), param }; | |
606 | CopyIn inParam(&inParamForm, reinterpret_cast<xdrproc_t>(xdr_CSSM_DERIVE_DATA)); | |
607 | ||
608 | try | |
609 | { | |
610 | DataOutput paramOutput(param, allocator); | |
611 | void *keyHeaderData; | |
612 | mach_msg_type_number_t keyHeaderDataLength; | |
613 | ||
614 | IPCKEY(ucsp_client_deriveKey(UCSP_ARGS, db, ctxcopy.data(), ctxcopy.length(), baseKey, | |
615 | creds.data(), creds.length(), proto.data(), proto.length(), | |
427c49bc | 616 | inParam.data(), inParam.length(), DATA_OUT(paramOutput), |
b1ab9ed8 A |
617 | usage, attrs, &newKey, &keyHeaderData, &keyHeaderDataLength), |
618 | baseKey, CSSM_ACL_AUTHORIZATION_DERIVE); | |
619 | ||
620 | CopyOut wrappedKeyHeaderXDR(keyHeaderData, keyHeaderDataLength + sizeof(CSSM_KEYHEADER), reinterpret_cast<xdrproc_t>(xdr_CSSM_KEYHEADER_PTR), true); | |
621 | newHeader = *static_cast<CssmKey::Header *>(reinterpret_cast<CSSM_KEYHEADER*>(wrappedKeyHeaderXDR.data())); | |
622 | } | |
623 | catch (CssmError& e) | |
624 | { | |
625 | // filter out errors for CSSM_ALGID_PKCS5_PBKDF2 | |
626 | if (context.algorithm() != CSSM_ALGID_PKCS5_PBKDF2 && e.error != CSSMERR_CSP_OUTPUT_LENGTH_ERROR) | |
627 | { | |
628 | throw; | |
629 | } | |
630 | } | |
631 | } | |
632 | ||
633 | ||
634 | // | |
635 | // Digest generation | |
636 | // | |
637 | void ClientSession::getKeyDigest(KeyHandle key, CssmData &digest, Allocator &allocator) | |
638 | { | |
639 | DataOutput dig(digest, allocator); | |
427c49bc | 640 | IPC(ucsp_client_getKeyDigest(UCSP_ARGS, key, DATA_OUT(dig))); |
b1ab9ed8 A |
641 | } |
642 | ||
643 | ||
644 | // | |
645 | // Key wrapping and unwrapping | |
646 | // | |
647 | void ClientSession::wrapKey(const Context &context, KeyHandle wrappingKey, | |
648 | KeyHandle keyToBeWrapped, const AccessCredentials *cred, | |
649 | const CssmData *descriptiveData, CssmWrappedKey &wrappedKey, Allocator &alloc) | |
650 | { | |
651 | CopyIn ctxcopy(&context, reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT)); | |
652 | CopyIn creds(cred, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACCESS_CREDENTIALS)); | |
653 | void *keyData; | |
654 | mach_msg_type_number_t keyDataLength; | |
655 | ||
656 | IPCKEY(ucsp_client_wrapKey(UCSP_ARGS, ctxcopy.data(), ctxcopy.length(), wrappingKey, | |
657 | creds.data(), creds.length(), | |
658 | keyToBeWrapped, OPTIONALDATA(descriptiveData), | |
659 | &keyData, &keyDataLength), | |
660 | keyToBeWrapped, | |
661 | context.algorithm() == CSSM_ALGID_NONE | |
662 | ? CSSM_ACL_AUTHORIZATION_EXPORT_CLEAR : CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED); | |
663 | ||
664 | CopyOut wrappedKeyXDR(keyData, keyDataLength + sizeof(CSSM_KEY), reinterpret_cast<xdrproc_t>(xdr_CSSM_KEY_PTR), true); | |
665 | CssmWrappedKey *wrappedKeyIPC = reinterpret_cast<CssmWrappedKey*>(wrappedKeyXDR.data()); | |
666 | wrappedKey.header() = wrappedKeyIPC->header(); | |
667 | wrappedKey.keyData() = CssmData(alloc.malloc(wrappedKeyIPC->keyData().length()), wrappedKeyIPC->keyData().length()); | |
668 | memcpy(wrappedKey.keyData().data(), wrappedKeyIPC->keyData(), wrappedKeyIPC->keyData().length()); | |
669 | } | |
670 | ||
671 | void ClientSession::unwrapKey(DbHandle db, const Context &context, KeyHandle key, | |
672 | KeyHandle publicKey, const CssmWrappedKey &wrappedKey, | |
673 | uint32 usage, uint32 attr, | |
674 | const AccessCredentials *cred, const AclEntryInput *acl, | |
675 | CssmData &descriptiveData, | |
676 | KeyHandle &newKey, CssmKey::Header &newHeader, Allocator &alloc) | |
677 | { | |
678 | CopyIn ctxcopy(&context, reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT)); | |
679 | DataOutput descriptor(descriptiveData, alloc); | |
680 | CopyIn creds(cred, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACCESS_CREDENTIALS)); | |
681 | CopyIn proto(acl ? &acl->proto() : NULL, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACL_ENTRY_PROTOTYPE)); | |
682 | CopyIn wrappedKeyXDR(&wrappedKey, reinterpret_cast<xdrproc_t>(xdr_CSSM_KEY)); | |
683 | void *keyHeaderData; | |
684 | mach_msg_type_number_t keyHeaderDataLength; | |
685 | ||
686 | IPCKEY(ucsp_client_unwrapKey(UCSP_ARGS, db, ctxcopy.data(), ctxcopy.length(), key, | |
687 | creds.data(), creds.length(), proto.data(), proto.length(), | |
427c49bc | 688 | publicKey, wrappedKeyXDR.data(), wrappedKeyXDR.length(), usage, attr, DATA_OUT(descriptor), |
b1ab9ed8 A |
689 | &newKey, &keyHeaderData, &keyHeaderDataLength), |
690 | key, CSSM_ACL_AUTHORIZATION_DECRYPT); | |
691 | ||
692 | CopyOut wrappedKeyHeaderXDR(keyHeaderData, keyHeaderDataLength + sizeof(CSSM_KEYHEADER), reinterpret_cast<xdrproc_t>(xdr_CSSM_KEYHEADER_PTR), true); | |
693 | newHeader = *static_cast<CssmKey::Header *>(reinterpret_cast<CSSM_KEYHEADER*>(wrappedKeyHeaderXDR.data())); | |
694 | } | |
695 | ||
696 | ||
697 | // | |
698 | // ACL management | |
699 | // | |
700 | void ClientSession::getAcl(AclKind kind, GenericHandle key, const char *tag, | |
701 | uint32 &infoCount, AclEntryInfo * &infoArray, Allocator &alloc) | |
702 | { | |
703 | uint32 count; | |
704 | void* info; mach_msg_type_number_t infoLength; | |
705 | IPC(ucsp_client_getAcl(UCSP_ARGS, kind, key, | |
706 | (tag != NULL), tag ? tag : "", | |
707 | &count, &info, &infoLength)); | |
708 | ||
709 | CSSM_ACL_ENTRY_INFO_ARRAY_PTR aclsArray; | |
710 | if (!::copyout_chunked(info, infoLength, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACL_ENTRY_INFO_ARRAY_PTR), reinterpret_cast<void**>(&aclsArray))) | |
711 | CssmError::throwMe(CSSM_ERRCODE_MEMORY_ERROR); | |
712 | ||
713 | infoCount = aclsArray->count; | |
714 | infoArray = reinterpret_cast<AclEntryInfo*>(aclsArray->acls); | |
715 | free(aclsArray); | |
716 | } | |
717 | ||
718 | void ClientSession::changeAcl(AclKind kind, GenericHandle key, const AccessCredentials &cred, | |
719 | const AclEdit &edit) | |
720 | { | |
721 | CopyIn creds(&cred, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACCESS_CREDENTIALS)); | |
722 | //@@@ ignoring callback | |
723 | CopyIn newEntry(edit.newEntry(), reinterpret_cast<xdrproc_t>(xdr_CSSM_ACL_ENTRY_INPUT)); | |
724 | ||
725 | IPCKEY(ucsp_client_changeAcl(UCSP_ARGS, kind, key, creds.data(), creds.length(), | |
726 | edit.mode(), toIPCHandle(edit.handle()), newEntry.data(), newEntry.length()), | |
727 | key, CSSM_ACL_AUTHORIZATION_CHANGE_ACL); | |
728 | } | |
729 | ||
730 | void ClientSession::getOwner(AclKind kind, GenericHandle key, AclOwnerPrototype &owner, | |
731 | Allocator &alloc) | |
732 | { | |
733 | void* proto; mach_msg_type_number_t protoLength; | |
734 | IPC(ucsp_client_getOwner(UCSP_ARGS, kind, key, &proto, &protoLength)); | |
735 | ||
736 | CSSM_ACL_OWNER_PROTOTYPE_PTR tmpOwner; | |
737 | if (!::copyout_chunked(proto, protoLength, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACL_OWNER_PROTOTYPE_PTR), reinterpret_cast<void **>(&tmpOwner))) | |
738 | CssmError::throwMe(CSSM_ERRCODE_MEMORY_ERROR); | |
739 | owner = *static_cast<AclOwnerPrototypePtr>(tmpOwner); | |
740 | free(tmpOwner); | |
741 | } | |
742 | ||
743 | void ClientSession::changeOwner(AclKind kind, GenericHandle key, | |
744 | const AccessCredentials &cred, const AclOwnerPrototype &proto) | |
745 | { | |
746 | CopyIn creds(&cred, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACCESS_CREDENTIALS)); | |
747 | CopyIn protos(&proto, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACL_OWNER_PROTOTYPE)); | |
748 | IPCKEY(ucsp_client_setOwner(UCSP_ARGS, kind, key, creds.data(), creds.length(), protos.data(), protos.length()), | |
749 | key, CSSM_ACL_AUTHORIZATION_CHANGE_OWNER); | |
750 | } | |
751 | ||
752 | ||
753 | void ClientSession::getKeyAcl(DbHandle db, const char *tag, | |
754 | uint32 &count, AclEntryInfo * &info, Allocator &alloc) | |
755 | { getAcl(keyAcl, db, tag, count, info, alloc); } | |
756 | ||
757 | void ClientSession::changeKeyAcl(DbHandle db, const AccessCredentials &cred, | |
758 | const AclEdit &edit) | |
759 | { changeAcl(keyAcl, db, cred, edit); } | |
760 | ||
761 | void ClientSession::getKeyOwner(DbHandle db, AclOwnerPrototype &owner, Allocator &alloc) | |
762 | { getOwner(keyAcl, db, owner, alloc); } | |
763 | ||
764 | void ClientSession::changeKeyOwner(DbHandle db, const AccessCredentials &cred, | |
765 | const AclOwnerPrototype &edit) | |
766 | { changeOwner(keyAcl, db, cred, edit); } | |
767 | ||
768 | void ClientSession::getDbAcl(DbHandle db, const char *tag, | |
769 | uint32 &count, AclEntryInfo * &info, Allocator &alloc) | |
770 | { getAcl(dbAcl, db, tag, count, info, alloc); } | |
771 | ||
772 | void ClientSession::changeDbAcl(DbHandle db, const AccessCredentials &cred, | |
773 | const AclEdit &edit) | |
774 | { changeAcl(dbAcl, db, cred, edit); } | |
775 | ||
776 | void ClientSession::getDbOwner(DbHandle db, AclOwnerPrototype &owner, Allocator &alloc) | |
777 | { getOwner(dbAcl, db, owner, alloc); } | |
778 | ||
779 | void ClientSession::changeDbOwner(DbHandle db, const AccessCredentials &cred, | |
780 | const AclOwnerPrototype &edit) | |
781 | { changeOwner(dbAcl, db, cred, edit); } | |
782 | ||
783 | ||
784 | // | |
785 | // Database key management | |
786 | // | |
787 | void ClientSession::extractMasterKey(DbHandle db, const Context &context, DbHandle sourceDb, | |
788 | uint32 keyUsage, uint32 keyAttr, | |
789 | const AccessCredentials *cred, const AclEntryInput *owner, | |
790 | KeyHandle &newKey, CssmKey::Header &newHeader, Allocator &alloc) | |
791 | { | |
792 | CopyIn ctxcopy(&context, reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT)); | |
793 | CopyIn creds(cred, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACCESS_CREDENTIALS)); | |
794 | CopyIn proto(owner ? &owner->proto() : NULL, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACL_ENTRY_PROTOTYPE)); | |
795 | void *keyHeaderData; | |
796 | mach_msg_type_number_t keyHeaderDataLength; | |
797 | ||
798 | IPC(ucsp_client_extractMasterKey(UCSP_ARGS, db, ctxcopy.data(), ctxcopy.length(), sourceDb, | |
799 | creds.data(), creds.length(), proto.data(), proto.length(), | |
800 | keyUsage, keyAttr, &newKey, &keyHeaderData, &keyHeaderDataLength)); | |
801 | ||
802 | CopyOut wrappedKeyHeaderXDR(keyHeaderData, keyHeaderDataLength + sizeof(CSSM_KEYHEADER), reinterpret_cast<xdrproc_t>(xdr_CSSM_KEYHEADER_PTR), true); | |
803 | newHeader = *static_cast<CssmKey::Header *>(reinterpret_cast<CSSM_KEYHEADER*>(wrappedKeyHeaderXDR.data())); | |
804 | } | |
805 | ||
806 | ||
807 | // | |
808 | // Authorization subsystem entry | |
809 | // | |
810 | void ClientSession::authCreate(const AuthorizationItemSet *rights, | |
811 | const AuthorizationItemSet *environment, AuthorizationFlags flags, | |
812 | AuthorizationBlob &result) | |
813 | { | |
814 | void *rightSet = NULL; mach_msg_size_t rightSet_size = 0; | |
815 | void *environ = NULL; mach_msg_size_t environ_size = 0; | |
816 | ||
817 | if ((rights && | |
818 | !copyin_AuthorizationItemSet(rights, &rightSet, &rightSet_size)) || | |
819 | (environment && | |
820 | !copyin_AuthorizationItemSet(environment, &environ, &environ_size))) | |
821 | CssmError::throwMe(errAuthorizationInternal); | |
822 | ||
823 | activate(); | |
824 | IPCSTART(ucsp_client_authorizationCreate(UCSP_ARGS, | |
825 | rightSet, rightSet_size, | |
826 | flags, | |
827 | environ, environ_size, | |
828 | &result)); | |
829 | ||
830 | free(rightSet); | |
831 | free(environ); | |
832 | ||
833 | if (rcode == CSSMERR_CSSM_NO_USER_INTERACTION) | |
834 | CssmError::throwMe(errAuthorizationInteractionNotAllowed); | |
835 | IPCEND_CHECK; | |
836 | } | |
837 | ||
838 | void ClientSession::authRelease(const AuthorizationBlob &auth, | |
839 | AuthorizationFlags flags) | |
840 | { | |
841 | activate(); | |
842 | IPCSTART(ucsp_client_authorizationRelease(UCSP_ARGS, auth, flags)); | |
843 | if (rcode == CSSMERR_CSSM_NO_USER_INTERACTION) | |
844 | CssmError::throwMe(errAuthorizationInteractionNotAllowed); | |
845 | IPCEND_CHECK; | |
846 | } | |
847 | ||
848 | void ClientSession::authCopyRights(const AuthorizationBlob &auth, | |
849 | const AuthorizationItemSet *rights, const AuthorizationItemSet *environment, | |
850 | AuthorizationFlags flags, | |
851 | AuthorizationItemSet **grantedRights) | |
852 | { | |
853 | void *rightSet = NULL; mach_msg_size_t rightSet_size = 0; | |
854 | void *environ = NULL; mach_msg_size_t environ_size = 0; | |
855 | void *result = NULL; mach_msg_type_number_t resultLength = 0; | |
856 | ||
857 | if ((rights && !copyin_AuthorizationItemSet(rights, &rightSet, &rightSet_size)) || | |
858 | (environment && !copyin_AuthorizationItemSet(environment, &environ, &environ_size))) | |
859 | CssmError::throwMe(errAuthorizationInternal); // allocation error probably | |
860 | ||
861 | activate(); | |
862 | IPCSTART(ucsp_client_authorizationCopyRights(UCSP_ARGS, | |
863 | auth, | |
864 | rightSet, rightSet_size, | |
865 | flags | (grantedRights ? 0 : kAuthorizationFlagNoData), | |
866 | environ, environ_size, | |
867 | &result, &resultLength)); | |
868 | ||
869 | free(rightSet); | |
870 | free(environ); | |
871 | ||
872 | // XXX/cs return error when copyout returns false | |
873 | if (rcode == CSSM_OK && grantedRights) | |
874 | copyout_AuthorizationItemSet(result, resultLength, grantedRights); | |
875 | ||
876 | if (result) | |
877 | mig_deallocate(reinterpret_cast<vm_address_t>(result), resultLength); | |
878 | if (rcode == CSSMERR_CSSM_NO_USER_INTERACTION) | |
879 | CssmError::throwMe(errAuthorizationInteractionNotAllowed); | |
880 | IPCEND_CHECK; | |
881 | } | |
882 | ||
883 | void ClientSession::authCopyInfo(const AuthorizationBlob &auth, | |
884 | const char *tag, | |
885 | AuthorizationItemSet * &info) | |
886 | { | |
887 | if (tag == NULL) | |
888 | tag = ""; | |
889 | else if (tag[0] == '\0') | |
890 | MacOSError::throwMe(errAuthorizationInvalidTag); | |
891 | ||
892 | activate(); | |
893 | void *result; mach_msg_type_number_t resultLength; | |
894 | IPCSTART(ucsp_client_authorizationCopyInfo(UCSP_ARGS, auth, tag, &result, &resultLength)); | |
895 | ||
896 | // XXX/cs return error when copyout returns false | |
897 | if (rcode == CSSM_OK) | |
898 | copyout_AuthorizationItemSet(result, resultLength, &info); | |
899 | ||
900 | if (result) | |
901 | mig_deallocate(reinterpret_cast<vm_address_t>(result), resultLength); | |
902 | ||
903 | if (rcode == CSSMERR_CSSM_NO_USER_INTERACTION) | |
904 | CssmError::throwMe(errAuthorizationInteractionNotAllowed); | |
905 | IPCEND_CHECK; | |
906 | } | |
907 | ||
908 | void ClientSession::authExternalize(const AuthorizationBlob &auth, | |
909 | AuthorizationExternalForm &extForm) | |
910 | { | |
911 | activate(); | |
912 | IPCSTART(ucsp_client_authorizationExternalize(UCSP_ARGS, auth, &extForm)); | |
913 | if (rcode == CSSMERR_CSSM_NO_USER_INTERACTION) | |
914 | CssmError::throwMe(errAuthorizationInteractionNotAllowed); | |
915 | IPCEND_CHECK; | |
916 | } | |
917 | ||
918 | void ClientSession::authInternalize(const AuthorizationExternalForm &extForm, | |
919 | AuthorizationBlob &auth) | |
920 | { | |
921 | activate(); | |
922 | IPCSTART(ucsp_client_authorizationInternalize(UCSP_ARGS, extForm, &auth)); | |
923 | if (rcode == CSSMERR_CSSM_NO_USER_INTERACTION) | |
924 | CssmError::throwMe(errAuthorizationInteractionNotAllowed); | |
925 | IPCEND_CHECK; | |
926 | } | |
927 | ||
928 | ||
929 | // | |
930 | // Push user preferences from an app in user space to securityd | |
931 | // | |
932 | void ClientSession::setSessionUserPrefs(SecuritySessionId sessionId, uint32_t userPreferencesLength, const void *userPreferences) | |
933 | { | |
934 | IPC(ucsp_client_setSessionUserPrefs(UCSP_ARGS, sessionId, const_cast<void *>(userPreferences), userPreferencesLength)); | |
935 | } | |
936 | ||
937 | ||
938 | void ClientSession::postNotification(NotificationDomain domain, NotificationEvent event, const CssmData &data) | |
939 | { | |
940 | uint32 seq = ++mGlobal().thread().notifySeq; | |
941 | #if !defined(NDEBUG) | |
942 | if (getenv("NOTIFYJITTER")) { | |
943 | // artificially reverse odd/even sequences to test securityd's jitter buffer | |
944 | seq += 2 * (seq % 2) - 1; | |
945 | secdebug("notify", "POSTING FAKE SEQUENCE %d NOTIFICATION", seq); | |
946 | } | |
947 | #endif //NDEBUG | |
948 | secdebug("notify", "posting domain 0x%x event %d sequence %d", | |
949 | domain, event, seq); | |
950 | IPC(ucsp_client_postNotification(UCSP_ARGS, domain, event, DATA(data), seq)); | |
951 | } | |
952 | ||
953 | // | |
954 | // authorizationdbGet/Set/Remove | |
955 | // | |
956 | void ClientSession::authorizationdbGet(const AuthorizationString rightname, CssmData &rightDefinition, Allocator &alloc) | |
957 | { | |
958 | DataOutput definition(rightDefinition, alloc); | |
959 | activate(); | |
427c49bc | 960 | IPCSTART(ucsp_client_authorizationdbGet(UCSP_ARGS, rightname, DATA_OUT(definition))); |
b1ab9ed8 A |
961 | if (rcode == CSSMERR_CSSM_NO_USER_INTERACTION) |
962 | CssmError::throwMe(errAuthorizationInteractionNotAllowed); | |
963 | IPCEND_CHECK; | |
964 | } | |
965 | ||
966 | void ClientSession::authorizationdbSet(const AuthorizationBlob &auth, const AuthorizationString rightname, uint32_t rightDefinitionLength, const void *rightDefinition) | |
967 | { | |
968 | // @@@ DATA_IN in transition.cpp is not const void * | |
969 | activate(); | |
970 | IPCSTART(ucsp_client_authorizationdbSet(UCSP_ARGS, auth, rightname, const_cast<void *>(rightDefinition), rightDefinitionLength)); | |
971 | if (rcode == CSSMERR_CSSM_NO_USER_INTERACTION) | |
972 | CssmError::throwMe(errAuthorizationInteractionNotAllowed); | |
973 | IPCEND_CHECK; | |
974 | } | |
975 | ||
976 | void ClientSession::authorizationdbRemove(const AuthorizationBlob &auth, const AuthorizationString rightname) | |
977 | { | |
978 | activate(); | |
979 | IPCSTART(ucsp_client_authorizationdbRemove(UCSP_ARGS, auth, rightname)); | |
980 | if (rcode == CSSMERR_CSSM_NO_USER_INTERACTION) | |
981 | CssmError::throwMe(errAuthorizationInteractionNotAllowed); | |
982 | IPCEND_CHECK; | |
983 | } | |
984 | ||
985 | ||
b1ab9ed8 A |
986 | // |
987 | // Code Signing related | |
988 | // | |
989 | void ClientSession::registerHosting(mach_port_t hostingPort, SecCSFlags flags) | |
990 | { | |
991 | IPC(ucsp_client_registerHosting(UCSP_ARGS, hostingPort, flags)); | |
992 | } | |
993 | ||
994 | mach_port_t ClientSession::hostingPort(pid_t pid) | |
995 | { | |
996 | mach_port_t result; | |
997 | IPC(ucsp_client_hostingPort(UCSP_ARGS, pid, &result)); | |
998 | return result; | |
999 | } | |
1000 | ||
1001 | SecGuestRef ClientSession::createGuest(SecGuestRef host, | |
1002 | uint32_t status, const char *path, const CssmData &cdhash, const CssmData &attributes, SecCSFlags flags) | |
1003 | { | |
1004 | SecGuestRef newGuest; | |
1005 | IPC(ucsp_client_createGuest(UCSP_ARGS, host, status, path, DATA(cdhash), DATA(attributes), flags, &newGuest)); | |
1006 | if (flags & kSecCSDedicatedHost) { | |
1007 | secdebug("ssclient", "setting dedicated guest to 0x%x (was 0x%x)", | |
1008 | mDedicatedGuest, newGuest); | |
1009 | mDedicatedGuest = newGuest; | |
1010 | } | |
1011 | return newGuest; | |
1012 | } | |
1013 | ||
1014 | void ClientSession::setGuestStatus(SecGuestRef guest, uint32 status, const CssmData &attributes) | |
1015 | { | |
1016 | IPC(ucsp_client_setGuestStatus(UCSP_ARGS, guest, status, DATA(attributes))); | |
1017 | } | |
1018 | ||
1019 | void ClientSession::removeGuest(SecGuestRef host, SecGuestRef guest) | |
1020 | { | |
1021 | IPC(ucsp_client_removeGuest(UCSP_ARGS, host, guest)); | |
1022 | } | |
1023 | ||
1024 | void ClientSession::selectGuest(SecGuestRef newGuest) | |
1025 | { | |
1026 | if (mDedicatedGuest) { | |
1027 | secdebug("ssclient", "ignoring selectGuest(0x%x) because dedicated guest=0x%x", | |
1028 | newGuest, mDedicatedGuest); | |
1029 | } else { | |
1030 | secdebug("ssclient", "switching to guest 0x%x", newGuest); | |
1031 | mGlobal().thread().currentGuest = newGuest; | |
1032 | } | |
1033 | } | |
1034 | ||
1035 | SecGuestRef ClientSession::selectedGuest() const | |
1036 | { | |
1037 | if (mDedicatedGuest) | |
1038 | return mDedicatedGuest; | |
1039 | else | |
1040 | return mGlobal().thread().currentGuest; | |
1041 | } | |
1042 | ||
1043 | ||
1044 | } // end namespace SecurityServer | |
1045 | } // end namespace Security |