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 <CommonCrypto/CommonRandom.h>
54 #include <securityd_client/xdr_auth.h>
55 #include <securityd_client/xdr_cssm.h>
56 #include <securityd_client/xdr_dldb.h>
59 namespace SecurityServer
{
61 using MachPlusPlus::check
;
62 using MachPlusPlus::VMGuard
;
65 // Common database interface
67 void ClientSession::authenticateDb(DbHandle db
, CSSM_DB_ACCESS_TYPE type
,
68 const AccessCredentials
*cred
)
70 // XXX/cs Leave it up to DatabaseAccessCredentials to rewrite it for now
71 DatabaseAccessCredentials
creds(cred
, internalAllocator
);
72 CopyIn
copy(creds
.value(), reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACCESS_CREDENTIALS
));
73 IPC(ucsp_client_authenticateDb(UCSP_ARGS
, db
, type
, copy
.data(), copy
.length()));
77 void ClientSession::releaseDb(DbHandle db
)
79 IPC(ucsp_client_releaseDb(UCSP_ARGS
, db
));
84 // External database interface
86 DbHandle
ClientSession::openToken(uint32 ssid
, const AccessCredentials
*cred
,
90 DatabaseAccessCredentials
creds(cred
, internalAllocator
);
91 CopyIn
copycreds(creds
.value(), reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACCESS_CREDENTIALS
));
93 IPC(ucsp_client_openToken(UCSP_ARGS
, ssid
, name
? name
: "", copycreds
.data(), copycreds
.length(), &db
));
99 RecordHandle
ClientSession::insertRecord(DbHandle db
,
100 CSSM_DB_RECORDTYPE recordType
,
101 const CssmDbRecordAttributeData
*attributes
,
102 const CssmData
*data
)
105 CopyIn
db_record_attr_data(attributes
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA
));
107 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
));
113 void ClientSession::deleteRecord(DbHandle db
, RecordHandle record
)
115 IPC(ucsp_client_deleteRecord(UCSP_ARGS
, db
, record
));
119 void ClientSession::modifyRecord(DbHandle db
, RecordHandle
&record
,
120 CSSM_DB_RECORDTYPE recordType
,
121 const CssmDbRecordAttributeData
*attributes
,
122 const CssmData
*data
,
123 CSSM_DB_MODIFY_MODE modifyMode
)
125 CopyIn
db_record_attr_data(attributes
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA
));
127 IPC(ucsp_client_modifyRecord(UCSP_ARGS
, db
, &record
, recordType
, db_record_attr_data
.data(), (mach_msg_type_number_t
)db_record_attr_data
.length(),
128 data
!= NULL
, OPTIONALDATA(data
), modifyMode
));
132 void copy_back_attribute_return_data(CssmDbRecordAttributeData
*dest_attrs
, CssmDbRecordAttributeData
*source_attrs
, Allocator
&returnAllocator
)
134 assert(dest_attrs
->size() == source_attrs
->size());
135 // global (per-record) fields
136 dest_attrs
->recordType(source_attrs
->recordType());
137 dest_attrs
->semanticInformation(source_attrs
->semanticInformation());
139 // transfer data values (but not infos, which we keep in the original vector)
140 for (uint32 n
= 0; n
< dest_attrs
->size(); n
++)
141 dest_attrs
->at(n
).copyValues(source_attrs
->at(n
), returnAllocator
);
144 RecordHandle
ClientSession::findFirst(DbHandle db
,
145 const CssmQuery
&inQuery
,
146 SearchHandle
&hSearch
,
147 CssmDbRecordAttributeData
*attributes
,
148 CssmData
*data
, KeyHandle
&hKey
)
150 CopyIn
query(&inQuery
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_QUERY
));
151 CopyIn
in_attr(attributes
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA
));
152 void *out_attr_data
= NULL
, *out_data
= NULL
;
153 mach_msg_size_t out_attr_length
= 0, out_data_length
= 0;
154 RecordHandle ipcHRecord
= 0;
156 IPC(ucsp_client_findFirst(UCSP_ARGS
, db
,
157 query
.data(), query
.length(), in_attr
.data(), in_attr
.length(),
158 &out_attr_data
, &out_attr_length
, (data
!= NULL
), &out_data
, &out_data_length
,
159 &hKey
, &hSearch
, &ipcHRecord
));
163 CopyOut
out_attrs(out_attr_data
, out_attr_length
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR
), true);
164 copy_back_attribute_return_data(attributes
, reinterpret_cast<CssmDbRecordAttributeData
*>(out_attrs
.data()), returnAllocator
);
167 // decode data from server as cssm_data or cssm_key (get data on keys returns cssm_key in data)
168 CopyOut
possible_key_in_data(out_data
, out_data_length
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_POSSIBLY_KEY_IN_DATA_PTR
), true, data
);
174 RecordHandle
ClientSession::findNext(SearchHandle hSearch
,
175 CssmDbRecordAttributeData
*attributes
,
176 CssmData
*data
, KeyHandle
&hKey
)
178 CopyIn
in_attr(attributes
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA
));
179 void *out_attr_data
= NULL
, *out_data
= NULL
;
180 mach_msg_size_t out_attr_length
= 0, out_data_length
= 0;
181 //DataOutput out_data(data, returnAllocator);
182 RecordHandle ipcHRecord
= 0;
184 IPC(ucsp_client_findNext(UCSP_ARGS
, hSearch
,
185 in_attr
.data(), in_attr
.length(), &out_attr_data
, &out_attr_length
,
186 (data
!= NULL
), &out_data
, &out_data_length
, &hKey
, &ipcHRecord
));
190 CopyOut
out_attrs(out_attr_data
, out_attr_length
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR
), true);
191 copy_back_attribute_return_data(attributes
, reinterpret_cast<CssmDbRecordAttributeData
*>(out_attrs
.data()), returnAllocator
);
194 // decode data from server as cssm_data or cssm_key (get data on keys returns cssm_key in data)
195 CopyOut
possible_key_in_data(out_data
, out_data_length
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_POSSIBLY_KEY_IN_DATA_PTR
), true, data
);
201 void ClientSession::findRecordHandle(RecordHandle hRecord
,
202 CssmDbRecordAttributeData
*attributes
,
203 CssmData
*data
, KeyHandle
&hKey
)
205 CopyIn
in_attr(attributes
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA
));
206 void *out_attr_data
= NULL
, *out_data
= NULL
;
207 mach_msg_size_t out_attr_length
= 0, out_data_length
= 0;
208 IPC(ucsp_client_findRecordHandle(UCSP_ARGS
, hRecord
,
209 in_attr
.data(), in_attr
.length(), &out_attr_data
, &out_attr_length
,
210 data
!= NULL
, &out_data
, &out_data_length
, &hKey
));
214 CopyOut
out_attrs(out_attr_data
, out_attr_length
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR
), true);
215 copy_back_attribute_return_data(attributes
, reinterpret_cast<CssmDbRecordAttributeData
*>(out_attrs
.data()), returnAllocator
);
218 // decode data from server as cssm_data or cssm_key (get data on keys returns cssm_key in data)
219 CopyOut
possible_key_in_data(out_data
, out_data_length
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_POSSIBLY_KEY_IN_DATA_PTR
), true, data
);
223 void ClientSession::releaseSearch(SearchHandle searchHandle
)
225 IPC(ucsp_client_releaseSearch(UCSP_ARGS
, searchHandle
));
229 void ClientSession::releaseRecord(RecordHandle record
)
231 IPC(ucsp_client_releaseRecord(UCSP_ARGS
, record
));
234 void ClientSession::getDbName(DbHandle db
, string
&name
)
236 char result
[PATH_MAX
];
238 IPC(ucsp_client_getDbName(UCSP_ARGS
, db
, result
));
243 void ClientSession::setDbName(DbHandle db
, const string
&name
)
245 IPC(ucsp_client_setDbName(UCSP_ARGS
, db
, name
.c_str()));
250 // Internal database management
252 DbHandle
ClientSession::createDb(const DLDbIdentifier
&dbId
,
253 const AccessCredentials
*cred
, const AclEntryInput
*owner
,
254 const DBParameters
¶ms
)
256 DatabaseAccessCredentials
creds(cred
, internalAllocator
);
257 CopyIn
copycreds(creds
.value(), reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACCESS_CREDENTIALS
));
258 CopyIn
proto(owner
? &owner
->proto() : NULL
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACL_ENTRY_PROTOTYPE
));
259 // XXX/64 make xdr routines translate directly between dldbident and flat rep
260 DataWalkers::DLDbFlatIdentifier
ident(dbId
);
261 CopyIn
id(&ident
, reinterpret_cast<xdrproc_t
>(xdr_DLDbFlatIdentifier
));
264 IPC(ucsp_client_createDb(UCSP_ARGS
, &db
, id
.data(), id
.length(), copycreds
.data(), copycreds
.length(), proto
.data(), proto
.length(), params
));
269 DbHandle
ClientSession::cloneDb(const DLDbIdentifier
&newDbId
, DbHandle srcDb
) {
270 DataWalkers::DLDbFlatIdentifier
ident(newDbId
);
271 CopyIn
id(&ident
, reinterpret_cast<xdrproc_t
>(xdr_DLDbFlatIdentifier
));
274 IPC(ucsp_client_cloneDb(UCSP_ARGS
, srcDb
, id
.data(), id
.length(), &db
));
278 DbHandle
ClientSession::recodeDbForSync(DbHandle dbToClone
,
283 IPC(ucsp_client_recodeDbForSync(UCSP_ARGS
, dbToClone
, srcDb
, &newDb
));
288 DbHandle
ClientSession::recodeDbToVersion(uint32 newVersion
, DbHandle srcDb
)
292 IPC(ucsp_client_recodeDbToVersion(UCSP_ARGS
, newVersion
, srcDb
, &newDb
));
297 void ClientSession::recodeFinished(DbHandle db
)
299 IPC(ucsp_client_recodeFinished(UCSP_ARGS
, db
));
302 DbHandle
ClientSession::authenticateDbsForSync(const CssmData
&dbHandleArray
,
303 const CssmData
&agentData
)
307 IPC(ucsp_client_authenticateDbsForSync(UCSP_ARGS
, DATA(dbHandleArray
), DATA(agentData
), &newDb
));
312 void ClientSession::commitDbForSync(DbHandle srcDb
, DbHandle cloneDb
,
313 CssmData
&blob
, Allocator
&alloc
)
315 DataOutput
outBlob(blob
, alloc
);
316 IPC(ucsp_client_commitDbForSync(UCSP_ARGS
, srcDb
, cloneDb
, DATA_OUT(outBlob
)));
319 DbHandle
ClientSession::decodeDb(const DLDbIdentifier
&dbId
,
320 const AccessCredentials
*cred
, const CssmData
&blob
)
322 // XXX/64 fold into one translation
323 DatabaseAccessCredentials
credentials(cred
, internalAllocator
);
324 CopyIn
creds(credentials
.value(), reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACCESS_CREDENTIALS
));
325 // XXX/64 fold into one translation
326 DataWalkers::DLDbFlatIdentifier
ident(dbId
);
327 CopyIn
id(&ident
, reinterpret_cast<xdrproc_t
>(xdr_DLDbFlatIdentifier
));
330 IPC(ucsp_client_decodeDb(UCSP_ARGS
, &db
, id
.data(), id
.length(), creds
.data(), creds
.length(), DATA(blob
)));
335 void ClientSession::encodeDb(DbHandle db
, CssmData
&blob
, Allocator
&alloc
)
337 DataOutput
outBlob(blob
, alloc
);
338 IPC(ucsp_client_encodeDb(UCSP_ARGS
, db
, DATA_OUT(outBlob
)));
341 void ClientSession::setDbParameters(DbHandle db
, const DBParameters
¶ms
)
343 IPC(ucsp_client_setDbParameters(UCSP_ARGS
, db
, params
));
346 void ClientSession::getDbParameters(DbHandle db
, DBParameters
¶ms
)
348 IPC(ucsp_client_getDbParameters(UCSP_ARGS
, db
, ¶ms
));
351 void ClientSession::changePassphrase(DbHandle db
, const AccessCredentials
*cred
)
353 CopyIn
creds(cred
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACCESS_CREDENTIALS
));
354 IPC(ucsp_client_changePassphrase(UCSP_ARGS
, db
, creds
.data(), creds
.length()));
358 void ClientSession::lock(DbHandle db
)
360 IPC(ucsp_client_authenticateDb(UCSP_ARGS
, db
, CSSM_DB_ACCESS_RESET
, NULL
, 0));
361 //@@@VIRTUAL IPC(ucsp_client_lockDb(UCSP_ARGS, db));
364 void ClientSession::lockAll (bool forSleep
)
366 IPC(ucsp_client_lockAll (UCSP_ARGS
, forSleep
));
369 void ClientSession::unlock(DbHandle db
)
371 IPC(ucsp_client_unlockDb(UCSP_ARGS
, db
));
374 void ClientSession::unlock(DbHandle db
, const CssmData
&passphrase
)
376 IPC(ucsp_client_unlockDbWithPassphrase(UCSP_ARGS
, db
, DATA(passphrase
)));
379 void ClientSession::stashDb(DbHandle db
)
381 IPC(ucsp_client_stashDb(UCSP_ARGS
, db
));
384 void ClientSession::stashDbCheck(DbHandle db
)
386 IPC(ucsp_client_stashDbCheck(UCSP_ARGS
, db
));
389 bool ClientSession::isLocked(DbHandle db
)
392 IPC(ucsp_client_isLocked(UCSP_ARGS
, db
, &locked
));
396 void ClientSession::verifyKeyStorePassphrase(uint32_t retries
)
398 IPC(ucsp_client_verifyKeyStorePassphrase(UCSP_ARGS
, retries
));
401 void ClientSession::resetKeyStorePassphrase(const CssmData
&passphrase
)
403 IPC(ucsp_client_resetKeyStorePassphrase(UCSP_ARGS
, DATA(passphrase
)));
406 void ClientSession::changeKeyStorePassphrase()
408 IPC(ucsp_client_changeKeyStorePassphrase(UCSP_ARGS
));
414 void ClientSession::encodeKey(KeyHandle key
, CssmData
&blob
,
415 KeyUID
*uid
, Allocator
&alloc
)
417 // Not really used as output
418 DataOutput
oBlob(blob
, alloc
);
420 mach_msg_type_number_t uidLength
;
422 IPC(ucsp_client_encodeKey(UCSP_ARGS
, key
, oBlob
.data(), oBlob
.length(),
423 (uid
!= NULL
), &uidp
, &uidLength
));
425 // return key uid if requested
427 assert(uidLength
== sizeof(KeyUID
));
428 memcpy(uid
, uidp
, sizeof(KeyUID
));
432 KeyHandle
ClientSession::decodeKey(DbHandle db
, const CssmData
&blob
, CssmKey::Header
&header
)
436 mach_msg_type_number_t keyHeaderDataLength
;
438 IPC(ucsp_client_decodeKey(UCSP_ARGS
, &key
, &keyHeaderData
, &keyHeaderDataLength
, db
, blob
.data(), (mach_msg_type_number_t
)blob
.length()));
440 CopyOut
wrappedKeyHeaderXDR(keyHeaderData
, keyHeaderDataLength
+ sizeof(CSSM_KEYHEADER
), reinterpret_cast<xdrproc_t
>(xdr_CSSM_KEYHEADER_PTR
), true);
441 header
= *static_cast<CssmKey::Header
*>(reinterpret_cast<CSSM_KEYHEADER
*>(wrappedKeyHeaderXDR
.data()));
446 // keychain synchronization
447 void ClientSession::recodeKey(DbHandle oldDb
, KeyHandle key
, DbHandle newDb
,
450 DataOutput
outBlob(blob
, returnAllocator
);
451 IPC(ucsp_client_recodeKey(UCSP_ARGS
, oldDb
, key
, newDb
, DATA_OUT(outBlob
)));
454 void ClientSession::releaseKey(KeyHandle key
)
456 IPC(ucsp_client_releaseKey(UCSP_ARGS
, key
));
460 CssmKeySize
ClientSession::queryKeySizeInBits(KeyHandle key
)
463 IPC(ucsp_client_queryKeySizeInBits(UCSP_ARGS
, key
, &length
));
468 uint32
ClientSession::getOutputSize(const Context
&context
, KeyHandle key
,
469 uint32 inputSize
, bool encrypt
)
471 CopyIn
ctxcopy(&context
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_CONTEXT
));
474 IPC(ucsp_client_getOutputSize(UCSP_ARGS
, ctxcopy
.data(), ctxcopy
.length(), key
, inputSize
, encrypt
, &outputSize
));
480 // Random number generation.
481 // This interfaces to the secure RNG inside the SecurityServer; it does not access
482 // a PRNG in its CSP. If you need a reproducible PRNG, attach a local CSP and use it.
483 // Note that this function does not allocate a buffer; it always fills the buffer provided.
485 // As of macOS 10.15 this no longer fetches random data from the daemon but generates it in-process
487 void ClientSession::generateRandom(const Security::Context
&context
, CssmData
&data
, Allocator
&alloc
)
489 size_t count
= context
.getInt(CSSM_ATTRIBUTE_OUTPUT_SIZE
);
490 if (data
.length() < count
) {
491 CssmError::throwMe(CSSM_ERRCODE_INVALID_DATA
);
493 CCRNGStatus status
= CCRandomGenerateBytes(data
.data(), count
);
494 if (status
!= kCCSuccess
) {
495 CssmError::throwMe(status
);
501 // Signatures and MACs
503 void ClientSession::generateSignature(const Context
&context
, KeyHandle key
,
504 const CssmData
&data
, CssmData
&signature
, Allocator
&alloc
, CSSM_ALGORITHMS signOnlyAlgorithm
)
506 CopyIn
ctxcopy(&context
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_CONTEXT
));
507 DataOutput
sig(signature
, alloc
);
509 IPCKEY(ucsp_client_generateSignature(UCSP_ARGS
, ctxcopy
.data(), ctxcopy
.length(), key
, signOnlyAlgorithm
,
510 DATA(data
), DATA_OUT(sig
)),
511 key
, CSSM_ACL_AUTHORIZATION_SIGN
);
514 void ClientSession::verifySignature(const Context
&context
, KeyHandle key
,
515 const CssmData
&data
, const CssmData
&signature
, CSSM_ALGORITHMS verifyOnlyAlgorithm
)
517 CopyIn
ctxcopy(&context
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_CONTEXT
));
519 IPC(ucsp_client_verifySignature(UCSP_ARGS
, ctxcopy
.data(), ctxcopy
.length(), key
, verifyOnlyAlgorithm
, DATA(data
), DATA(signature
)));
523 void ClientSession::generateMac(const Context
&context
, KeyHandle key
,
524 const CssmData
&data
, CssmData
&signature
, Allocator
&alloc
)
526 CopyIn
ctxcopy(&context
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_CONTEXT
));
527 DataOutput
sig(signature
, alloc
);
529 IPCKEY(ucsp_client_generateMac(UCSP_ARGS
, ctxcopy
.data(), ctxcopy
.length(), key
, DATA(data
), DATA_OUT(sig
)),
530 key
, CSSM_ACL_AUTHORIZATION_MAC
);
533 void ClientSession::verifyMac(const Context
&context
, KeyHandle key
,
534 const CssmData
&data
, const CssmData
&signature
)
536 CopyIn
ctxcopy(&context
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_CONTEXT
));
538 IPCKEY(ucsp_client_verifyMac(UCSP_ARGS
, ctxcopy
.data(), ctxcopy
.length(), key
,
539 DATA(data
), DATA(signature
)),
540 key
, CSSM_ACL_AUTHORIZATION_MAC
);
545 // Encryption/Decryption
548 void ClientSession::encrypt(const Context
&context
, KeyHandle key
,
549 const CssmData
&clear
, CssmData
&cipher
, Allocator
&alloc
)
551 CopyIn
ctxcopy(&context
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_CONTEXT
));
552 DataOutput
cipherOut(cipher
, alloc
);
553 IPCKEY(ucsp_client_encrypt(UCSP_ARGS
, ctxcopy
.data(), ctxcopy
.length(), key
, DATA(clear
), DATA_OUT(cipherOut
)),
554 key
, CSSM_ACL_AUTHORIZATION_ENCRYPT
);
557 void ClientSession::decrypt(const Context
&context
, KeyHandle key
,
558 const CssmData
&cipher
, CssmData
&clear
, Allocator
&alloc
)
560 CopyIn
ctxcopy(&context
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_CONTEXT
));
561 DataOutput
clearOut(clear
, alloc
);
563 IPCKEY(ucsp_client_decrypt(UCSP_ARGS
, ctxcopy
.data(), ctxcopy
.length(), key
, DATA(cipher
), DATA_OUT(clearOut
)),
564 key
, CSSM_ACL_AUTHORIZATION_DECRYPT
);
571 void ClientSession::generateKey(DbHandle db
, const Context
&context
, uint32 keyUsage
, uint32 keyAttr
,
572 const AccessCredentials
*cred
, const AclEntryInput
*owner
,
573 KeyHandle
&newKey
, CssmKey::Header
&newHeader
)
575 CopyIn
ctxcopy(&context
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_CONTEXT
));
576 CopyIn
creds(cred
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACCESS_CREDENTIALS
));
577 CopyIn
proto(owner
? &owner
->proto() : NULL
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACL_ENTRY_PROTOTYPE
));
579 mach_msg_type_number_t keyHeaderDataLength
;
581 IPC(ucsp_client_generateKey(UCSP_ARGS
, db
, ctxcopy
.data(), ctxcopy
.length(),
582 creds
.data(), creds
.length(), proto
.data(), proto
.length(),
583 keyUsage
, keyAttr
, &newKey
, &keyHeaderData
, &keyHeaderDataLength
));
585 CopyOut
wrappedKeyHeaderXDR(keyHeaderData
, keyHeaderDataLength
+ sizeof(CSSM_KEYHEADER
), reinterpret_cast<xdrproc_t
>(xdr_CSSM_KEYHEADER_PTR
), true);
586 newHeader
= *static_cast<CssmKey::Header
*>(reinterpret_cast<CSSM_KEYHEADER
*>(wrappedKeyHeaderXDR
.data()));
589 void ClientSession::generateKey(DbHandle db
, const Context
&context
,
590 uint32 pubKeyUsage
, uint32 pubKeyAttr
,
591 uint32 privKeyUsage
, uint32 privKeyAttr
,
592 const AccessCredentials
*cred
, const AclEntryInput
*owner
,
593 KeyHandle
&pubKey
, CssmKey::Header
&pubHeader
,
594 KeyHandle
&privKey
, CssmKey::Header
&privHeader
)
596 CopyIn
ctxcopy(&context
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_CONTEXT
));
597 CopyIn
creds(cred
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACCESS_CREDENTIALS
));
598 CopyIn
proto(owner
? &owner
->proto() : NULL
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACL_ENTRY_PROTOTYPE
));
599 void *pubKeyHeaderData
, *privKeyHeaderData
;
600 mach_msg_type_number_t pubKeyHeaderDataLength
, privKeyHeaderDataLength
;
602 IPC(ucsp_client_generateKeyPair(UCSP_ARGS
, db
, ctxcopy
.data(), ctxcopy
.length(),
603 creds
.data(), creds
.length(), proto
.data(), proto
.length(),
604 pubKeyUsage
, pubKeyAttr
, privKeyUsage
, privKeyAttr
,
605 &pubKey
, &pubKeyHeaderData
, &pubKeyHeaderDataLength
,
606 &privKey
, &privKeyHeaderData
, &privKeyHeaderDataLength
));
608 CopyOut
wrappedPubKeyHeaderXDR(pubKeyHeaderData
, pubKeyHeaderDataLength
+ sizeof(CSSM_KEYHEADER
), reinterpret_cast<xdrproc_t
>(xdr_CSSM_KEYHEADER_PTR
), true);
609 pubHeader
= *static_cast<CssmKey::Header
*>(reinterpret_cast<CSSM_KEYHEADER
*>(wrappedPubKeyHeaderXDR
.data()));
610 CopyOut
wrappedPrivKeyHeaderXDR(privKeyHeaderData
, privKeyHeaderDataLength
+ sizeof(CSSM_KEYHEADER
), reinterpret_cast<xdrproc_t
>(xdr_CSSM_KEYHEADER_PTR
), true);
611 privHeader
= *static_cast<CssmKey::Header
*>(reinterpret_cast<CSSM_KEYHEADER
*>(wrappedPrivKeyHeaderXDR
.data()));
618 // This is a bit strained; the incoming 'param' value may have structure,
619 // and we use a synthetic CssmDeriveData structure (with ad-hoc walker) to
620 // handle that. Param also is input/output, which is always a pain (not to mention
621 // ill-defined by the CDSA standard).
623 // If you're here because an algorithm of yours requires structured parameter
624 // input, go to security_cdsa_utilities/cssmwalkers.h and add a case to the
625 // CssmDeriveData walker.
627 void ClientSession::deriveKey(DbHandle db
, const Context
&context
, KeyHandle baseKey
,
628 CSSM_KEYUSE usage
, CSSM_KEYATTR_FLAGS attrs
, CssmData
¶m
,
629 const AccessCredentials
*cred
, const AclEntryInput
*owner
,
630 KeyHandle
&newKey
, CssmKey::Header
&newHeader
, Allocator
&allocator
)
632 CopyIn
ctxcopy(&context
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_CONTEXT
));
633 CopyIn
creds(cred
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACCESS_CREDENTIALS
));
634 CopyIn
proto(owner
? &owner
->proto() : NULL
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACL_ENTRY_PROTOTYPE
));
635 CSSM_DERIVE_DATA inParamForm
= { context
.algorithm(), param
};
636 CopyIn
inParam(&inParamForm
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_DERIVE_DATA
));
640 DataOutput
paramOutput(param
, allocator
);
642 mach_msg_type_number_t keyHeaderDataLength
;
644 IPCKEY(ucsp_client_deriveKey(UCSP_ARGS
, db
, ctxcopy
.data(), ctxcopy
.length(), baseKey
,
645 creds
.data(), creds
.length(), proto
.data(), proto
.length(),
646 inParam
.data(), inParam
.length(), DATA_OUT(paramOutput
),
647 usage
, attrs
, &newKey
, &keyHeaderData
, &keyHeaderDataLength
),
648 baseKey
, CSSM_ACL_AUTHORIZATION_DERIVE
);
650 CopyOut
wrappedKeyHeaderXDR(keyHeaderData
, keyHeaderDataLength
+ sizeof(CSSM_KEYHEADER
), reinterpret_cast<xdrproc_t
>(xdr_CSSM_KEYHEADER_PTR
), true);
651 newHeader
= *static_cast<CssmKey::Header
*>(reinterpret_cast<CSSM_KEYHEADER
*>(wrappedKeyHeaderXDR
.data()));
655 // filter out errors for CSSM_ALGID_PKCS5_PBKDF2
656 if (context
.algorithm() != CSSM_ALGID_PKCS5_PBKDF2
&& e
.error
!= CSSMERR_CSP_OUTPUT_LENGTH_ERROR
)
667 void ClientSession::getKeyDigest(KeyHandle key
, CssmData
&digest
, Allocator
&allocator
)
669 DataOutput
dig(digest
, allocator
);
670 IPC(ucsp_client_getKeyDigest(UCSP_ARGS
, key
, DATA_OUT(dig
)));
675 // Key wrapping and unwrapping
677 void ClientSession::wrapKey(const Context
&context
, KeyHandle wrappingKey
,
678 KeyHandle keyToBeWrapped
, const AccessCredentials
*cred
,
679 const CssmData
*descriptiveData
, CssmWrappedKey
&wrappedKey
, Allocator
&alloc
)
681 CopyIn
ctxcopy(&context
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_CONTEXT
));
682 CopyIn
creds(cred
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACCESS_CREDENTIALS
));
684 mach_msg_type_number_t keyDataLength
;
686 IPCKEY(ucsp_client_wrapKey(UCSP_ARGS
, ctxcopy
.data(), ctxcopy
.length(), wrappingKey
,
687 creds
.data(), creds
.length(),
688 keyToBeWrapped
, OPTIONALDATA(descriptiveData
),
689 &keyData
, &keyDataLength
),
691 context
.algorithm() == CSSM_ALGID_NONE
692 ? CSSM_ACL_AUTHORIZATION_EXPORT_CLEAR
: CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED
);
694 CopyOut
wrappedKeyXDR(keyData
, keyDataLength
+ sizeof(CSSM_KEY
), reinterpret_cast<xdrproc_t
>(xdr_CSSM_KEY_PTR
), true);
695 CssmWrappedKey
*wrappedKeyIPC
= reinterpret_cast<CssmWrappedKey
*>(wrappedKeyXDR
.data());
696 wrappedKey
.header() = wrappedKeyIPC
->header();
697 wrappedKey
.keyData() = CssmData(alloc
.malloc(wrappedKeyIPC
->keyData().length()), wrappedKeyIPC
->keyData().length());
698 memcpy(wrappedKey
.keyData().data(), wrappedKeyIPC
->keyData(), wrappedKeyIPC
->keyData().length());
701 void ClientSession::unwrapKey(DbHandle db
, const Context
&context
, KeyHandle key
,
702 KeyHandle publicKey
, const CssmWrappedKey
&wrappedKey
,
703 uint32 usage
, uint32 attr
,
704 const AccessCredentials
*cred
, const AclEntryInput
*acl
,
705 CssmData
&descriptiveData
,
706 KeyHandle
&newKey
, CssmKey::Header
&newHeader
, Allocator
&alloc
)
708 CopyIn
ctxcopy(&context
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_CONTEXT
));
709 DataOutput
descriptor(descriptiveData
, alloc
);
710 CopyIn
creds(cred
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACCESS_CREDENTIALS
));
711 CopyIn
proto(acl
? &acl
->proto() : NULL
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACL_ENTRY_PROTOTYPE
));
712 CopyIn
wrappedKeyXDR(&wrappedKey
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_KEY
));
714 mach_msg_type_number_t keyHeaderDataLength
;
716 IPCKEY(ucsp_client_unwrapKey(UCSP_ARGS
, db
, ctxcopy
.data(), ctxcopy
.length(), key
,
717 creds
.data(), creds
.length(), proto
.data(), proto
.length(),
718 publicKey
, wrappedKeyXDR
.data(), wrappedKeyXDR
.length(), usage
, attr
, DATA_OUT(descriptor
),
719 &newKey
, &keyHeaderData
, &keyHeaderDataLength
),
720 key
, CSSM_ACL_AUTHORIZATION_DECRYPT
);
722 CopyOut
wrappedKeyHeaderXDR(keyHeaderData
, keyHeaderDataLength
+ sizeof(CSSM_KEYHEADER
), reinterpret_cast<xdrproc_t
>(xdr_CSSM_KEYHEADER_PTR
), true);
723 newHeader
= *static_cast<CssmKey::Header
*>(reinterpret_cast<CSSM_KEYHEADER
*>(wrappedKeyHeaderXDR
.data()));
730 void ClientSession::getAcl(AclKind kind
, GenericHandle key
, const char *tag
,
731 uint32
&infoCount
, AclEntryInfo
* &infoArray
, Allocator
&alloc
)
734 void* info
; mach_msg_type_number_t infoLength
;
735 IPC(ucsp_client_getAcl(UCSP_ARGS
, kind
, key
,
736 (tag
!= NULL
), tag
? tag
: "",
737 &count
, &info
, &infoLength
));
739 CSSM_ACL_ENTRY_INFO_ARRAY_PTR aclsArray
;
740 if (!::copyout_chunked(info
, infoLength
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACL_ENTRY_INFO_ARRAY_PTR
), reinterpret_cast<void**>(&aclsArray
)))
741 CssmError::throwMe(CSSM_ERRCODE_MEMORY_ERROR
);
743 infoCount
= aclsArray
->count
;
744 infoArray
= reinterpret_cast<AclEntryInfo
*>(aclsArray
->acls
);
748 void ClientSession::changeAcl(AclKind kind
, GenericHandle key
, const AccessCredentials
&cred
,
751 CopyIn
creds(&cred
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACCESS_CREDENTIALS
));
752 //@@@ ignoring callback
753 CopyIn
newEntry(edit
.newEntry(), reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACL_ENTRY_INPUT
));
755 IPCKEY(ucsp_client_changeAcl(UCSP_ARGS
, kind
, key
, creds
.data(), creds
.length(),
756 edit
.mode(), toIPCHandle(edit
.handle()), newEntry
.data(), newEntry
.length()),
757 key
, CSSM_ACL_AUTHORIZATION_CHANGE_ACL
);
760 void ClientSession::getOwner(AclKind kind
, GenericHandle key
, AclOwnerPrototype
&owner
,
763 void* proto
; mach_msg_type_number_t protoLength
;
764 IPC(ucsp_client_getOwner(UCSP_ARGS
, kind
, key
, &proto
, &protoLength
));
766 CSSM_ACL_OWNER_PROTOTYPE_PTR tmpOwner
;
767 if (!::copyout_chunked(proto
, protoLength
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACL_OWNER_PROTOTYPE_PTR
), reinterpret_cast<void **>(&tmpOwner
)))
768 CssmError::throwMe(CSSM_ERRCODE_MEMORY_ERROR
);
769 owner
= *static_cast<AclOwnerPrototypePtr
>(tmpOwner
);
773 void ClientSession::changeOwner(AclKind kind
, GenericHandle key
,
774 const AccessCredentials
&cred
, const AclOwnerPrototype
&proto
)
776 CopyIn
creds(&cred
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACCESS_CREDENTIALS
));
777 CopyIn
protos(&proto
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACL_OWNER_PROTOTYPE
));
778 IPCKEY(ucsp_client_setOwner(UCSP_ARGS
, kind
, key
, creds
.data(), creds
.length(), protos
.data(), protos
.length()),
779 key
, CSSM_ACL_AUTHORIZATION_CHANGE_OWNER
);
783 void ClientSession::getKeyAcl(DbHandle db
, const char *tag
,
784 uint32
&count
, AclEntryInfo
* &info
, Allocator
&alloc
)
785 { getAcl(keyAcl
, db
, tag
, count
, info
, alloc
); }
787 void ClientSession::changeKeyAcl(DbHandle db
, const AccessCredentials
&cred
,
789 { changeAcl(keyAcl
, db
, cred
, edit
); }
791 void ClientSession::getKeyOwner(DbHandle db
, AclOwnerPrototype
&owner
, Allocator
&alloc
)
792 { getOwner(keyAcl
, db
, owner
, alloc
); }
794 void ClientSession::changeKeyOwner(DbHandle db
, const AccessCredentials
&cred
,
795 const AclOwnerPrototype
&edit
)
796 { changeOwner(keyAcl
, db
, cred
, edit
); }
798 void ClientSession::getDbAcl(DbHandle db
, const char *tag
,
799 uint32
&count
, AclEntryInfo
* &info
, Allocator
&alloc
)
800 { getAcl(dbAcl
, db
, tag
, count
, info
, alloc
); }
802 void ClientSession::changeDbAcl(DbHandle db
, const AccessCredentials
&cred
,
804 { changeAcl(dbAcl
, db
, cred
, edit
); }
806 void ClientSession::getDbOwner(DbHandle db
, AclOwnerPrototype
&owner
, Allocator
&alloc
)
807 { getOwner(dbAcl
, db
, owner
, alloc
); }
809 void ClientSession::changeDbOwner(DbHandle db
, const AccessCredentials
&cred
,
810 const AclOwnerPrototype
&edit
)
811 { changeOwner(dbAcl
, db
, cred
, edit
); }
815 // Database key management
817 void ClientSession::extractMasterKey(DbHandle db
, const Context
&context
, DbHandle sourceDb
,
818 uint32 keyUsage
, uint32 keyAttr
,
819 const AccessCredentials
*cred
, const AclEntryInput
*owner
,
820 KeyHandle
&newKey
, CssmKey::Header
&newHeader
, Allocator
&alloc
)
822 CopyIn
ctxcopy(&context
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_CONTEXT
));
823 CopyIn
creds(cred
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACCESS_CREDENTIALS
));
824 CopyIn
proto(owner
? &owner
->proto() : NULL
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACL_ENTRY_PROTOTYPE
));
826 mach_msg_type_number_t keyHeaderDataLength
;
828 IPC(ucsp_client_extractMasterKey(UCSP_ARGS
, db
, ctxcopy
.data(), ctxcopy
.length(), sourceDb
,
829 creds
.data(), creds
.length(), proto
.data(), proto
.length(),
830 keyUsage
, keyAttr
, &newKey
, &keyHeaderData
, &keyHeaderDataLength
));
832 CopyOut
wrappedKeyHeaderXDR(keyHeaderData
, keyHeaderDataLength
+ sizeof(CSSM_KEYHEADER
), reinterpret_cast<xdrproc_t
>(xdr_CSSM_KEYHEADER_PTR
), true);
833 newHeader
= *static_cast<CssmKey::Header
*>(reinterpret_cast<CSSM_KEYHEADER
*>(wrappedKeyHeaderXDR
.data()));
837 void ClientSession::postNotification(NotificationDomain domain
, NotificationEvent event
, const CssmData
&data
)
839 uint32 seq
= ++mGlobal().thread().notifySeq
;
841 if (getenv("NOTIFYJITTER")) {
842 // artificially reverse odd/even sequences to test securityd's jitter buffer
843 seq
+= 2 * (seq
% 2) - 1;
844 secinfo("notify", "POSTING FAKE SEQUENCE %d NOTIFICATION", seq
);
847 secinfo("notify", "posting domain 0x%x event %d sequence %d",
849 IPC(ucsp_client_postNotification(UCSP_ARGS
, domain
, event
, DATA(data
), seq
));
857 // Return the number of Keychain users prompts securityd has considered showing.
858 // On non-internal installs, this returns 0.
859 void ClientSession::getUserPromptAttempts(uint32_t& attempts
) {
860 IPC(ucsp_client_getUserPromptAttempts(UCSP_ARGS
, &attempts
));
864 } // end namespace SecurityServer
865 } // end namespace Security