]> git.saurik.com Git - apple/security.git/blob - SecurityServer/sstransit.cpp
Security-29.tar.gz
[apple/security.git] / SecurityServer / sstransit.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 // sstransit - SecurityServer client library transition code.
21 //
22 // These are the functions that implement CssmClient methods in terms of
23 // MIG IPC client calls, plus their supporting machinery.
24 //
25 #include "sstransit.h"
26
27 namespace Security
28 {
29
30 using MachPlusPlus::check;
31
32
33 //
34 // Utility classes
35 //
36 DataOutput::~DataOutput()
37 {
38 if (mData) { // was assigned to; IPC returned OK
39 if (argument) { // buffer was provided
40 if (argument.length() < mLength)
41 CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR);
42 argument.length(mLength);
43 } else { // allocate buffer
44 argument = CssmData(allocator.malloc(mLength), mLength);
45 }
46 memcpy(argument.data(), mData, mLength);
47 }
48 }
49
50
51 CssmList chunkCopy(CssmList &list, CssmAllocator &alloc)
52 {
53 CssmList copy = list;
54 ChunkCopyWalker w(alloc);
55 walk(w, copy);
56 return copy;
57 }
58
59
60 //
61 // Create a packaged-up Context for IPC transmission.
62 // In addition to collecting the context into a contiguous blob for transmission,
63 // we also evaluate CssmCryptoData callbacks at this time.
64 //
65 SendContext::SendContext(const Context &ctx) : context(ctx)
66 {
67 CssmCryptoData cryptoDataValue; // holding area for CssmCryptoData element
68 IFDEBUG(uint32 cryptoDataUsed = 0);
69 Context::Builder builder(CssmAllocator::standard());
70 for (unsigned n = 0; n < ctx.attributesInUse(); n++) {
71 switch (ctx[n].baseType()) {
72 case CSSM_ATTRIBUTE_DATA_CRYPTO_DATA: {
73 CssmCryptoData &data = ctx[n]; // extract CssmCryptoData value
74 cryptoDataValue = data(); // evaluate callback (if any)
75 builder.setup(&cryptoDataValue); // use evaluted value
76 IFDEBUG(cryptoDataUsed++);
77 break;
78 }
79 default:
80 builder.setup(ctx[n]);
81 break;
82 }
83 }
84 attributeSize = builder.make();
85 for (unsigned n = 0; n < ctx.attributesInUse(); n++) {
86 const Context::Attr &attr = ctx[n];
87 switch (attr.baseType()) {
88 case CSSM_ATTRIBUTE_DATA_CRYPTO_DATA:
89 builder.put(attr.type(), &cryptoDataValue);
90 break;
91 default:
92 builder.put(attr);
93 break;
94 }
95 }
96 uint32 count; // not needed
97 builder.done(attributes, count);
98 assert(cryptoDataUsed <= 1); // no more than one slot converted
99 }
100
101
102 namespace SecurityServer
103 {
104
105 //
106 // Database control
107 //
108 DbHandle ClientSession::createDb(const DLDbIdentifier &dbId,
109 const AccessCredentials *cred, const AclEntryInput *owner,
110 const DBParameters &params)
111 {
112 Copier<AccessCredentials> creds(cred, internalAllocator);
113 Copier<AclEntryPrototype> proto(&owner->proto(), internalAllocator);
114 DataWalkers::DLDbFlatIdentifier ident(dbId);
115 Copier<DataWalkers::DLDbFlatIdentifier> id(&ident, internalAllocator);
116 DbHandle db;
117 IPC(ucsp_client_createDb(UCSP_ARGS, &db, COPY(id), COPY(creds), COPY(proto), params));
118 return db;
119 }
120
121 DbHandle ClientSession::decodeDb(const DLDbIdentifier &dbId,
122 const AccessCredentials *cred, const CssmData &blob)
123 {
124 Copier<AccessCredentials> creds(cred, internalAllocator);
125 DataWalkers::DLDbFlatIdentifier ident(dbId);
126 Copier<DataWalkers::DLDbFlatIdentifier> id(&ident, internalAllocator);
127 DbHandle db;
128 IPC(ucsp_client_decodeDb(UCSP_ARGS, &db, COPY(id), COPY(creds), DATA(blob)));
129 return db;
130 }
131
132 void ClientSession::encodeDb(DbHandle db, CssmData &blob, CssmAllocator &alloc)
133 {
134 DataOutput outBlob(blob, alloc);
135 IPC(ucsp_client_encodeDb(UCSP_ARGS, db, DATA(outBlob)));
136 }
137
138 void ClientSession::releaseDb(DbHandle db)
139 {
140 IPC(ucsp_client_releaseDb(UCSP_ARGS, db));
141 }
142
143 void ClientSession::authenticateDb(DbHandle db, DBAccessType type,
144 const AccessCredentials *cred)
145 {
146 Copier<AccessCredentials> creds(cred, internalAllocator);
147 IPC(ucsp_client_authenticateDb(UCSP_ARGS, db, COPY(creds)));
148 }
149
150 void ClientSession::setDbParameters(DbHandle db, const DBParameters &params)
151 {
152 IPC(ucsp_client_setDbParameters(UCSP_ARGS, db, params));
153 }
154
155 void ClientSession::getDbParameters(DbHandle db, DBParameters &params)
156 {
157 IPC(ucsp_client_getDbParameters(UCSP_ARGS, db, &params));
158 }
159
160 void ClientSession::changePassphrase(DbHandle db, const AccessCredentials *cred)
161 {
162 Copier<AccessCredentials> creds(cred, internalAllocator);
163 IPC(ucsp_client_changePassphrase(UCSP_ARGS, db, COPY(creds)));
164 }
165
166
167 void ClientSession::lock(DbHandle db)
168 {
169 IPC(ucsp_client_lockDb(UCSP_ARGS, db));
170 }
171
172 void ClientSession::unlock(DbHandle db)
173 {
174 IPC(ucsp_client_unlockDb(UCSP_ARGS, db));
175 }
176
177 void ClientSession::unlock(DbHandle db, const CssmData &passphrase)
178 {
179 IPC(ucsp_client_unlockDbWithPassphrase(UCSP_ARGS, db, DATA(passphrase)));
180 }
181
182 bool ClientSession::isLocked(DbHandle db)
183 {
184 boolean_t locked;
185 IPC(ucsp_client_isLocked(UCSP_ARGS, db, &locked));
186 return locked;
187 }
188
189
190 //
191 // Key control
192 //
193 void ClientSession::encodeKey(KeyHandle key, CssmData &blob,
194 KeyUID *uid, CssmAllocator &alloc)
195 {
196 DataOutput oBlob(blob, alloc);
197 void *uidp;
198 mach_msg_type_number_t uidLength;
199 IPC(ucsp_client_encodeKey(UCSP_ARGS, key, oBlob.data(), oBlob.length(),
200 (uid != NULL), &uidp, &uidLength));
201 // return key uid if requested
202 if (uid) {
203 assert(uidLength == sizeof(KeyUID));
204 memcpy(uid, uidp, sizeof(KeyUID));
205 }
206 }
207
208
209 KeyHandle ClientSession::decodeKey(DbHandle db, const CssmData &blob, CssmKey::Header &header)
210 {
211 KeyHandle key;
212 IPC(ucsp_client_decodeKey(UCSP_ARGS, &key, &header, db, blob.data(), blob.length()));
213 return key;
214 }
215
216 void ClientSession::releaseKey(KeyHandle key)
217 {
218 IPC(ucsp_client_releaseKey(UCSP_ARGS, key));
219 }
220
221
222 //
223 // Random number generation.
224 // This interfaces to the secure RNG inside the SecurityServer; it does not access
225 // a PRNG in its CSP. If you need a reproducible PRNG, attach a local CSP and use it.
226 // Note that this function does not allocate a buffer; it always fills the buffer provided.
227 //
228 void ClientSession::generateRandom(CssmData &data)
229 {
230 void *result;
231 mach_msg_type_number_t resultLength;
232 IPC(ucsp_client_generateRandom(UCSP_ARGS, data.length(), &result, &resultLength));
233 assert(resultLength == data.length());
234 memcpy(data.data(), result, data.length());
235 }
236
237
238 //
239 // Signatures and MACs
240 //
241 void ClientSession::generateSignature(const Context &context, KeyHandle key,
242 const CssmData &data, CssmData &signature, CssmAllocator &alloc)
243 {
244 SendContext ctx(context);
245 DataOutput sig(signature, alloc);
246 IPC(ucsp_client_generateSignature(UCSP_ARGS, CONTEXT(ctx), key,
247 DATA(data), DATA(sig)));
248 }
249
250 void ClientSession::verifySignature(const Context &context, KeyHandle key,
251 const CssmData &data, const CssmData &signature)
252 {
253 SendContext ctx(context);
254 IPC(ucsp_client_verifySignature(UCSP_ARGS, CONTEXT(ctx), key,
255 DATA(data), DATA(signature)));
256 }
257
258
259 void ClientSession::generateMac(const Context &context, KeyHandle key,
260 const CssmData &data, CssmData &signature, CssmAllocator &alloc)
261 {
262 SendContext ctx(context);
263 DataOutput sig(signature, alloc);
264 IPC(ucsp_client_generateMac(UCSP_ARGS, CONTEXT(ctx), key,
265 DATA(data), DATA(sig)));
266 }
267
268 void ClientSession::verifyMac(const Context &context, KeyHandle key,
269 const CssmData &data, const CssmData &signature)
270 {
271 SendContext ctx(context);
272 IPC(ucsp_client_verifyMac(UCSP_ARGS, CONTEXT(ctx), key,
273 DATA(data), DATA(signature)));
274 }
275
276
277 //
278 // Encryption/Decryption
279 //
280
281 void ClientSession::encrypt(const Context &context, KeyHandle key,
282 const CssmData &clear, CssmData &cipher, CssmAllocator &alloc)
283 {
284 SendContext ctx(context);
285 DataOutput cipherOut(cipher, alloc);
286 IPC(ucsp_client_encrypt(UCSP_ARGS, CONTEXT(ctx), key, DATA(clear), DATA(cipherOut)));
287 }
288
289 void ClientSession::decrypt(const Context &context, KeyHandle key,
290 const CssmData &cipher, CssmData &clear, CssmAllocator &alloc)
291 {
292 SendContext ctx(context);
293 DataOutput clearOut(clear, alloc);
294 IPC(ucsp_client_decrypt(UCSP_ARGS, CONTEXT(ctx), key, DATA(cipher), DATA(clearOut)));
295 }
296
297
298 //
299 // Key generation
300 //
301 void ClientSession::generateKey(DbHandle db, const Context &context, uint32 keyUsage, uint32 keyAttr,
302 const AccessCredentials *cred, const AclEntryInput *owner,
303 KeyHandle &newKey, CssmKey::Header &newHeader)
304 {
305 SendContext ctx(context);
306 Copier<AccessCredentials> creds(cred, internalAllocator);
307 Copier<AclEntryPrototype> proto(&owner->proto(), internalAllocator);
308 IPC(ucsp_client_generateKey(UCSP_ARGS, db, CONTEXT(ctx),
309 COPY(creds), COPY(proto), keyUsage, keyAttr, &newKey, &newHeader));
310 }
311
312 void ClientSession::generateKey(DbHandle db, const Context &context,
313 uint32 pubKeyUsage, uint32 pubKeyAttr,
314 uint32 privKeyUsage, uint32 privKeyAttr,
315 const AccessCredentials *cred, const AclEntryInput *owner,
316 KeyHandle &pubKey, CssmKey::Header &pubHeader,
317 KeyHandle &privKey, CssmKey::Header &privHeader)
318 {
319 SendContext ctx(context);
320 Copier<AccessCredentials> creds(cred, internalAllocator);
321 Copier<AclEntryPrototype> proto(&owner->proto(), internalAllocator);
322 IPC(ucsp_client_generateKeyPair(UCSP_ARGS, db, CONTEXT(ctx),
323 COPY(creds), COPY(proto),
324 pubKeyUsage, pubKeyAttr, privKeyUsage, privKeyAttr,
325 &pubKey, &pubHeader, &privKey, &privHeader));
326 }
327
328
329 //
330 // Key wrapping and unwrapping
331 //
332 void ClientSession::wrapKey(const Context &context, KeyHandle wrappingKey,
333 KeyHandle keyToBeWrapped, const AccessCredentials *cred,
334 const CssmData *descriptiveData, CssmWrappedKey &wrappedKey, CssmAllocator &alloc)
335 {
336 SendContext ctx(context);
337 Copier<AccessCredentials> creds(cred, internalAllocator);
338 DataOutput keyData(wrappedKey, alloc);
339 IPC(ucsp_client_wrapKey(UCSP_ARGS, CONTEXT(ctx), wrappingKey, COPY(creds),
340 keyToBeWrapped, OPTIONALDATA(descriptiveData),
341 &wrappedKey, DATA(keyData)));
342 wrappedKey = CssmData(); // null out data section (force allocation for key data)
343 }
344
345 void ClientSession::unwrapKey(DbHandle db, const Context &context, KeyHandle key,
346 KeyHandle publicKey, const CssmWrappedKey &wrappedKey,
347 uint32 usage, uint32 attr,
348 const AccessCredentials *cred, const AclEntryInput *acl,
349 CssmData &descriptiveData,
350 KeyHandle &newKey, CssmKey::Header &newHeader, CssmAllocator &alloc)
351 {
352 SendContext ctx(context);
353 DataOutput descriptor(descriptiveData, alloc);
354 Copier<AccessCredentials> creds(cred, internalAllocator);
355 Copier<AclEntryPrototype> proto(&acl->proto(), internalAllocator);
356 IPC(ucsp_client_unwrapKey(UCSP_ARGS, db, CONTEXT(ctx), key,
357 COPY(creds), COPY(proto),
358 publicKey, wrappedKey, DATA(wrappedKey), usage, attr, DATA(descriptor),
359 &newKey, &newHeader));
360 }
361
362
363 //
364 // ACL management
365 //
366 void ClientSession::getAcl(AclKind kind, KeyHandle key, const char *tag,
367 uint32 &infoCount, AclEntryInfo * &infoArray, CssmAllocator &alloc)
368 {
369 uint32 count;
370 AclEntryInfo *info, *infoBase;
371 mach_msg_type_number_t infoLength;
372 IPC(ucsp_client_getAcl(UCSP_ARGS, kind, key,
373 (tag != NULL), tag ? tag : "",
374 &count, COPY_OUT(info)));
375 infoCount = count;
376
377 // relocate incoming AclEntryInfo array
378 ReconstituteWalker relocator(info, infoBase);
379 for (uint32 n = 0; n < count; n++)
380 walk(relocator, info[n]);
381
382 // copy AclEntryInfo array into discrete memory nodes
383 infoArray = alloc.alloc<AclEntryInfo>(count);
384 ChunkCopyWalker chunker(alloc);
385 for (uint32 n = 0; n < count; n++) {
386 infoArray[n] = info[n];
387 walk(chunker, infoArray[n]);
388 }
389 }
390
391 void ClientSession::changeAcl(AclKind kind, KeyHandle key, const AccessCredentials &cred,
392 const AclEdit &edit)
393 {
394 Copier<AccessCredentials> creds(&cred, internalAllocator);
395 //@@@ ignoring callback
396 Copier<AclEntryPrototype> aclEntry(&edit.newEntry()->proto(), internalAllocator);
397 IPC(ucsp_client_changeAcl(UCSP_ARGS, kind, key, COPY(creds),
398 edit.mode(), edit.handle(), COPY(aclEntry)));
399 }
400
401 void ClientSession::getOwner(AclKind kind, KeyHandle key, AclOwnerPrototype &owner,
402 CssmAllocator &alloc)
403 {
404 AclOwnerPrototype *proto, *protoBase;
405 mach_msg_type_number_t protoLength;
406 IPC(ucsp_client_getOwner(UCSP_ARGS, kind, key, COPY_OUT(proto)));
407 // turn the returned AclOwnerPrototype into its proper output form
408 relocate(proto, protoBase);
409 owner.TypedSubject = chunkCopy(proto->subject(), alloc);
410 owner.Delegate = proto->delegate();
411 }
412
413 void ClientSession::changeOwner(AclKind kind, KeyHandle key,
414 const AccessCredentials &cred, const AclOwnerPrototype &proto)
415 {
416 Copier<AccessCredentials> creds(&cred, internalAllocator);
417 Copier<AclOwnerPrototype> protos(&proto, internalAllocator);
418 IPC(ucsp_client_setOwner(UCSP_ARGS, kind, key, COPY(creds), COPY(protos)));
419 }
420
421
422 void ClientSession::getKeyAcl(DbHandle db, const char *tag,
423 uint32 &count, AclEntryInfo * &info, CssmAllocator &alloc)
424 { getAcl(keyAcl, db, tag, count, info, alloc); }
425
426 void ClientSession::changeKeyAcl(DbHandle db, const AccessCredentials &cred,
427 const AclEdit &edit)
428 { changeAcl(keyAcl, db, cred, edit); }
429
430 void ClientSession::getKeyOwner(DbHandle db, AclOwnerPrototype &owner, CssmAllocator &alloc)
431 { getOwner(keyAcl, db, owner, alloc); }
432
433 void ClientSession::changeKeyOwner(DbHandle db, const AccessCredentials &cred,
434 const AclOwnerPrototype &edit)
435 { changeOwner(keyAcl, db, cred, edit); }
436
437 void ClientSession::getDbAcl(DbHandle db, const char *tag,
438 uint32 &count, AclEntryInfo * &info, CssmAllocator &alloc)
439 { getAcl(dbAcl, db, tag, count, info, alloc); }
440
441 void ClientSession::changeDbAcl(DbHandle db, const AccessCredentials &cred,
442 const AclEdit &edit)
443 { changeAcl(dbAcl, db, cred, edit); }
444
445 void ClientSession::getDbOwner(DbHandle db, AclOwnerPrototype &owner, CssmAllocator &alloc)
446 { getOwner(dbAcl, db, owner, alloc); }
447
448 void ClientSession::changeDbOwner(DbHandle db, const AccessCredentials &cred,
449 const AclOwnerPrototype &edit)
450 { changeOwner(dbAcl, db, cred, edit); }
451
452
453 //
454 // Authorization subsystem entry
455 //
456 void ClientSession::authCreate(const AuthorizationItemSet *rights,
457 const AuthorizationItemSet *environment, AuthorizationFlags flags,
458 AuthorizationBlob &result)
459 {
460 Copier<AuthorizationItemSet> rightSet(rights, internalAllocator);
461 Copier<AuthorizationItemSet> environ(environment, internalAllocator);
462 IPC(ucsp_client_authorizationCreate(UCSP_ARGS,
463 COPY(rightSet), flags, COPY(environ), &result));
464 }
465
466 void ClientSession::authRelease(const AuthorizationBlob &auth,
467 AuthorizationFlags flags)
468 {
469 IPC(ucsp_client_authorizationRelease(UCSP_ARGS, auth, flags));
470 }
471
472 void ClientSession::authCopyRights(const AuthorizationBlob &auth,
473 const AuthorizationItemSet *rights, const AuthorizationItemSet *environment,
474 AuthorizationFlags flags,
475 AuthorizationItemSet **grantedRights)
476 {
477 Copier<AuthorizationItemSet> rightSet(rights, internalAllocator);
478 Copier<AuthorizationItemSet> environ(environment, internalAllocator);
479 COPY_OUT_DECL(AuthorizationItemSet, result);
480 IPC(ucsp_client_authorizationCopyRights(UCSP_ARGS, auth, COPY(rightSet),
481 flags | (grantedRights ? 0 : kAuthorizationFlagNoData),
482 COPY(environ), COPY_OUT(result)));
483 // return rights vector (only) if requested
484 if (grantedRights) {
485 relocate(result, resultBase);
486 *grantedRights = copy(result, returnAllocator);
487 }
488 }
489
490 void ClientSession::authCopyInfo(const AuthorizationBlob &auth,
491 const char *tag,
492 AuthorizationItemSet * &info)
493 {
494 COPY_OUT_DECL(AuthorizationItemSet, result);
495 if (tag == NULL)
496 tag = "";
497 else if (tag[0] == '\0')
498 MacOSError::throwMe(errAuthorizationInvalidTag);
499 IPC(ucsp_client_authorizationCopyInfo(UCSP_ARGS, auth, tag, COPY_OUT(result)));
500 relocate(result, resultBase);
501 info = copy(result, returnAllocator);
502 }
503
504 void ClientSession::authExternalize(const AuthorizationBlob &auth,
505 AuthorizationExternalForm &extForm)
506 {
507 IPC(ucsp_client_authorizationExternalize(UCSP_ARGS, auth, &extForm));
508 }
509
510 void ClientSession::authInternalize(const AuthorizationExternalForm &extForm,
511 AuthorizationBlob &auth)
512 {
513 IPC(ucsp_client_authorizationInternalize(UCSP_ARGS, extForm, &auth));
514 }
515
516
517 //
518 // Session management API
519 //
520 void ClientSession::getSessionInfo(SecuritySessionId &sessionId, SessionAttributeBits &attrs)
521 {
522 IPC(ucsp_client_getSessionInfo(UCSP_ARGS, &sessionId, &attrs));
523 }
524
525 void ClientSession::setupSession(SessionCreationFlags flags, SessionAttributeBits attrs)
526 {
527 IPC(ucsp_client_setupSession(UCSP_ARGS, flags, attrs));
528 }
529
530
531 } // end namespace SecurityServer
532
533 } // end namespace Security