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 // sstransit - SecurityServer client library transition code.
22 // These are the functions that implement CssmClient methods in terms of
23 // MIG IPC client calls, plus their supporting machinery.
25 #include "sstransit.h"
30 using MachPlusPlus::check
;
36 DataOutput::~DataOutput()
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
);
46 memcpy(argument
.data(), mData
, mLength
);
51 CssmList
chunkCopy(CssmList
&list
, CssmAllocator
&alloc
)
54 ChunkCopyWalker
w(alloc
);
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.
65 SendContext::SendContext(const Context
&ctx
) : context(ctx
)
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
++);
80 builder
.setup(ctx
[n
]);
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
);
96 uint32 count
; // not needed
97 builder
.done(attributes
, count
);
98 assert(cryptoDataUsed
<= 1); // no more than one slot converted
102 namespace SecurityServer
108 DbHandle
ClientSession::createDb(const DLDbIdentifier
&dbId
,
109 const AccessCredentials
*cred
, const AclEntryInput
*owner
,
110 const DBParameters
¶ms
)
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
);
117 IPC(ucsp_client_createDb(UCSP_ARGS
, &db
, COPY(id
), COPY(creds
), COPY(proto
), params
));
121 DbHandle
ClientSession::decodeDb(const DLDbIdentifier
&dbId
,
122 const AccessCredentials
*cred
, const CssmData
&blob
)
124 Copier
<AccessCredentials
> creds(cred
, internalAllocator
);
125 DataWalkers::DLDbFlatIdentifier
ident(dbId
);
126 Copier
<DataWalkers::DLDbFlatIdentifier
> id(&ident
, internalAllocator
);
128 IPC(ucsp_client_decodeDb(UCSP_ARGS
, &db
, COPY(id
), COPY(creds
), DATA(blob
)));
132 void ClientSession::encodeDb(DbHandle db
, CssmData
&blob
, CssmAllocator
&alloc
)
134 DataOutput
outBlob(blob
, alloc
);
135 IPC(ucsp_client_encodeDb(UCSP_ARGS
, db
, DATA(outBlob
)));
138 void ClientSession::releaseDb(DbHandle db
)
140 IPC(ucsp_client_releaseDb(UCSP_ARGS
, db
));
143 void ClientSession::authenticateDb(DbHandle db
, DBAccessType type
,
144 const AccessCredentials
*cred
)
146 Copier
<AccessCredentials
> creds(cred
, internalAllocator
);
147 IPC(ucsp_client_authenticateDb(UCSP_ARGS
, db
, COPY(creds
)));
150 void ClientSession::setDbParameters(DbHandle db
, const DBParameters
¶ms
)
152 IPC(ucsp_client_setDbParameters(UCSP_ARGS
, db
, params
));
155 void ClientSession::getDbParameters(DbHandle db
, DBParameters
¶ms
)
157 IPC(ucsp_client_getDbParameters(UCSP_ARGS
, db
, ¶ms
));
160 void ClientSession::changePassphrase(DbHandle db
, const AccessCredentials
*cred
)
162 Copier
<AccessCredentials
> creds(cred
, internalAllocator
);
163 IPC(ucsp_client_changePassphrase(UCSP_ARGS
, db
, COPY(creds
)));
167 void ClientSession::lock(DbHandle db
)
169 IPC(ucsp_client_lockDb(UCSP_ARGS
, db
));
172 void ClientSession::unlock(DbHandle db
)
174 IPC(ucsp_client_unlockDb(UCSP_ARGS
, db
));
177 void ClientSession::unlock(DbHandle db
, const CssmData
&passphrase
)
179 IPC(ucsp_client_unlockDbWithPassphrase(UCSP_ARGS
, db
, DATA(passphrase
)));
182 bool ClientSession::isLocked(DbHandle db
)
185 IPC(ucsp_client_isLocked(UCSP_ARGS
, db
, &locked
));
193 void ClientSession::encodeKey(KeyHandle key
, CssmData
&blob
,
194 KeyUID
*uid
, CssmAllocator
&alloc
)
196 DataOutput
oBlob(blob
, alloc
);
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
203 assert(uidLength
== sizeof(KeyUID
));
204 memcpy(uid
, uidp
, sizeof(KeyUID
));
209 KeyHandle
ClientSession::decodeKey(DbHandle db
, const CssmData
&blob
, CssmKey::Header
&header
)
212 IPC(ucsp_client_decodeKey(UCSP_ARGS
, &key
, &header
, db
, blob
.data(), blob
.length()));
216 void ClientSession::releaseKey(KeyHandle key
)
218 IPC(ucsp_client_releaseKey(UCSP_ARGS
, key
));
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.
228 void ClientSession::generateRandom(CssmData
&data
)
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());
239 // Signatures and MACs
241 void ClientSession::generateSignature(const Context
&context
, KeyHandle key
,
242 const CssmData
&data
, CssmData
&signature
, CssmAllocator
&alloc
)
244 SendContext
ctx(context
);
245 DataOutput
sig(signature
, alloc
);
246 IPC(ucsp_client_generateSignature(UCSP_ARGS
, CONTEXT(ctx
), key
,
247 DATA(data
), DATA(sig
)));
250 void ClientSession::verifySignature(const Context
&context
, KeyHandle key
,
251 const CssmData
&data
, const CssmData
&signature
)
253 SendContext
ctx(context
);
254 IPC(ucsp_client_verifySignature(UCSP_ARGS
, CONTEXT(ctx
), key
,
255 DATA(data
), DATA(signature
)));
259 void ClientSession::generateMac(const Context
&context
, KeyHandle key
,
260 const CssmData
&data
, CssmData
&signature
, CssmAllocator
&alloc
)
262 SendContext
ctx(context
);
263 DataOutput
sig(signature
, alloc
);
264 IPC(ucsp_client_generateMac(UCSP_ARGS
, CONTEXT(ctx
), key
,
265 DATA(data
), DATA(sig
)));
268 void ClientSession::verifyMac(const Context
&context
, KeyHandle key
,
269 const CssmData
&data
, const CssmData
&signature
)
271 SendContext
ctx(context
);
272 IPC(ucsp_client_verifyMac(UCSP_ARGS
, CONTEXT(ctx
), key
,
273 DATA(data
), DATA(signature
)));
278 // Encryption/Decryption
281 void ClientSession::encrypt(const Context
&context
, KeyHandle key
,
282 const CssmData
&clear
, CssmData
&cipher
, CssmAllocator
&alloc
)
284 SendContext
ctx(context
);
285 DataOutput
cipherOut(cipher
, alloc
);
286 IPC(ucsp_client_encrypt(UCSP_ARGS
, CONTEXT(ctx
), key
, DATA(clear
), DATA(cipherOut
)));
289 void ClientSession::decrypt(const Context
&context
, KeyHandle key
,
290 const CssmData
&cipher
, CssmData
&clear
, CssmAllocator
&alloc
)
292 SendContext
ctx(context
);
293 DataOutput
clearOut(clear
, alloc
);
294 IPC(ucsp_client_decrypt(UCSP_ARGS
, CONTEXT(ctx
), key
, DATA(cipher
), DATA(clearOut
)));
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
)
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
));
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
)
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
));
330 // Key wrapping and unwrapping
332 void ClientSession::wrapKey(const Context
&context
, KeyHandle wrappingKey
,
333 KeyHandle keyToBeWrapped
, const AccessCredentials
*cred
,
334 const CssmData
*descriptiveData
, CssmWrappedKey
&wrappedKey
, CssmAllocator
&alloc
)
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)
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
)
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
));
366 void ClientSession::getAcl(AclKind kind
, KeyHandle key
, const char *tag
,
367 uint32
&infoCount
, AclEntryInfo
* &infoArray
, CssmAllocator
&alloc
)
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
)));
377 // relocate incoming AclEntryInfo array
378 ReconstituteWalker
relocator(info
, infoBase
);
379 for (uint32 n
= 0; n
< count
; n
++)
380 walk(relocator
, info
[n
]);
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
]);
391 void ClientSession::changeAcl(AclKind kind
, KeyHandle key
, const AccessCredentials
&cred
,
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
)));
401 void ClientSession::getOwner(AclKind kind
, KeyHandle key
, AclOwnerPrototype
&owner
,
402 CssmAllocator
&alloc
)
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();
413 void ClientSession::changeOwner(AclKind kind
, KeyHandle key
,
414 const AccessCredentials
&cred
, const AclOwnerPrototype
&proto
)
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
)));
422 void ClientSession::getKeyAcl(DbHandle db
, const char *tag
,
423 uint32
&count
, AclEntryInfo
* &info
, CssmAllocator
&alloc
)
424 { getAcl(keyAcl
, db
, tag
, count
, info
, alloc
); }
426 void ClientSession::changeKeyAcl(DbHandle db
, const AccessCredentials
&cred
,
428 { changeAcl(keyAcl
, db
, cred
, edit
); }
430 void ClientSession::getKeyOwner(DbHandle db
, AclOwnerPrototype
&owner
, CssmAllocator
&alloc
)
431 { getOwner(keyAcl
, db
, owner
, alloc
); }
433 void ClientSession::changeKeyOwner(DbHandle db
, const AccessCredentials
&cred
,
434 const AclOwnerPrototype
&edit
)
435 { changeOwner(keyAcl
, db
, cred
, edit
); }
437 void ClientSession::getDbAcl(DbHandle db
, const char *tag
,
438 uint32
&count
, AclEntryInfo
* &info
, CssmAllocator
&alloc
)
439 { getAcl(dbAcl
, db
, tag
, count
, info
, alloc
); }
441 void ClientSession::changeDbAcl(DbHandle db
, const AccessCredentials
&cred
,
443 { changeAcl(dbAcl
, db
, cred
, edit
); }
445 void ClientSession::getDbOwner(DbHandle db
, AclOwnerPrototype
&owner
, CssmAllocator
&alloc
)
446 { getOwner(dbAcl
, db
, owner
, alloc
); }
448 void ClientSession::changeDbOwner(DbHandle db
, const AccessCredentials
&cred
,
449 const AclOwnerPrototype
&edit
)
450 { changeOwner(dbAcl
, db
, cred
, edit
); }
454 // Authorization subsystem entry
456 void ClientSession::authCreate(const AuthorizationItemSet
*rights
,
457 const AuthorizationItemSet
*environment
, AuthorizationFlags flags
,
458 AuthorizationBlob
&result
)
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
));
466 void ClientSession::authRelease(const AuthorizationBlob
&auth
,
467 AuthorizationFlags flags
)
469 IPC(ucsp_client_authorizationRelease(UCSP_ARGS
, auth
, flags
));
472 void ClientSession::authCopyRights(const AuthorizationBlob
&auth
,
473 const AuthorizationItemSet
*rights
, const AuthorizationItemSet
*environment
,
474 AuthorizationFlags flags
,
475 AuthorizationItemSet
**grantedRights
)
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
485 relocate(result
, resultBase
);
486 *grantedRights
= copy(result
, returnAllocator
);
490 void ClientSession::authCopyInfo(const AuthorizationBlob
&auth
,
492 AuthorizationItemSet
* &info
)
494 COPY_OUT_DECL(AuthorizationItemSet
, result
);
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
);
504 void ClientSession::authExternalize(const AuthorizationBlob
&auth
,
505 AuthorizationExternalForm
&extForm
)
507 IPC(ucsp_client_authorizationExternalize(UCSP_ARGS
, auth
, &extForm
));
510 void ClientSession::authInternalize(const AuthorizationExternalForm
&extForm
,
511 AuthorizationBlob
&auth
)
513 IPC(ucsp_client_authorizationInternalize(UCSP_ARGS
, extForm
, &auth
));
518 // Session management API
520 void ClientSession::getSessionInfo(SecuritySessionId
&sessionId
, SessionAttributeBits
&attrs
)
522 IPC(ucsp_client_getSessionInfo(UCSP_ARGS
, &sessionId
, &attrs
));
525 void ClientSession::setupSession(SessionCreationFlags flags
, SessionAttributeBits attrs
)
527 IPC(ucsp_client_setupSession(UCSP_ARGS
, flags
, attrs
));
531 } // end namespace SecurityServer
533 } // end namespace Security