2 * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
28 // transition - SecurityServer IPC-to-class-methods transition layer
30 #include <securityd_client/ucsp.h>
34 #include "kcdatabase.h"
36 #include "transwalkers.h"
37 #include <mach/mach_error.h>
39 #include <CoreFoundation/CFDictionary.h>
40 #include <CoreFoundation/CFPropertyList.h>
45 #define UCSP_ARGS mach_port_t servicePort, mach_port_t replyPort, security_token_t securityToken, \
47 #define CONTEXT_ARGS Context context, Pointer contextBase, Context::Attr *attributes, mach_msg_type_number_t attrSize
49 #define BEGIN_IPCN *rcode = CSSM_OK; try {
50 #define BEGIN_IPC BEGIN_IPCN RefPointer<Connection> connRef(&Server::connection(replyPort)); \
51 Connection &connection __attribute__((unused)) = *connRef;
52 #define END_IPC(base) END_IPCN(base) Server::requestComplete(); return KERN_SUCCESS;
53 #define END_IPCN(base) } \
54 catch (const CommonError &err) { *rcode = CssmError::cssmError(err, CSSM_ ## base ## _BASE_ERROR); } \
55 catch (const std::bad_alloc &) { *rcode = CssmError::merge(CSSM_ERRCODE_MEMORY_ERROR, CSSM_ ## base ## _BASE_ERROR); } \
56 catch (Connection *conn) { *rcode = 0; } \
57 catch (...) { *rcode = CssmError::merge(CSSM_ERRCODE_INTERNAL_ERROR, CSSM_ ## base ## _BASE_ERROR); }
59 #define DATA_IN(base) void *base, mach_msg_type_number_t base##Length
60 #define DATA_OUT(base) void **base, mach_msg_type_number_t *base##Length
61 #define DATA(base) CssmData(base, base##Length)
63 #define COPY_IN(type,name) type *name, mach_msg_type_number_t name##Length, type *name##Base
64 #define COPY_OUT(type,name) \
65 type **name, mach_msg_type_number_t *name##Length, type **name##Base
68 using LowLevelMemoryUtilities::increment
;
69 using LowLevelMemoryUtilities::difference
;
73 // An OutputData object will take memory allocated within the SecurityServer,
74 // hand it to the MIG return-output parameters, and schedule it to be released
75 // after the MIG reply has been sent. It will also get rid of it in case of
78 class OutputData
: public CssmData
{
80 OutputData(void **outP
, mach_msg_type_number_t
*outLength
)
81 : mData(*outP
), mLength(*outLength
) { }
83 { mData
= data(); mLength
= length(); Server::releaseWhenDone(mData
); }
85 void operator = (const CssmData
&source
)
86 { CssmData::operator = (source
); }
90 mach_msg_type_number_t
&mLength
;
95 // Setup/Teardown functions.
97 kern_return_t
ucsp_server_setup(UCSP_ARGS
, mach_port_t taskPort
, ClientSetupInfo info
, const char *identity
)
100 Server::active().setupConnection(Server::connectNewProcess
, servicePort
, replyPort
,
101 taskPort
, securityToken
, &info
, identity
);
106 kern_return_t
ucsp_server_setupNew(UCSP_ARGS
, mach_port_t taskPort
,
107 ClientSetupInfo info
, const char *identity
,
108 mach_port_t
*newServicePort
)
112 RefPointer
<Session
> session
= new DynamicSession(TaskPort(taskPort
).bootstrap());
113 Server::active().setupConnection(Server::connectNewSession
, session
->servicePort(), replyPort
,
114 taskPort
, securityToken
, &info
, identity
);
115 *newServicePort
= session
->servicePort();
116 } catch (const MachPlusPlus::Error
&err
) {
118 case BOOTSTRAP_SERVICE_ACTIVE
:
119 MacOSError::throwMe(errSessionAuthorizationDenied
); // translate
128 kern_return_t
ucsp_server_setupThread(UCSP_ARGS
, mach_port_t taskPort
)
131 Server::active().setupConnection(Server::connectNewThread
, servicePort
, replyPort
,
132 taskPort
, securityToken
);
138 kern_return_t
ucsp_server_teardown(UCSP_ARGS
)
141 Server::active().endConnection(replyPort
);
151 kern_return_t
ucsp_server_attach(UCSP_ARGS
, COPY_IN(CssmSubserviceUid
, ssUid
), AttachmentHandle
*attachment
)
154 secdebug("dl", "attach");
155 relocate(ssUid
, ssUidBase
, ssUidLength
);
161 kern_return_t
ucsp_server_detach(UCSP_ARGS
, AttachmentHandle attachment
)
164 secdebug("dl", "detach");
169 kern_return_t
ucsp_server_openDb(UCSP_ARGS
, AttachmentHandle attachment
, DATA_IN(name
),
170 COPY_IN(CssmNetAddress
, location
), CSSM_DB_ACCESS_TYPE accessType
,
171 COPY_IN(AccessCredentials
, accessCredentials
), DATA_IN(openParameters
), DbHandle
*db
)
174 secdebug("dl", "openDb");
176 relocate(location
, locationBase
, locationLength
);
177 relocate(accessCredentials
, accessCredentialsBase
, accessCredentialsLength
);
178 //DATA(openParameters);
184 kern_return_t
ucsp_server_createDb2(UCSP_ARGS
, AttachmentHandle attachment
, DATA_IN(name
),
185 COPY_IN(CssmNetAddress
, location
), COPY_IN(CSSM_DBINFO
, dbInfo
), CSSM_DB_ACCESS_TYPE accessType
,
186 COPY_IN(AccessCredentials
, accessCredentials
), COPY_IN(AclEntryPrototype
, aclEntryPrototype
),
187 DATA_IN(openParameters
), DbHandle
*db
)
190 secdebug("dl", "createDb2");
192 relocate(location
, locationBase
, locationLength
);
193 relocate(dbInfo
, dbInfoBase
, dbInfoLength
);
194 relocate(accessCredentials
, accessCredentialsBase
, accessCredentialsLength
);
195 relocate(aclEntryPrototype
, aclEntryPrototypeBase
, aclEntryPrototypeLength
);
196 //DATA(openParameters);
202 kern_return_t
ucsp_server_deleteDb(UCSP_ARGS
, AttachmentHandle attachment
,
203 DATA_IN(name
), COPY_IN(CssmNetAddress
, location
), COPY_IN(AccessCredentials
, accessCredentials
))
206 secdebug("dl", "deleteDb");
208 relocate(location
, locationBase
, locationLength
);
209 relocate(accessCredentials
, accessCredentialsBase
, accessCredentialsLength
);
214 kern_return_t
ucsp_server_getDbNames(UCSP_ARGS
, AttachmentHandle attachment
,
215 COPY_OUT(CSSM_NAME_LIST
, outNameList
))
218 secdebug("dl", "getDbNames");
221 CSSM_NAME_LIST
*nameList
;
222 //Attachment &a = Proccess::attachment(attachment);
223 //nameList = a.copyNameList();
224 Copier
<CSSM_NAME_LIST
> nameLists(nameList
, Allocator::standard()); // make flat copy
225 //a.freeNameList(nameList); // Release original
226 *outNameListLength
= nameLists
.length();
227 //flips(nameLists.value(), outNameList, outNameListBase);
228 Server::releaseWhenDone(nameLists
.keep()); // throw flat copy out when done
232 kern_return_t
ucsp_server_getDbNameFromHandle(UCSP_ARGS
, DbHandle db
, DATA_OUT(name
))
235 secdebug("dl", "getDbNameFromHandle");
240 kern_return_t
ucsp_server_closeDb(UCSP_ARGS
, DbHandle db
)
243 secdebug("dl", "closeDb");
248 kern_return_t
ucsp_server_authenticateDb(UCSP_ARGS
, DbHandle db
,
249 CSSM_DB_ACCESS_TYPE accessType
, COPY_IN(AccessCredentials
, cred
))
252 secdebug("dl", "authenticateDb");
253 relocate(cred
, credBase
, credLength
);
254 // @@@ Pass in accessType.
255 Server::database(db
)->authenticate(cred
);
259 kern_return_t
ucsp_server_createRelation(UCSP_ARGS
, DbHandle db
,
260 CSSM_DB_RECORDTYPE recordType
,
261 RelationName relationName
,
262 uint32 attributeCount
,
263 COPY_IN(CSSM_DB_SCHEMA_ATTRIBUTE_INFO
, attributes
),
265 COPY_IN(CSSM_DB_SCHEMA_INDEX_INFO
, indices
))
268 secdebug("dl", "createRelation");
269 CheckingReconstituteWalker
relocator(attributes
, attributesBase
, attributesLength
,
270 Server::process().byteFlipped());
271 for (uint32 ix
= 0; ix
< attributeCount
; ++ix
)
272 walk(relocator
, attributes
[ix
]);
273 CheckingReconstituteWalker
relocator2(indices
, indicesBase
, indicesLength
,
274 Server::process().byteFlipped());
275 for (uint32 ix
= 0; ix
< indexCount
; ++ix
)
276 walk(relocator
, indices
[ix
]);
281 kern_return_t
ucsp_server_destroyRelation(UCSP_ARGS
, DbHandle db
, CSSM_DB_RECORDTYPE recordType
)
284 secdebug("dl", "destroyRelation");
289 kern_return_t
ucsp_server_insertRecord(UCSP_ARGS
, DbHandle db
, CSSM_DB_RECORDTYPE recordType
,
290 COPY_IN(CssmDbRecordAttributeData
, attributes
), DATA_IN(data
), RecordHandle
*record
)
293 secdebug("dl", "insertRecord");
298 kern_return_t
ucsp_server_deleteRecord(UCSP_ARGS
, RecordHandle record
)
301 secdebug("dl", "deleteRecord");
306 kern_return_t
ucsp_server_modifyRecord(UCSP_ARGS
, RecordHandle record
, CSSM_DB_RECORDTYPE recordType
,
307 COPY_IN(CssmDbRecordAttributeData
, attributes
), DATA_IN(data
), CSSM_DB_MODIFY_MODE modifyMode
)
310 secdebug("dl", "modifyRecord");
315 kern_return_t
ucsp_server_findFirstRecord(UCSP_ARGS
, DbHandle db
,
316 COPY_IN(CssmQuery
, query
),
317 SearchHandle
*search
,
318 COPY_IN(CssmDbRecordAttributeData
, inAttributes
),
319 COPY_OUT(CssmDbRecordAttributeData
, outAttributes
),
326 secdebug("dl", "findFirstRecord");
331 kern_return_t
ucsp_server_findNextRecord(UCSP_ARGS
, SearchHandle search
,
332 COPY_IN(CssmDbRecordAttributeData
, inAttributes
),
333 COPY_OUT(CssmDbRecordAttributeData
, outAttributes
),
336 RecordHandle
*record
)
339 secdebug("dl", "findNextRecord");
344 kern_return_t
ucsp_server_abortFind(UCSP_ARGS
, SearchHandle search
)
347 secdebug("dl", "abortFind");
348 //delete &Process::search(search);
353 kern_return_t
ucsp_server_getRecordFromHandle(UCSP_ARGS
, RecordHandle record
,
354 COPY_IN(CssmDbRecordAttributeData
, inAttributes
),
355 COPY_OUT(CssmDbRecordAttributeData
, outAttributes
),
360 secdebug("dl", "getRecordFromHandle");
361 relocate(inAttributes
, inAttributesBase
, inAttributesLength
);
366 kern_return_t
ucsp_server_freeRecordHandle(UCSP_ARGS
, RecordHandle record
)
369 secdebug("dl", "freeRecordHandle");
370 //delete &Process::record(record);
377 // Database management
379 kern_return_t
ucsp_server_createDb(UCSP_ARGS
, DbHandle
*db
,
380 COPY_IN(DLDbFlatIdentifier
, ident
),
381 COPY_IN(AccessCredentials
, cred
), COPY_IN(AclEntryPrototype
, owner
),
385 relocate(cred
, credBase
, credLength
);
386 relocate(owner
, ownerBase
, ownerLength
);
387 relocate(ident
, identBase
, identLength
);
388 *db
= (new KeychainDatabase(*ident
, params
, connection
.process(), cred
, owner
))->handle();
392 kern_return_t
ucsp_server_decodeDb(UCSP_ARGS
, DbHandle
*db
,
393 COPY_IN(DLDbFlatIdentifier
, ident
), COPY_IN(AccessCredentials
, cred
), DATA_IN(blob
))
396 relocate(cred
, credBase
, credLength
);
397 relocate(ident
, identBase
, identLength
);
398 *db
= (new KeychainDatabase(*ident
, DATA(blob
).interpretedAs
<DbBlob
>(),
399 connection
.process(), cred
))->handle();
403 kern_return_t
ucsp_server_encodeDb(UCSP_ARGS
, DbHandle db
, DATA_OUT(blob
))
406 DbBlob
*dbBlob
= Server::keychain(db
)->blob(); // memory owned by database
408 *blobLength
= dbBlob
->length();
412 kern_return_t
ucsp_server_releaseDb(UCSP_ARGS
, DbHandle db
)
415 connection
.process().removeReference(*Server::database(db
));
419 kern_return_t
ucsp_server_getDbIndex(UCSP_ARGS
, DbHandle db
, DATA_OUT(index
))
422 OutputData
indexData(index
, indexLength
);
423 Server::keychain(db
)->getDbIndex(indexData
);
427 kern_return_t
ucsp_server_authenticateDb(UCSP_ARGS
, DbHandle db
,
428 COPY_IN(AccessCredentials
, cred
))
431 relocate(cred
, credBase
, credLength
);
432 Server::database(db
)->authenticate(cred
);
436 kern_return_t
ucsp_server_setDbParameters(UCSP_ARGS
, DbHandle db
, DBParameters params
)
439 Server::keychain(db
)->setParameters(params
);
443 kern_return_t
ucsp_server_getDbParameters(UCSP_ARGS
, DbHandle db
, DBParameters
*params
)
446 Server::keychain(db
)->getParameters(*params
);
450 kern_return_t
ucsp_server_changePassphrase(UCSP_ARGS
, DbHandle db
,
451 COPY_IN(AccessCredentials
, cred
))
454 relocate(cred
, credBase
, credLength
);
455 Server::keychain(db
)->changePassphrase(cred
);
459 kern_return_t
ucsp_server_lockDb(UCSP_ARGS
, DbHandle db
)
462 Server::keychain(db
)->lockDb();
466 kern_return_t
ucsp_server_lockAll (UCSP_ARGS
, boolean_t forSleep
)
469 connection
.session().allReferences(&DbCommon::sleepProcessing
);
473 kern_return_t
ucsp_server_unlockDb(UCSP_ARGS
, DbHandle db
)
476 Server::keychain(db
)->unlockDb();
480 kern_return_t
ucsp_server_unlockDbWithPassphrase(UCSP_ARGS
, DbHandle db
, DATA_IN(passphrase
))
483 Server::keychain(db
)->unlockDb(DATA(passphrase
));
487 kern_return_t
ucsp_server_isLocked(UCSP_ARGS
, DbHandle db
, boolean_t
*locked
)
490 *locked
= Server::keychain(db
)->isLocked();
498 kern_return_t
ucsp_server_encodeKey(UCSP_ARGS
, KeyHandle keyh
, DATA_OUT(blob
),
499 boolean_t wantUid
, DATA_OUT(uid
))
502 RefPointer
<Key
> gKey
= Server::key(keyh
);
503 if (KeychainKey
*key
= dynamic_cast<KeychainKey
*>(gKey
.get())) {
504 KeyBlob
*keyBlob
= key
->blob(); // still owned by key
506 *blobLength
= keyBlob
->length();
507 if (wantUid
) { // uid generation is not implemented
508 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED
);
510 *uidLength
= 0; // do not return this
512 } else { // not a KeychainKey
513 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_REFERENCE
);
518 kern_return_t
ucsp_server_decodeKey(UCSP_ARGS
, KeyHandle
*keyh
, CssmKey::Header
*header
,
519 DbHandle db
, DATA_IN(blob
))
522 RefPointer
<Key
> key
= new KeychainKey(*Server::keychain(db
), DATA(blob
).interpretedAs
<KeyBlob
>());
523 key
->returnKey(*keyh
, *header
);
528 kern_return_t
ucsp_server_releaseKey(UCSP_ARGS
, KeyHandle keyh
)
531 RefPointer
<Key
> key
= Server::key(keyh
);
532 key
->database().releaseKey(*key
);
536 kern_return_t
ucsp_server_queryKeySizeInBits(UCSP_ARGS
, KeyHandle keyh
, CSSM_KEY_SIZE
*length
)
539 RefPointer
<Key
> key
= Server::key(keyh
);
540 *length
= key
->database().queryKeySize(*key
);
544 kern_return_t
ucsp_server_getOutputSize(UCSP_ARGS
, CONTEXT_ARGS
, KeyHandle keyh
,
545 uint32 inputSize
, boolean_t encrypt
, uint32
*outputSize
)
548 relocate(context
, contextBase
, attributes
, attrSize
);
549 RefPointer
<Key
> key
= Server::key(keyh
);
550 *outputSize
= key
->database().getOutputSize(context
, *key
, inputSize
, encrypt
);
554 kern_return_t
ucsp_server_getKeyDigest(UCSP_ARGS
, KeyHandle key
, DATA_OUT(digest
))
557 CssmData digestData
= Server::key(key
)->canonicalDigest();
558 *digest
= digestData
.data();
559 *digestLength
= digestData
.length();
566 kern_return_t
ucsp_server_generateRandom(UCSP_ARGS
, uint32 bytes
, DATA_OUT(data
))
569 Allocator
&allocator
= Allocator::standard(Allocator::sensitive
);
570 void *buffer
= allocator
.malloc(bytes
);
571 Server::active().random(buffer
, bytes
);
574 Server::releaseWhenDone(allocator
, buffer
);
580 // Signatures and MACs
582 kern_return_t
ucsp_server_generateSignature(UCSP_ARGS
, CONTEXT_ARGS
, KeyHandle keyh
,
583 CSSM_ALGORITHMS signOnlyAlgorithm
, DATA_IN(data
), DATA_OUT(signature
))
586 relocate(context
, contextBase
, attributes
, attrSize
);
587 RefPointer
<Key
> key
= Server::key(keyh
);
588 OutputData
sigData(signature
, signatureLength
);
589 key
->database().generateSignature(context
, *key
, signOnlyAlgorithm
,
590 DATA(data
), sigData
);
594 kern_return_t
ucsp_server_verifySignature(UCSP_ARGS
, CONTEXT_ARGS
, KeyHandle keyh
,
595 CSSM_ALGORITHMS verifyOnlyAlgorithm
, DATA_IN(data
), DATA_IN(signature
))
598 relocate(context
, contextBase
, attributes
, attrSize
);
599 RefPointer
<Key
> key
= Server::key(keyh
);
600 key
->database().verifySignature(context
, *key
, verifyOnlyAlgorithm
,
601 DATA(data
), DATA(signature
));
605 kern_return_t
ucsp_server_generateMac(UCSP_ARGS
, CONTEXT_ARGS
, KeyHandle keyh
,
606 DATA_IN(data
), DATA_OUT(mac
))
609 relocate(context
, contextBase
, attributes
, attrSize
);
610 RefPointer
<Key
> key
= Server::key(keyh
);
611 OutputData
macData(mac
, macLength
);
612 key
->database().generateMac(context
, *key
, DATA(data
), macData
);
616 kern_return_t
ucsp_server_verifyMac(UCSP_ARGS
, CONTEXT_ARGS
, KeyHandle keyh
,
617 DATA_IN(data
), DATA_IN(mac
))
620 relocate(context
, contextBase
, attributes
, attrSize
);
621 RefPointer
<Key
> key
= Server::key(keyh
);
622 key
->database().verifyMac(context
, *key
, DATA(data
), DATA(mac
));
628 // Encryption/Decryption
630 kern_return_t
ucsp_server_encrypt(UCSP_ARGS
, CONTEXT_ARGS
, KeyHandle keyh
,
631 DATA_IN(clear
), DATA_OUT(cipher
))
634 relocate(context
, contextBase
, attributes
, attrSize
);
635 RefPointer
<Key
> key
= Server::key(keyh
);
636 OutputData
cipherOut(cipher
, cipherLength
);
637 key
->database().encrypt(context
, *key
, DATA(clear
), cipherOut
);
641 kern_return_t
ucsp_server_decrypt(UCSP_ARGS
, CONTEXT_ARGS
, KeyHandle keyh
,
642 DATA_IN(cipher
), DATA_OUT(clear
))
645 relocate(context
, contextBase
, attributes
, attrSize
);
646 RefPointer
<Key
> key
= Server::key(keyh
);
647 OutputData
clearOut(clear
, clearLength
);
648 key
->database().decrypt(context
, *key
, DATA(cipher
), clearOut
);
656 kern_return_t
ucsp_server_generateKey(UCSP_ARGS
, DbHandle db
, CONTEXT_ARGS
,
657 COPY_IN(AccessCredentials
, cred
), COPY_IN(AclEntryPrototype
, owner
),
658 uint32 usage
, uint32 attrs
, KeyHandle
*newKey
, CssmKey::Header
*newHeader
)
661 relocate(context
, contextBase
, attributes
, attrSize
);
662 relocate(cred
, credBase
, credLength
);
663 relocate(owner
, ownerBase
, ownerLength
);
664 //@@@ preliminary interpretation - will get "type handle"
665 RefPointer
<Database
> database
= Server::optionalDatabase(db
);
667 database
->generateKey(context
, cred
, owner
, usage
, attrs
, key
);
668 key
->returnKey(*newKey
, *newHeader
);
673 kern_return_t
ucsp_server_generateKeyPair(UCSP_ARGS
, DbHandle db
, CONTEXT_ARGS
,
674 COPY_IN(AccessCredentials
, cred
), COPY_IN(AclEntryPrototype
, owner
),
675 uint32 pubUsage
, uint32 pubAttrs
, uint32 privUsage
, uint32 privAttrs
,
676 KeyHandle
*pubKey
, CssmKey::Header
*pubHeader
, KeyHandle
*privKey
, CssmKey::Header
*privHeader
)
679 relocate(context
, contextBase
, attributes
, attrSize
);
680 relocate(cred
, credBase
, credLength
);
681 relocate(owner
, ownerBase
, ownerLength
);
682 RefPointer
<Key
> pub
, priv
;
683 RefPointer
<Database
> database
= Server::optionalDatabase(db
);
684 database
->generateKey(context
, cred
, owner
,
685 pubUsage
, pubAttrs
, privUsage
, privAttrs
, pub
, priv
);
686 pub
->returnKey(*pubKey
, *pubHeader
);
688 priv
->returnKey(*privKey
, *privHeader
);
696 // This is a bit strained; the incoming 'param' value may have structure
697 // and needs to be handled on a per-algorithm basis, which means we have to
698 // know which key derivation algorithms we support for passing to our CSP(s).
699 // The default behavior is to handle "flat" data blobs, which is as good
700 // a default as we can manage.
701 // NOTE: The param-specific handling must be synchronized with the client library
702 // code (in sstransit.h).
704 kern_return_t
ucsp_server_deriveKey(UCSP_ARGS
, DbHandle db
, CONTEXT_ARGS
, KeyHandle keyh
,
705 COPY_IN(AccessCredentials
, cred
), COPY_IN(AclEntryPrototype
, owner
),
706 COPY_IN(void, paramInputData
), DATA_OUT(paramOutput
),
707 uint32 usage
, uint32 attrs
, KeyHandle
*newKey
, CssmKey::Header
*newHeader
)
710 relocate(context
, contextBase
, attributes
, attrSize
);
711 relocate(cred
, credBase
, credLength
);
712 relocate(owner
, ownerBase
, ownerLength
);
714 // munge together the incoming 'param' value according to algorithm
716 switch (context
.algorithm()) {
717 case CSSM_ALGID_PKCS5_PBKDF2
:
718 relocate((CSSM_PKCS5_PBKDF2_PARAMS
*)paramInputData
,
719 (CSSM_PKCS5_PBKDF2_PARAMS
*)paramInputDataBase
,
720 paramInputDataLength
);
721 param
= CssmData(paramInputData
, sizeof(CSSM_PKCS5_PBKDF2_PARAMS
));
724 param
= CssmData(paramInputData
, paramInputDataLength
);
727 RefPointer
<Database
> database
= Server::optionalDatabase(db
);
728 RefPointer
<Key
> theKey
= database
->deriveKey(context
, Server::optionalKey(keyh
),
729 cred
, owner
, ¶m
, usage
, attrs
);
730 theKey
->returnKey(*newKey
, *newHeader
);
732 if (param
.length()) {
733 if (!param
) // CSP screwed up
734 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR
);
735 if (paramInputDataLength
) // using incoming buffer; make a copy
736 param
= CssmAutoData(Server::csp().allocator(), param
).release();
737 OutputData(paramOutput
, paramOutputLength
) = param
; // return the data
744 // Key wrapping and unwrapping
746 kern_return_t
ucsp_server_wrapKey(UCSP_ARGS
, CONTEXT_ARGS
, KeyHandle keyh
,
747 COPY_IN(AccessCredentials
, cred
), KeyHandle keyToBeWrappedh
,
748 DATA_IN(descriptiveData
), CssmKey
*wrappedKey
, DATA_OUT(keyData
))
751 relocate(context
, contextBase
, attributes
, attrSize
);
752 relocate(cred
, credBase
, credLength
);
753 RefPointer
<Key
> inputKey
= Server::key(keyToBeWrappedh
);
754 inputKey
->database().wrapKey(context
, Server::optionalKey(keyh
),
755 *inputKey
, cred
, DATA(descriptiveData
), *wrappedKey
);
756 // transmit key data back as a separate blob
757 *keyData
= wrappedKey
->data();
758 *keyDataLength
= wrappedKey
->length();
759 Server::releaseWhenDone(*keyData
);
764 kern_return_t
ucsp_server_unwrapKey(UCSP_ARGS
, DbHandle db
, CONTEXT_ARGS
, KeyHandle keyh
,
765 COPY_IN(AccessCredentials
, cred
), COPY_IN(AclEntryPrototype
, owner
),
766 KeyHandle publicKeyh
, CssmKey wrappedKey
, DATA_IN(wrappedKeyData
),
767 uint32 usage
, uint32 attr
, DATA_OUT(descriptiveData
),
768 KeyHandle
*newKey
, CssmKey::Header
*newHeader
)
771 relocate(context
, contextBase
, attributes
, attrSize
);
773 wrappedKey
.KeyData
= DATA(wrappedKeyData
);
774 relocate(cred
, credBase
, credLength
);
775 relocate(owner
, ownerBase
, ownerLength
);
776 RefPointer
<Database
> database
= Server::optionalDatabase(db
);
777 CssmData descriptiveDatas
;
778 RefPointer
<Key
> theKey
= database
->unwrapKey(context
, Server::optionalKey(keyh
),
779 cred
, owner
, usage
, attr
, wrappedKey
,
780 Server::optionalKey(publicKeyh
), &descriptiveDatas
);
781 theKey
->returnKey(*newKey
, *newHeader
);
783 *descriptiveData
= descriptiveDatas
.data();
784 *descriptiveDataLength
= descriptiveDatas
.length();
785 Server::releaseWhenDone(*descriptiveData
);
792 // Watch out for the memory-management tap-dance.
794 kern_return_t
ucsp_server_getOwner(UCSP_ARGS
, AclKind kind
, KeyHandle key
,
795 COPY_OUT(AclOwnerPrototype
, ownerOut
))
798 AclOwnerPrototype owner
;
799 Server::aclBearer(kind
, key
).cssmGetOwner(owner
); // allocates memory in owner
800 Copier
<AclOwnerPrototype
> owners(&owner
, Allocator::standard()); // make flat copy
801 { ChunkFreeWalker free
; walk(free
, owner
); } // release chunked original
802 *ownerOutLength
= owners
.length();
803 flips(owners
.value(), ownerOut
, ownerOutBase
);
804 Server::releaseWhenDone(owners
.keep()); // throw flat copy out when done
808 kern_return_t
ucsp_server_setOwner(UCSP_ARGS
, AclKind kind
, KeyHandle key
,
809 COPY_IN(AccessCredentials
, cred
), COPY_IN(AclOwnerPrototype
, owner
))
812 relocate(cred
, credBase
, credLength
);
813 relocate(owner
, ownerBase
, ownerLength
);
814 Server::aclBearer(kind
, key
).cssmChangeOwner(*owner
, cred
);
818 kern_return_t
ucsp_server_getAcl(UCSP_ARGS
, AclKind kind
, KeyHandle key
,
819 boolean_t haveTag
, const char *tag
,
820 uint32
*countp
, COPY_OUT(AclEntryInfo
, acls
))
824 AclEntryInfo
*aclList
;
825 Server::aclBearer(kind
, key
).cssmGetAcl(haveTag
? tag
: NULL
, count
, aclList
);
827 Copier
<AclEntryInfo
> aclsOut(AclEntryInfo::overlay(aclList
), count
); // make flat copy
829 { // release the chunked memory originals
830 ChunkFreeWalker free
;
831 for (uint32 n
= 0; n
< count
; n
++)
832 walk(free
, aclList
[n
]);
834 // release the memory allocated for the list itself when we are done
835 Allocator::standard().free (aclList
);
838 // set result (note: this is *almost* flips(), but on an array)
839 *aclsLength
= aclsOut
.length();
840 *acls
= *aclsBase
= aclsOut
;
843 for (uint32 n
= 0; n
< count
; n
++)
846 Flippers::flip(*aclsBase
);
848 Server::releaseWhenDone(aclsOut
.keep());
852 kern_return_t
ucsp_server_changeAcl(UCSP_ARGS
, AclKind kind
, KeyHandle key
,
853 COPY_IN(AccessCredentials
, cred
), CSSM_ACL_EDIT_MODE mode
, CSSM_ACL_HANDLE handle
,
854 COPY_IN(AclEntryInput
, acl
))
857 relocate(cred
, credBase
, credLength
);
858 relocate(acl
, aclBase
, aclLength
);
859 Server::aclBearer(kind
, key
).cssmChangeAcl(AclEdit(mode
, handle
, acl
), cred
);
865 // Database key management.
866 // ExtractMasterKey looks vaguely like a key derivation operation, and is in fact
867 // presented by the CSPDL's CSSM layer as such.
869 kern_return_t
ucsp_server_extractMasterKey(UCSP_ARGS
, DbHandle db
, CONTEXT_ARGS
, DbHandle sourceDb
,
870 COPY_IN(AccessCredentials
, cred
), COPY_IN(AclEntryPrototype
, owner
),
871 uint32 usage
, uint32 attrs
, KeyHandle
*newKey
, CssmKey::Header
*newHeader
)
874 context
.postIPC(contextBase
, attributes
);
875 relocate(cred
, credBase
, credLength
);
876 relocate(owner
, ownerBase
, ownerLength
);
877 RefPointer
<KeychainDatabase
> keychain
= Server::keychain(sourceDb
);
878 RefPointer
<Key
> masterKey
= keychain
->extractMasterKey(*Server::optionalDatabase(db
),
879 cred
, owner
, usage
, attrs
);
880 masterKey
->returnKey(*newKey
, *newHeader
);
887 // Authorization subsystem support
889 kern_return_t
ucsp_server_authorizationCreate(UCSP_ARGS
,
890 COPY_IN(AuthorizationItemSet
, inRights
),
892 COPY_IN(AuthorizationItemSet
, inEnvironment
),
893 AuthorizationBlob
*authorization
)
896 relocate(inRights
, inRightsBase
, inRightsLength
);
897 relocate(inEnvironment
, inEnvironmentBase
, inEnvironmentLength
);
898 Authorization::AuthItemSet
rights(inRights
), environment(inEnvironment
);
900 *rcode
= connection
.process().session().authCreate(rights
, environment
,
901 flags
, *authorization
, securityToken
);
905 kern_return_t
ucsp_server_authorizationRelease(UCSP_ARGS
,
906 AuthorizationBlob authorization
, uint32 flags
)
909 connection
.process().session().authFree(authorization
, flags
);
913 kern_return_t
ucsp_server_authorizationCopyRights(UCSP_ARGS
,
914 AuthorizationBlob authorization
,
915 COPY_IN(AuthorizationItemSet
, inRights
),
917 COPY_IN(AuthorizationItemSet
, inEnvironment
),
918 COPY_OUT(AuthorizationItemSet
, result
))
921 relocate(inRights
, inRightsBase
, inRightsLength
);
922 relocate(inEnvironment
, inEnvironmentBase
, inEnvironmentLength
);
923 Authorization::AuthItemSet
rights(inRights
), environment(inEnvironment
), grantedRights
;
924 *rcode
= connection
.process().session().authGetRights(authorization
,
925 rights
, environment
, flags
, grantedRights
);
926 if (result
&& resultLength
)
929 grantedRights
.copy(*result
, resultSize
);
930 *resultLength
= resultSize
;
931 *resultBase
= *result
;
932 flips(*result
, result
, resultBase
);
933 Server::releaseWhenDone(*result
);
938 kern_return_t
ucsp_server_authorizationCopyInfo(UCSP_ARGS
,
939 AuthorizationBlob authorization
,
940 AuthorizationString tag
,
941 COPY_OUT(AuthorizationItemSet
, info
))
944 Authorization::AuthItemSet infoSet
;
945 *info
= *infoBase
= NULL
;
947 *rcode
= connection
.process().session().authGetInfo(authorization
,
948 tag
[0] ? tag
: NULL
, infoSet
);
949 if (*rcode
== noErr
) {
951 infoSet
.copy(*info
, infoSize
);
952 *infoLength
= infoSize
;
954 flips(*info
, info
, infoBase
);
955 Server::releaseWhenDone(*info
);
960 kern_return_t
ucsp_server_authorizationExternalize(UCSP_ARGS
,
961 AuthorizationBlob authorization
, AuthorizationExternalForm
*extForm
)
964 *rcode
= connection
.process().session().authExternalize(authorization
, *extForm
);
968 kern_return_t
ucsp_server_authorizationInternalize(UCSP_ARGS
,
969 AuthorizationExternalForm extForm
, AuthorizationBlob
*authorization
)
972 *rcode
= connection
.process().session().authInternalize(extForm
, *authorization
);
978 // Session management subsystem
980 kern_return_t
ucsp_server_getSessionInfo(UCSP_ARGS
,
981 SecuritySessionId
*sessionId
, SessionAttributeBits
*attrs
)
984 Session
&session
= Session::find(*sessionId
);
985 *sessionId
= session
.handle();
986 *attrs
= session
.attributes();
990 kern_return_t
ucsp_server_setupSession(UCSP_ARGS
,
991 SessionCreationFlags flags
, SessionAttributeBits attrs
)
994 Session::setup(flags
, attrs
);
1000 // Notification core subsystem
1002 kern_return_t
ucsp_server_requestNotification(UCSP_ARGS
, mach_port_t receiver
, uint32 domain
, uint32 events
)
1005 connection
.process().requestNotifications(receiver
, domain
, events
);
1009 kern_return_t
ucsp_server_stopNotification(UCSP_ARGS
, mach_port_t receiver
)
1012 connection
.process().stopNotifications(receiver
);
1016 kern_return_t
ucsp_server_postNotification(UCSP_ARGS
, uint32 domain
, uint32 event
, DATA_IN(data
))
1019 Listener::notify(domain
, event
, DATA(data
));
1025 // AuthorizationDB modification
1027 kern_return_t
ucsp_server_authorizationdbGet(UCSP_ARGS
, const char *rightname
, DATA_OUT(rightDefinition
))
1030 CFDictionaryRef rightDict
;
1032 *rcode
= connection
.process().session().authorizationdbGet(rightname
, &rightDict
);
1034 if (!*rcode
&& rightDict
)
1036 CFRef
<CFDataRef
> data(CFPropertyListCreateXMLData (NULL
, rightDict
));
1037 CFRelease(rightDict
);
1039 return errAuthorizationInternal
;
1041 // @@@ copy data to avoid having to do a delayed cfrelease
1042 mach_msg_type_number_t length
= CFDataGetLength(data
);
1043 void *xmlData
= Allocator::standard().malloc(length
);
1044 memcpy(xmlData
, CFDataGetBytePtr(data
), length
);
1045 Server::releaseWhenDone(xmlData
);
1047 *rightDefinition
= xmlData
;
1048 *rightDefinitionLength
= length
;
1053 kern_return_t
ucsp_server_authorizationdbSet(UCSP_ARGS
, AuthorizationBlob authorization
, const char *rightname
, DATA_IN(rightDefinition
))
1056 CFRef
<CFDataRef
> data(CFDataCreate(NULL
, (UInt8
*)rightDefinition
, rightDefinitionLength
));
1059 return errAuthorizationInternal
;
1061 CFRef
<CFDictionaryRef
> rightDefinition(static_cast<CFDictionaryRef
>(CFPropertyListCreateFromXMLData(NULL
, data
, kCFPropertyListImmutable
, NULL
)));
1063 if (!rightDefinition
|| (CFGetTypeID(rightDefinition
) != CFDictionaryGetTypeID()))
1064 return errAuthorizationInternal
;
1066 *rcode
= connection
.process().session().authorizationdbSet(authorization
, rightname
, rightDefinition
);
1071 kern_return_t
ucsp_server_authorizationdbRemove(UCSP_ARGS
, AuthorizationBlob authorization
, const char *rightname
)
1074 *rcode
= connection
.process().session().authorizationdbRemove(authorization
, rightname
);
1080 // Miscellaneous administrative functions
1082 kern_return_t
ucsp_server_addCodeEquivalence(UCSP_ARGS
, DATA_IN(oldHash
), DATA_IN(newHash
),
1083 const char *name
, boolean_t forSystem
)
1086 Server::codeSignatures().addLink(DATA(oldHash
), DATA(newHash
), name
, forSystem
);
1090 kern_return_t
ucsp_server_removeCodeEquivalence(UCSP_ARGS
, DATA_IN(hash
),
1091 const char *name
, boolean_t forSystem
)
1094 Server::codeSignatures().removeLink(DATA(hash
), name
, forSystem
);
1098 kern_return_t
ucsp_server_setAlternateSystemRoot(UCSP_ARGS
, const char *root
)
1102 if (connection
.process().uid() != 0)
1103 CssmError::throwMe(CSSM_ERRCODE_OS_ACCESS_DENIED
);
1105 Server::codeSignatures().open((string(root
) + EQUIVALENCEDBPATH
).c_str());