2 * Copyright (c) 2000-2008,2011-2013 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
26 // transition - SecurityServer client library transition code.
28 // These are the functions that implement CssmClient methods in terms of
29 // MIG IPC client calls, plus their supporting machinery.
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.
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.
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).
50 #include "sstransit.h"
51 #include <security_cdsa_client/cspclient.h>
53 #include <securityd_client/xdr_auth.h>
54 #include <securityd_client/xdr_cssm.h>
55 #include <securityd_client/xdr_dldb.h>
58 namespace SecurityServer
{
60 using MachPlusPlus::check
;
61 using MachPlusPlus::VMGuard
;
64 // Common database interface
66 void ClientSession::authenticateDb(DbHandle db
, CSSM_DB_ACCESS_TYPE type
,
67 const AccessCredentials
*cred
)
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()));
76 void ClientSession::releaseDb(DbHandle db
)
78 IPC(ucsp_client_releaseDb(UCSP_ARGS
, db
));
83 // External database interface
85 DbHandle
ClientSession::openToken(uint32 ssid
, const AccessCredentials
*cred
,
89 DatabaseAccessCredentials
creds(cred
, internalAllocator
);
90 CopyIn
copycreds(creds
.value(), reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACCESS_CREDENTIALS
));
92 IPC(ucsp_client_openToken(UCSP_ARGS
, ssid
, name
? name
: "", copycreds
.data(), copycreds
.length(), &db
));
98 RecordHandle
ClientSession::insertRecord(DbHandle db
,
99 CSSM_DB_RECORDTYPE recordType
,
100 const CssmDbRecordAttributeData
*attributes
,
101 const CssmData
*data
)
104 CopyIn
db_record_attr_data(attributes
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA
));
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
));
112 void ClientSession::deleteRecord(DbHandle db
, RecordHandle record
)
114 IPC(ucsp_client_deleteRecord(UCSP_ARGS
, db
, record
));
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
)
124 CopyIn
db_record_attr_data(attributes
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA
));
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(),
127 data
!= NULL
, OPTIONALDATA(data
), modifyMode
));
131 void copy_back_attribute_return_data(CssmDbRecordAttributeData
*dest_attrs
, CssmDbRecordAttributeData
*source_attrs
, Allocator
&returnAllocator
)
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());
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
);
143 RecordHandle
ClientSession::findFirst(DbHandle db
,
144 const CssmQuery
&inQuery
,
145 SearchHandle
&hSearch
,
146 CssmDbRecordAttributeData
*attributes
,
147 CssmData
*data
, KeyHandle
&hKey
)
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;
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
));
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
);
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
);
173 RecordHandle
ClientSession::findNext(SearchHandle hSearch
,
174 CssmDbRecordAttributeData
*attributes
,
175 CssmData
*data
, KeyHandle
&hKey
)
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;
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
));
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
);
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
);
200 void ClientSession::findRecordHandle(RecordHandle hRecord
,
201 CssmDbRecordAttributeData
*attributes
,
202 CssmData
*data
, KeyHandle
&hKey
)
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
));
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
);
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
);
222 void ClientSession::releaseSearch(SearchHandle searchHandle
)
224 IPC(ucsp_client_releaseSearch(UCSP_ARGS
, searchHandle
));
228 void ClientSession::releaseRecord(RecordHandle record
)
230 IPC(ucsp_client_releaseRecord(UCSP_ARGS
, record
));
233 void ClientSession::getDbName(DbHandle db
, string
&name
)
235 char result
[PATH_MAX
];
237 IPC(ucsp_client_getDbName(UCSP_ARGS
, db
, result
));
242 void ClientSession::setDbName(DbHandle db
, const string
&name
)
244 IPC(ucsp_client_setDbName(UCSP_ARGS
, db
, name
.c_str()));
249 // Internal database management
251 DbHandle
ClientSession::createDb(const DLDbIdentifier
&dbId
,
252 const AccessCredentials
*cred
, const AclEntryInput
*owner
,
253 const DBParameters
¶ms
)
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
));
263 IPC(ucsp_client_createDb(UCSP_ARGS
, &db
, id
.data(), id
.length(), copycreds
.data(), copycreds
.length(), proto
.data(), proto
.length(), params
));
268 DbHandle
ClientSession::cloneDb(const DLDbIdentifier
&newDbId
, DbHandle srcDb
) {
269 DataWalkers::DLDbFlatIdentifier
ident(newDbId
);
270 CopyIn
id(&ident
, reinterpret_cast<xdrproc_t
>(xdr_DLDbFlatIdentifier
));
273 IPC(ucsp_client_cloneDb(UCSP_ARGS
, srcDb
, id
.data(), id
.length(), &db
));
277 DbHandle
ClientSession::recodeDbForSync(DbHandle dbToClone
,
282 IPC(ucsp_client_recodeDbForSync(UCSP_ARGS
, dbToClone
, srcDb
, &newDb
));
287 DbHandle
ClientSession::recodeDbToVersion(uint32 newVersion
, DbHandle srcDb
)
291 IPC(ucsp_client_recodeDbToVersion(UCSP_ARGS
, newVersion
, srcDb
, &newDb
));
296 void ClientSession::recodeFinished(DbHandle db
)
298 IPC(ucsp_client_recodeFinished(UCSP_ARGS
, db
));
301 DbHandle
ClientSession::authenticateDbsForSync(const CssmData
&dbHandleArray
,
302 const CssmData
&agentData
)
306 IPC(ucsp_client_authenticateDbsForSync(UCSP_ARGS
, DATA(dbHandleArray
), DATA(agentData
), &newDb
));
311 void ClientSession::commitDbForSync(DbHandle srcDb
, DbHandle cloneDb
,
312 CssmData
&blob
, Allocator
&alloc
)
314 DataOutput
outBlob(blob
, alloc
);
315 IPC(ucsp_client_commitDbForSync(UCSP_ARGS
, srcDb
, cloneDb
, DATA_OUT(outBlob
)));
318 DbHandle
ClientSession::decodeDb(const DLDbIdentifier
&dbId
,
319 const AccessCredentials
*cred
, const CssmData
&blob
)
321 // XXX/64 fold into one translation
322 DatabaseAccessCredentials
credentials(cred
, internalAllocator
);
323 CopyIn
creds(credentials
.value(), reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACCESS_CREDENTIALS
));
324 // XXX/64 fold into one translation
325 DataWalkers::DLDbFlatIdentifier
ident(dbId
);
326 CopyIn
id(&ident
, reinterpret_cast<xdrproc_t
>(xdr_DLDbFlatIdentifier
));
329 IPC(ucsp_client_decodeDb(UCSP_ARGS
, &db
, id
.data(), id
.length(), creds
.data(), creds
.length(), DATA(blob
)));
334 void ClientSession::encodeDb(DbHandle db
, CssmData
&blob
, Allocator
&alloc
)
336 DataOutput
outBlob(blob
, alloc
);
337 IPC(ucsp_client_encodeDb(UCSP_ARGS
, db
, DATA_OUT(outBlob
)));
340 void ClientSession::setDbParameters(DbHandle db
, const DBParameters
¶ms
)
342 IPC(ucsp_client_setDbParameters(UCSP_ARGS
, db
, params
));
345 void ClientSession::getDbParameters(DbHandle db
, DBParameters
¶ms
)
347 IPC(ucsp_client_getDbParameters(UCSP_ARGS
, db
, ¶ms
));
350 void ClientSession::changePassphrase(DbHandle db
, const AccessCredentials
*cred
)
352 CopyIn
creds(cred
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACCESS_CREDENTIALS
));
353 IPC(ucsp_client_changePassphrase(UCSP_ARGS
, db
, creds
.data(), creds
.length()));
357 void ClientSession::lock(DbHandle db
)
359 IPC(ucsp_client_authenticateDb(UCSP_ARGS
, db
, CSSM_DB_ACCESS_RESET
, NULL
, 0));
360 //@@@VIRTUAL IPC(ucsp_client_lockDb(UCSP_ARGS, db));
363 void ClientSession::lockAll (bool forSleep
)
365 IPC(ucsp_client_lockAll (UCSP_ARGS
, forSleep
));
368 void ClientSession::unlock(DbHandle db
)
370 IPC(ucsp_client_unlockDb(UCSP_ARGS
, db
));
373 void ClientSession::unlock(DbHandle db
, const CssmData
&passphrase
)
375 IPC(ucsp_client_unlockDbWithPassphrase(UCSP_ARGS
, db
, DATA(passphrase
)));
378 void ClientSession::stashDb(DbHandle db
)
380 IPC(ucsp_client_stashDb(UCSP_ARGS
, db
));
383 void ClientSession::stashDbCheck(DbHandle db
)
385 IPC(ucsp_client_stashDbCheck(UCSP_ARGS
, db
));
388 bool ClientSession::isLocked(DbHandle db
)
391 IPC(ucsp_client_isLocked(UCSP_ARGS
, db
, &locked
));
395 void ClientSession::verifyKeyStorePassphrase(uint32_t retries
)
397 IPC(ucsp_client_verifyKeyStorePassphrase(UCSP_ARGS
, retries
));
400 void ClientSession::resetKeyStorePassphrase(const CssmData
&passphrase
)
402 IPC(ucsp_client_resetKeyStorePassphrase(UCSP_ARGS
, DATA(passphrase
)));
405 void ClientSession::changeKeyStorePassphrase()
407 IPC(ucsp_client_changeKeyStorePassphrase(UCSP_ARGS
));
413 void ClientSession::encodeKey(KeyHandle key
, CssmData
&blob
,
414 KeyUID
*uid
, Allocator
&alloc
)
416 // Not really used as output
417 DataOutput
oBlob(blob
, alloc
);
419 mach_msg_type_number_t uidLength
;
421 IPC(ucsp_client_encodeKey(UCSP_ARGS
, key
, oBlob
.data(), oBlob
.length(),
422 (uid
!= NULL
), &uidp
, &uidLength
));
424 // return key uid if requested
426 assert(uidLength
== sizeof(KeyUID
));
427 memcpy(uid
, uidp
, sizeof(KeyUID
));
431 KeyHandle
ClientSession::decodeKey(DbHandle db
, const CssmData
&blob
, CssmKey::Header
&header
)
435 mach_msg_type_number_t keyHeaderDataLength
;
437 IPC(ucsp_client_decodeKey(UCSP_ARGS
, &key
, &keyHeaderData
, &keyHeaderDataLength
, db
, blob
.data(), (mach_msg_type_number_t
)blob
.length()));
439 CopyOut
wrappedKeyHeaderXDR(keyHeaderData
, keyHeaderDataLength
+ sizeof(CSSM_KEYHEADER
), reinterpret_cast<xdrproc_t
>(xdr_CSSM_KEYHEADER_PTR
), true);
440 header
= *static_cast<CssmKey::Header
*>(reinterpret_cast<CSSM_KEYHEADER
*>(wrappedKeyHeaderXDR
.data()));
445 // keychain synchronization
446 void ClientSession::recodeKey(DbHandle oldDb
, KeyHandle key
, DbHandle newDb
,
449 DataOutput
outBlob(blob
, returnAllocator
);
450 IPC(ucsp_client_recodeKey(UCSP_ARGS
, oldDb
, key
, newDb
, DATA_OUT(outBlob
)));
453 void ClientSession::releaseKey(KeyHandle key
)
455 IPC(ucsp_client_releaseKey(UCSP_ARGS
, key
));
459 CssmKeySize
ClientSession::queryKeySizeInBits(KeyHandle key
)
462 IPC(ucsp_client_queryKeySizeInBits(UCSP_ARGS
, key
, &length
));
467 uint32
ClientSession::getOutputSize(const Context
&context
, KeyHandle key
,
468 uint32 inputSize
, bool encrypt
)
470 CopyIn
ctxcopy(&context
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_CONTEXT
));
473 IPC(ucsp_client_getOutputSize(UCSP_ARGS
, ctxcopy
.data(), ctxcopy
.length(), key
, inputSize
, encrypt
, &outputSize
));
479 // Random number generation.
480 // This interfaces to the secure RNG inside the SecurityServer; it does not access
481 // a PRNG in its CSP. If you need a reproducible PRNG, attach a local CSP and use it.
482 // Note that this function does not allocate a buffer; it always fills the buffer provided.
484 void ClientSession::generateRandom(const Security::Context
&context
, CssmData
&data
, Allocator
&alloc
)
486 CopyIn
ctxcopy(&context
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_CONTEXT
));
487 DataOutput
result(data
, alloc
);
489 IPC(ucsp_client_generateRandom(UCSP_ARGS
, 0, ctxcopy
.data(), ctxcopy
.length(), DATA_OUT(result
)));
494 // Signatures and MACs
496 void ClientSession::generateSignature(const Context
&context
, KeyHandle key
,
497 const CssmData
&data
, CssmData
&signature
, Allocator
&alloc
, CSSM_ALGORITHMS signOnlyAlgorithm
)
499 CopyIn
ctxcopy(&context
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_CONTEXT
));
500 DataOutput
sig(signature
, alloc
);
502 IPCKEY(ucsp_client_generateSignature(UCSP_ARGS
, ctxcopy
.data(), ctxcopy
.length(), key
, signOnlyAlgorithm
,
503 DATA(data
), DATA_OUT(sig
)),
504 key
, CSSM_ACL_AUTHORIZATION_SIGN
);
507 void ClientSession::verifySignature(const Context
&context
, KeyHandle key
,
508 const CssmData
&data
, const CssmData
&signature
, CSSM_ALGORITHMS verifyOnlyAlgorithm
)
510 CopyIn
ctxcopy(&context
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_CONTEXT
));
512 IPC(ucsp_client_verifySignature(UCSP_ARGS
, ctxcopy
.data(), ctxcopy
.length(), key
, verifyOnlyAlgorithm
, DATA(data
), DATA(signature
)));
516 void ClientSession::generateMac(const Context
&context
, KeyHandle key
,
517 const CssmData
&data
, CssmData
&signature
, Allocator
&alloc
)
519 CopyIn
ctxcopy(&context
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_CONTEXT
));
520 DataOutput
sig(signature
, alloc
);
522 IPCKEY(ucsp_client_generateMac(UCSP_ARGS
, ctxcopy
.data(), ctxcopy
.length(), key
, DATA(data
), DATA_OUT(sig
)),
523 key
, CSSM_ACL_AUTHORIZATION_MAC
);
526 void ClientSession::verifyMac(const Context
&context
, KeyHandle key
,
527 const CssmData
&data
, const CssmData
&signature
)
529 CopyIn
ctxcopy(&context
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_CONTEXT
));
531 IPCKEY(ucsp_client_verifyMac(UCSP_ARGS
, ctxcopy
.data(), ctxcopy
.length(), key
,
532 DATA(data
), DATA(signature
)),
533 key
, CSSM_ACL_AUTHORIZATION_MAC
);
538 // Encryption/Decryption
541 void ClientSession::encrypt(const Context
&context
, KeyHandle key
,
542 const CssmData
&clear
, CssmData
&cipher
, Allocator
&alloc
)
544 CopyIn
ctxcopy(&context
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_CONTEXT
));
545 DataOutput
cipherOut(cipher
, alloc
);
546 IPCKEY(ucsp_client_encrypt(UCSP_ARGS
, ctxcopy
.data(), ctxcopy
.length(), key
, DATA(clear
), DATA_OUT(cipherOut
)),
547 key
, CSSM_ACL_AUTHORIZATION_ENCRYPT
);
550 void ClientSession::decrypt(const Context
&context
, KeyHandle key
,
551 const CssmData
&cipher
, CssmData
&clear
, Allocator
&alloc
)
553 CopyIn
ctxcopy(&context
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_CONTEXT
));
554 DataOutput
clearOut(clear
, alloc
);
556 IPCKEY(ucsp_client_decrypt(UCSP_ARGS
, ctxcopy
.data(), ctxcopy
.length(), key
, DATA(cipher
), DATA_OUT(clearOut
)),
557 key
, CSSM_ACL_AUTHORIZATION_DECRYPT
);
564 void ClientSession::generateKey(DbHandle db
, const Context
&context
, uint32 keyUsage
, uint32 keyAttr
,
565 const AccessCredentials
*cred
, const AclEntryInput
*owner
,
566 KeyHandle
&newKey
, CssmKey::Header
&newHeader
)
568 CopyIn
ctxcopy(&context
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_CONTEXT
));
569 CopyIn
creds(cred
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACCESS_CREDENTIALS
));
570 CopyIn
proto(owner
? &owner
->proto() : NULL
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACL_ENTRY_PROTOTYPE
));
572 mach_msg_type_number_t keyHeaderDataLength
;
574 IPC(ucsp_client_generateKey(UCSP_ARGS
, db
, ctxcopy
.data(), ctxcopy
.length(),
575 creds
.data(), creds
.length(), proto
.data(), proto
.length(),
576 keyUsage
, keyAttr
, &newKey
, &keyHeaderData
, &keyHeaderDataLength
));
578 CopyOut
wrappedKeyHeaderXDR(keyHeaderData
, keyHeaderDataLength
+ sizeof(CSSM_KEYHEADER
), reinterpret_cast<xdrproc_t
>(xdr_CSSM_KEYHEADER_PTR
), true);
579 newHeader
= *static_cast<CssmKey::Header
*>(reinterpret_cast<CSSM_KEYHEADER
*>(wrappedKeyHeaderXDR
.data()));
582 void ClientSession::generateKey(DbHandle db
, const Context
&context
,
583 uint32 pubKeyUsage
, uint32 pubKeyAttr
,
584 uint32 privKeyUsage
, uint32 privKeyAttr
,
585 const AccessCredentials
*cred
, const AclEntryInput
*owner
,
586 KeyHandle
&pubKey
, CssmKey::Header
&pubHeader
,
587 KeyHandle
&privKey
, CssmKey::Header
&privHeader
)
589 CopyIn
ctxcopy(&context
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_CONTEXT
));
590 CopyIn
creds(cred
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACCESS_CREDENTIALS
));
591 CopyIn
proto(owner
? &owner
->proto() : NULL
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACL_ENTRY_PROTOTYPE
));
592 void *pubKeyHeaderData
, *privKeyHeaderData
;
593 mach_msg_type_number_t pubKeyHeaderDataLength
, privKeyHeaderDataLength
;
595 IPC(ucsp_client_generateKeyPair(UCSP_ARGS
, db
, ctxcopy
.data(), ctxcopy
.length(),
596 creds
.data(), creds
.length(), proto
.data(), proto
.length(),
597 pubKeyUsage
, pubKeyAttr
, privKeyUsage
, privKeyAttr
,
598 &pubKey
, &pubKeyHeaderData
, &pubKeyHeaderDataLength
,
599 &privKey
, &privKeyHeaderData
, &privKeyHeaderDataLength
));
601 CopyOut
wrappedPubKeyHeaderXDR(pubKeyHeaderData
, pubKeyHeaderDataLength
+ sizeof(CSSM_KEYHEADER
), reinterpret_cast<xdrproc_t
>(xdr_CSSM_KEYHEADER_PTR
), true);
602 pubHeader
= *static_cast<CssmKey::Header
*>(reinterpret_cast<CSSM_KEYHEADER
*>(wrappedPubKeyHeaderXDR
.data()));
603 CopyOut
wrappedPrivKeyHeaderXDR(privKeyHeaderData
, privKeyHeaderDataLength
+ sizeof(CSSM_KEYHEADER
), reinterpret_cast<xdrproc_t
>(xdr_CSSM_KEYHEADER_PTR
), true);
604 privHeader
= *static_cast<CssmKey::Header
*>(reinterpret_cast<CSSM_KEYHEADER
*>(wrappedPrivKeyHeaderXDR
.data()));
611 // This is a bit strained; the incoming 'param' value may have structure,
612 // and we use a synthetic CssmDeriveData structure (with ad-hoc walker) to
613 // handle that. Param also is input/output, which is always a pain (not to mention
614 // ill-defined by the CDSA standard).
616 // If you're here because an algorithm of yours requires structured parameter
617 // input, go to security_cdsa_utilities/cssmwalkers.h and add a case to the
618 // CssmDeriveData walker.
620 void ClientSession::deriveKey(DbHandle db
, const Context
&context
, KeyHandle baseKey
,
621 CSSM_KEYUSE usage
, CSSM_KEYATTR_FLAGS attrs
, CssmData
¶m
,
622 const AccessCredentials
*cred
, const AclEntryInput
*owner
,
623 KeyHandle
&newKey
, CssmKey::Header
&newHeader
, Allocator
&allocator
)
625 CopyIn
ctxcopy(&context
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_CONTEXT
));
626 CopyIn
creds(cred
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACCESS_CREDENTIALS
));
627 CopyIn
proto(owner
? &owner
->proto() : NULL
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACL_ENTRY_PROTOTYPE
));
628 CSSM_DERIVE_DATA inParamForm
= { context
.algorithm(), param
};
629 CopyIn
inParam(&inParamForm
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_DERIVE_DATA
));
633 DataOutput
paramOutput(param
, allocator
);
635 mach_msg_type_number_t keyHeaderDataLength
;
637 IPCKEY(ucsp_client_deriveKey(UCSP_ARGS
, db
, ctxcopy
.data(), ctxcopy
.length(), baseKey
,
638 creds
.data(), creds
.length(), proto
.data(), proto
.length(),
639 inParam
.data(), inParam
.length(), DATA_OUT(paramOutput
),
640 usage
, attrs
, &newKey
, &keyHeaderData
, &keyHeaderDataLength
),
641 baseKey
, CSSM_ACL_AUTHORIZATION_DERIVE
);
643 CopyOut
wrappedKeyHeaderXDR(keyHeaderData
, keyHeaderDataLength
+ sizeof(CSSM_KEYHEADER
), reinterpret_cast<xdrproc_t
>(xdr_CSSM_KEYHEADER_PTR
), true);
644 newHeader
= *static_cast<CssmKey::Header
*>(reinterpret_cast<CSSM_KEYHEADER
*>(wrappedKeyHeaderXDR
.data()));
648 // filter out errors for CSSM_ALGID_PKCS5_PBKDF2
649 if (context
.algorithm() != CSSM_ALGID_PKCS5_PBKDF2
&& e
.error
!= CSSMERR_CSP_OUTPUT_LENGTH_ERROR
)
660 void ClientSession::getKeyDigest(KeyHandle key
, CssmData
&digest
, Allocator
&allocator
)
662 DataOutput
dig(digest
, allocator
);
663 IPC(ucsp_client_getKeyDigest(UCSP_ARGS
, key
, DATA_OUT(dig
)));
668 // Key wrapping and unwrapping
670 void ClientSession::wrapKey(const Context
&context
, KeyHandle wrappingKey
,
671 KeyHandle keyToBeWrapped
, const AccessCredentials
*cred
,
672 const CssmData
*descriptiveData
, CssmWrappedKey
&wrappedKey
, Allocator
&alloc
)
674 CopyIn
ctxcopy(&context
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_CONTEXT
));
675 CopyIn
creds(cred
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACCESS_CREDENTIALS
));
677 mach_msg_type_number_t keyDataLength
;
679 IPCKEY(ucsp_client_wrapKey(UCSP_ARGS
, ctxcopy
.data(), ctxcopy
.length(), wrappingKey
,
680 creds
.data(), creds
.length(),
681 keyToBeWrapped
, OPTIONALDATA(descriptiveData
),
682 &keyData
, &keyDataLength
),
684 context
.algorithm() == CSSM_ALGID_NONE
685 ? CSSM_ACL_AUTHORIZATION_EXPORT_CLEAR
: CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED
);
687 CopyOut
wrappedKeyXDR(keyData
, keyDataLength
+ sizeof(CSSM_KEY
), reinterpret_cast<xdrproc_t
>(xdr_CSSM_KEY_PTR
), true);
688 CssmWrappedKey
*wrappedKeyIPC
= reinterpret_cast<CssmWrappedKey
*>(wrappedKeyXDR
.data());
689 wrappedKey
.header() = wrappedKeyIPC
->header();
690 wrappedKey
.keyData() = CssmData(alloc
.malloc(wrappedKeyIPC
->keyData().length()), wrappedKeyIPC
->keyData().length());
691 memcpy(wrappedKey
.keyData().data(), wrappedKeyIPC
->keyData(), wrappedKeyIPC
->keyData().length());
694 void ClientSession::unwrapKey(DbHandle db
, const Context
&context
, KeyHandle key
,
695 KeyHandle publicKey
, const CssmWrappedKey
&wrappedKey
,
696 uint32 usage
, uint32 attr
,
697 const AccessCredentials
*cred
, const AclEntryInput
*acl
,
698 CssmData
&descriptiveData
,
699 KeyHandle
&newKey
, CssmKey::Header
&newHeader
, Allocator
&alloc
)
701 CopyIn
ctxcopy(&context
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_CONTEXT
));
702 DataOutput
descriptor(descriptiveData
, alloc
);
703 CopyIn
creds(cred
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACCESS_CREDENTIALS
));
704 CopyIn
proto(acl
? &acl
->proto() : NULL
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACL_ENTRY_PROTOTYPE
));
705 CopyIn
wrappedKeyXDR(&wrappedKey
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_KEY
));
707 mach_msg_type_number_t keyHeaderDataLength
;
709 IPCKEY(ucsp_client_unwrapKey(UCSP_ARGS
, db
, ctxcopy
.data(), ctxcopy
.length(), key
,
710 creds
.data(), creds
.length(), proto
.data(), proto
.length(),
711 publicKey
, wrappedKeyXDR
.data(), wrappedKeyXDR
.length(), usage
, attr
, DATA_OUT(descriptor
),
712 &newKey
, &keyHeaderData
, &keyHeaderDataLength
),
713 key
, CSSM_ACL_AUTHORIZATION_DECRYPT
);
715 CopyOut
wrappedKeyHeaderXDR(keyHeaderData
, keyHeaderDataLength
+ sizeof(CSSM_KEYHEADER
), reinterpret_cast<xdrproc_t
>(xdr_CSSM_KEYHEADER_PTR
), true);
716 newHeader
= *static_cast<CssmKey::Header
*>(reinterpret_cast<CSSM_KEYHEADER
*>(wrappedKeyHeaderXDR
.data()));
723 void ClientSession::getAcl(AclKind kind
, GenericHandle key
, const char *tag
,
724 uint32
&infoCount
, AclEntryInfo
* &infoArray
, Allocator
&alloc
)
727 void* info
; mach_msg_type_number_t infoLength
;
728 IPC(ucsp_client_getAcl(UCSP_ARGS
, kind
, key
,
729 (tag
!= NULL
), tag
? tag
: "",
730 &count
, &info
, &infoLength
));
732 CSSM_ACL_ENTRY_INFO_ARRAY_PTR aclsArray
;
733 if (!::copyout_chunked(info
, infoLength
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACL_ENTRY_INFO_ARRAY_PTR
), reinterpret_cast<void**>(&aclsArray
)))
734 CssmError::throwMe(CSSM_ERRCODE_MEMORY_ERROR
);
736 infoCount
= aclsArray
->count
;
737 infoArray
= reinterpret_cast<AclEntryInfo
*>(aclsArray
->acls
);
741 void ClientSession::changeAcl(AclKind kind
, GenericHandle key
, const AccessCredentials
&cred
,
744 CopyIn
creds(&cred
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACCESS_CREDENTIALS
));
745 //@@@ ignoring callback
746 CopyIn
newEntry(edit
.newEntry(), reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACL_ENTRY_INPUT
));
748 IPCKEY(ucsp_client_changeAcl(UCSP_ARGS
, kind
, key
, creds
.data(), creds
.length(),
749 edit
.mode(), toIPCHandle(edit
.handle()), newEntry
.data(), newEntry
.length()),
750 key
, CSSM_ACL_AUTHORIZATION_CHANGE_ACL
);
753 void ClientSession::getOwner(AclKind kind
, GenericHandle key
, AclOwnerPrototype
&owner
,
756 void* proto
; mach_msg_type_number_t protoLength
;
757 IPC(ucsp_client_getOwner(UCSP_ARGS
, kind
, key
, &proto
, &protoLength
));
759 CSSM_ACL_OWNER_PROTOTYPE_PTR tmpOwner
;
760 if (!::copyout_chunked(proto
, protoLength
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACL_OWNER_PROTOTYPE_PTR
), reinterpret_cast<void **>(&tmpOwner
)))
761 CssmError::throwMe(CSSM_ERRCODE_MEMORY_ERROR
);
762 owner
= *static_cast<AclOwnerPrototypePtr
>(tmpOwner
);
766 void ClientSession::changeOwner(AclKind kind
, GenericHandle key
,
767 const AccessCredentials
&cred
, const AclOwnerPrototype
&proto
)
769 CopyIn
creds(&cred
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACCESS_CREDENTIALS
));
770 CopyIn
protos(&proto
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACL_OWNER_PROTOTYPE
));
771 IPCKEY(ucsp_client_setOwner(UCSP_ARGS
, kind
, key
, creds
.data(), creds
.length(), protos
.data(), protos
.length()),
772 key
, CSSM_ACL_AUTHORIZATION_CHANGE_OWNER
);
776 void ClientSession::getKeyAcl(DbHandle db
, const char *tag
,
777 uint32
&count
, AclEntryInfo
* &info
, Allocator
&alloc
)
778 { getAcl(keyAcl
, db
, tag
, count
, info
, alloc
); }
780 void ClientSession::changeKeyAcl(DbHandle db
, const AccessCredentials
&cred
,
782 { changeAcl(keyAcl
, db
, cred
, edit
); }
784 void ClientSession::getKeyOwner(DbHandle db
, AclOwnerPrototype
&owner
, Allocator
&alloc
)
785 { getOwner(keyAcl
, db
, owner
, alloc
); }
787 void ClientSession::changeKeyOwner(DbHandle db
, const AccessCredentials
&cred
,
788 const AclOwnerPrototype
&edit
)
789 { changeOwner(keyAcl
, db
, cred
, edit
); }
791 void ClientSession::getDbAcl(DbHandle db
, const char *tag
,
792 uint32
&count
, AclEntryInfo
* &info
, Allocator
&alloc
)
793 { getAcl(dbAcl
, db
, tag
, count
, info
, alloc
); }
795 void ClientSession::changeDbAcl(DbHandle db
, const AccessCredentials
&cred
,
797 { changeAcl(dbAcl
, db
, cred
, edit
); }
799 void ClientSession::getDbOwner(DbHandle db
, AclOwnerPrototype
&owner
, Allocator
&alloc
)
800 { getOwner(dbAcl
, db
, owner
, alloc
); }
802 void ClientSession::changeDbOwner(DbHandle db
, const AccessCredentials
&cred
,
803 const AclOwnerPrototype
&edit
)
804 { changeOwner(dbAcl
, db
, cred
, edit
); }
808 // Database key management
810 void ClientSession::extractMasterKey(DbHandle db
, const Context
&context
, DbHandle sourceDb
,
811 uint32 keyUsage
, uint32 keyAttr
,
812 const AccessCredentials
*cred
, const AclEntryInput
*owner
,
813 KeyHandle
&newKey
, CssmKey::Header
&newHeader
, Allocator
&alloc
)
815 CopyIn
ctxcopy(&context
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_CONTEXT
));
816 CopyIn
creds(cred
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACCESS_CREDENTIALS
));
817 CopyIn
proto(owner
? &owner
->proto() : NULL
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACL_ENTRY_PROTOTYPE
));
819 mach_msg_type_number_t keyHeaderDataLength
;
821 IPC(ucsp_client_extractMasterKey(UCSP_ARGS
, db
, ctxcopy
.data(), ctxcopy
.length(), sourceDb
,
822 creds
.data(), creds
.length(), proto
.data(), proto
.length(),
823 keyUsage
, keyAttr
, &newKey
, &keyHeaderData
, &keyHeaderDataLength
));
825 CopyOut
wrappedKeyHeaderXDR(keyHeaderData
, keyHeaderDataLength
+ sizeof(CSSM_KEYHEADER
), reinterpret_cast<xdrproc_t
>(xdr_CSSM_KEYHEADER_PTR
), true);
826 newHeader
= *static_cast<CssmKey::Header
*>(reinterpret_cast<CSSM_KEYHEADER
*>(wrappedKeyHeaderXDR
.data()));
830 void ClientSession::postNotification(NotificationDomain domain
, NotificationEvent event
, const CssmData
&data
)
832 uint32 seq
= ++mGlobal().thread().notifySeq
;
834 if (getenv("NOTIFYJITTER")) {
835 // artificially reverse odd/even sequences to test securityd's jitter buffer
836 seq
+= 2 * (seq
% 2) - 1;
837 secinfo("notify", "POSTING FAKE SEQUENCE %d NOTIFICATION", seq
);
840 secinfo("notify", "posting domain 0x%x event %d sequence %d",
842 IPC(ucsp_client_postNotification(UCSP_ARGS
, domain
, event
, DATA(data
), seq
));
847 // Code Signing related
849 void ClientSession::registerHosting(mach_port_t hostingPort
, SecCSFlags flags
)
851 IPC(ucsp_client_registerHosting(UCSP_ARGS
, hostingPort
, flags
));
854 mach_port_t
ClientSession::hostingPort(pid_t pid
)
857 IPC(ucsp_client_hostingPort(UCSP_ARGS
, pid
, &result
));
861 SecGuestRef
ClientSession::createGuest(SecGuestRef host
,
862 uint32_t status
, const char *path
, const CssmData
&cdhash
, const CssmData
&attributes
, SecCSFlags flags
)
864 SecGuestRef newGuest
;
865 IPC(ucsp_client_createGuest(UCSP_ARGS
, host
, status
, path
, DATA(cdhash
), DATA(attributes
), flags
, &newGuest
));
866 if (flags
& kSecCSDedicatedHost
) {
867 secinfo("ssclient", "setting dedicated guest to 0x%x (was 0x%x)",
868 mDedicatedGuest
, newGuest
);
869 mDedicatedGuest
= newGuest
;
874 void ClientSession::setGuestStatus(SecGuestRef guest
, uint32 status
, const CssmData
&attributes
)
876 IPC(ucsp_client_setGuestStatus(UCSP_ARGS
, guest
, status
, DATA(attributes
)));
879 void ClientSession::removeGuest(SecGuestRef host
, SecGuestRef guest
)
881 IPC(ucsp_client_removeGuest(UCSP_ARGS
, host
, guest
));
884 void ClientSession::selectGuest(SecGuestRef newGuest
)
886 if (mDedicatedGuest
) {
887 secinfo("ssclient", "ignoring selectGuest(0x%x) because dedicated guest=0x%x",
888 newGuest
, mDedicatedGuest
);
890 secinfo("ssclient", "switching to guest 0x%x", newGuest
);
891 mGlobal().thread().currentGuest
= newGuest
;
895 SecGuestRef
ClientSession::selectedGuest() const
898 return mDedicatedGuest
;
900 return mGlobal().thread().currentGuest
;
907 // Return the number of Keychain users prompts securityd has considered showing.
908 // On non-internal installs, this returns 0.
909 void ClientSession::getUserPromptAttempts(uint32_t& attempts
) {
910 IPC(ucsp_client_getUserPromptAttempts(UCSP_ARGS
, &attempts
));
914 } // end namespace SecurityServer
915 } // end namespace Security