/* * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ #include "transit.h" using namespace Security::Tokend; // // Server inbound transition layer. // These are C functions in the global namespace, called by the MIG dispatch. // // // Probe: Examine token, determine score, and generate token uid string // kern_return_t tokend_server_probe(TOKEND_ARGS, TokenScore *score, TokenUidString uid) { BEGIN_IPC uid[0] = '\0'; // default to no uid obtained CALL(probe, (kSecTokendCallbacksDefault, score, uid)); assert(strlen(uid) < TOKEND_MAX_UID); server.tokenUid(uid); END_IPC(CSSM) } // // Establish: take securityd's information and stash it away; // determine MDS resources and return them. // kern_return_t tokend_server_establish(TOKEND_ARGS, CSSM_GUID guid, uint32 ssid, SecTokendEstablishFlags flags, const char *cacheDirectory, const char *workDirectory, char mdsDirectory[PATH_MAX], char printName[PATH_MAX]) { BEGIN_IPC mdsDirectory[0] = '\0'; // default to all resources printName[0] = '\0'; // default to no print name CALL(establish, (&guid, ssid, flags, cacheDirectory, workDirectory, mdsDirectory, printName)); END_IPC(CSSM) } // // Induce termination // kern_return_t tokend_server_terminate(mach_port_t servicePort, uint32 reason, uint32 options) { server.termination(reason, options); } // // Find/retrieve interface // kern_return_t tokend_server_findFirst(TOKEND_ARGS, COPY_IN(CssmQuery, query), COPY_IN(CssmDbRecordAttributeData, inAttributes), boolean_t getData, DATA_OUT(outData), KeyHandle *hKey, COPY_OUT(CssmDbRecordAttributeData, outAttributes), SearchHandle *hSearch, RecordHandle *hRecord) { BEGIN_IPC relocate(query, queryBase); relocate(inAttributes, inAttributesBase); DataRetrieval interface(inAttributes, getData); CALL(findFirst, (query, &interface, hSearch)); interface.returnData(*hKey, *hRecord, *outData, *outDataLength, *outAttributes, *outAttributesLength, *outAttributesBase); END_IPC(DL) } kern_return_t tokend_server_findNext(TOKEND_ARGS, SearchHandle hSearch, COPY_IN(CssmDbRecordAttributeData, inAttributes), boolean_t getData, DATA_OUT(outData), KeyHandle *hKey, COPY_OUT(CssmDbRecordAttributeData, outAttributes), RecordHandle *hRecord) { BEGIN_IPC relocate(inAttributes, inAttributesBase); DataRetrieval interface(inAttributes, getData); CALL(findNext, (hSearch, &interface)); interface.returnData(*hKey, *hRecord, *outData, *outDataLength, *outAttributes, *outAttributesLength, *outAttributesBase); END_IPC(DL) } kern_return_t tokend_server_findRecordHandle(TOKEND_ARGS, RecordHandle hRecord, COPY_IN(CssmDbRecordAttributeData, inAttributes), boolean_t getData, DATA_OUT(outData), KeyHandle *hKey, COPY_OUT(CssmDbRecordAttributeData, outAttributes)) { BEGIN_IPC relocate(inAttributes, inAttributesBase); DataRetrieval interface(inAttributes, getData); CALL(findRecordHandle, (hRecord, &interface)); interface.returnData(*hKey, hRecord, *outData, *outDataLength, *outAttributes, *outAttributesLength, *outAttributesBase); END_IPC(DL) } kern_return_t tokend_server_insertRecord(TOKEND_ARGS, CSSM_DB_RECORDTYPE recordType, COPY_IN(CssmDbRecordAttributeData, attributes), DATA_IN(data), RecordHandle *hRecord) { BEGIN_IPC relocate(attributes, attributesBase); const CssmData dataBlob(DATA(data)); CALL(insertRecord, (recordType, attributes, data ? &dataBlob : NULL, hRecord)); END_IPC(DL) } kern_return_t tokend_server_modifyRecord(TOKEND_ARGS, CSSM_DB_RECORDTYPE recordType, RecordHandle *hRecord, COPY_IN(CssmDbRecordAttributeData, attributes), boolean_t setData, DATA_IN(data), CSSM_DB_MODIFY_MODE modifyMode) { BEGIN_IPC relocate(attributes, attributesBase); const CssmData dataBlob(DATA(data)); CALL(modifyRecord, (recordType, hRecord, attributes, setData ? &dataBlob : NULL, modifyMode)); END_IPC(DL) } kern_return_t tokend_server_deleteRecord(TOKEND_ARGS, RecordHandle hRecord) { BEGIN_IPC CALL(deleteRecord, (hRecord)); END_IPC(DL) } kern_return_t tokend_server_releaseSearch(TOKEND_ARGS, SearchHandle hSearch) { BEGIN_IPC CALL(releaseSearch, (hSearch)); END_IPC(DL) } kern_return_t tokend_server_releaseRecord(TOKEND_ARGS, RecordHandle hRecord) { BEGIN_IPC CALL(releaseRecord, (hRecord)); END_IPC(DL) } // // Key management // kern_return_t tokend_server_releaseKey(TOKEND_ARGS, KeyHandle hKey) { BEGIN_IPC CALL(releaseKey, (hKey)); END_IPC(DL) } kern_return_t tokend_server_queryKeySizeInBits(TOKEND_ARGS, KeyHandle hKey, CSSM_KEY_SIZE *size) { BEGIN_IPC CALL(getKeySize, (hKey, size)); END_IPC(CSP) } kern_return_t tokend_server_getOutputSize(TOKEND_ARGS, CONTEXT_ARGS, KeyHandle hKey, uint32 inputSize, boolean_t encrypt, uint32 *outputSize) { BEGIN_IPC relocate(context, contextBase, attributes, attrSize); CALL(getOutputSize, (&context, hKey, inputSize, encrypt, outputSize)); END_IPC(CSP) } // // Signatures and MACs // kern_return_t tokend_server_generateSignature(TOKEND_ARGS, CONTEXT_ARGS, KeyHandle hKey, CSSM_ALGORITHMS signOnlyAlgorithm, DATA_IN(data), DATA_OUT(signature)) { BEGIN_IPC relocate(context, contextBase, attributes, attrSize); const CssmData dataBlob(DATA(data)); OutputData sigData(signature, signatureLength); CALL(generateSignature, (&context, hKey, signOnlyAlgorithm, &dataBlob, &sigData)); END_IPC(CSP) } kern_return_t tokend_server_verifySignature(TOKEND_ARGS, CONTEXT_ARGS, KeyHandle hKey, CSSM_ALGORITHMS verifyOnlyAlgorithm, DATA_IN(data), DATA_IN(signature)) { BEGIN_IPC relocate(context, contextBase, attributes, attrSize); const CssmData dataBlob(DATA(data)); const CssmData signatureBlob(DATA(signature)); CALL(verifySignature, (&context, hKey, verifyOnlyAlgorithm, &dataBlob, &signatureBlob)); END_IPC(CSP) } kern_return_t tokend_server_generateMac(TOKEND_ARGS, CONTEXT_ARGS, KeyHandle hKey, DATA_IN(data), DATA_OUT(mac)) { BEGIN_IPC relocate(context, contextBase, attributes, attrSize); const CssmData dataBlob(DATA(data)); OutputData macData(mac, macLength); CALL(generateMac, (&context, hKey, &dataBlob, &macData)); END_IPC(CSP) } kern_return_t tokend_server_verifyMac(TOKEND_ARGS, CONTEXT_ARGS, KeyHandle hKey, DATA_IN(data), DATA_IN(mac)) { BEGIN_IPC relocate(context, contextBase, attributes, attrSize); const CssmData dataBlob(DATA(data)); const CssmData macBlob(DATA(mac)); CALL(verifyMac, (&context, hKey, &dataBlob, &macBlob)); END_IPC(CSP) } // // Encryption/Decryption // kern_return_t tokend_server_encrypt(TOKEND_ARGS, CONTEXT_ARGS, KeyHandle hKey, DATA_IN(clear), DATA_OUT(cipher)) { BEGIN_IPC relocate(context, contextBase, attributes, attrSize); const CssmData clearBlob(DATA(clear)); OutputData cipherOut(cipher, cipherLength); CALL(encrypt, (&context, hKey, &clearBlob, &cipherOut)); END_IPC(CSP) } kern_return_t tokend_server_decrypt(TOKEND_ARGS, CONTEXT_ARGS, KeyHandle hKey, DATA_IN(cipher), DATA_OUT(clear)) { BEGIN_IPC relocate(context, contextBase, attributes, attrSize); const CssmData cipherBlob(DATA(cipher)); OutputData clearOut(clear, clearLength); CALL(decrypt, (&context, hKey, &cipherBlob, &clearOut)); END_IPC(CSP) } // // Key generation // kern_return_t tokend_server_generateKey(TOKEND_ARGS, CONTEXT_ARGS, COPY_IN(AccessCredentials, cred), COPY_IN(AclEntryPrototype, owner), uint32 usage, uint32 attrs, KeyHandle *hKey, COPY_OUT(CssmKey, key)) { BEGIN_IPC relocate(context, contextBase, attributes, attrSize); relocate(cred, credBase); relocate(owner, ownerBase); Return rKey(key, keyLength, keyBase); CALL(generateKey, (&context, cred, owner, usage, attrs, hKey, &rKey)); END_IPC(CSP) } kern_return_t tokend_server_generateKeyPair(TOKEND_ARGS, CONTEXT_ARGS, COPY_IN(AccessCredentials, cred), COPY_IN(AclEntryPrototype, owner), CSSM_KEYUSE pubUsage, CSSM_KEYATTR_FLAGS pubAttrs, CSSM_KEYUSE privUsage, CSSM_KEYATTR_FLAGS privAttrs, KeyHandle *hPubKey, COPY_OUT(CssmKey, pubKey), KeyHandle *hPrivKey, COPY_OUT(CssmKey, privKey)) { BEGIN_IPC relocate(context, contextBase, attributes, attrSize); relocate(cred, credBase); relocate(owner, ownerBase); Return rPubKey(pubKey, pubKeyLength, pubKeyBase); Return rPrivKey(privKey, privKeyLength, privKeyBase); CALL(generateKeyPair, (&context, cred, owner, pubUsage, pubAttrs, privUsage, privAttrs, hPubKey, &rPubKey, hPrivKey, &rPrivKey)); END_IPC(CSP) } // // Key wrapping and unwrapping // kern_return_t tokend_server_wrapKey(TOKEND_ARGS, CONTEXT_ARGS, KeyHandle hWrappingKey, COPY_IN(CssmKey, wrappingKey), COPY_IN(AccessCredentials, cred), KeyHandle hSubjectKey, COPY_IN(CssmKey, subjectKey), DATA_IN(descriptiveData), COPY_OUT(CssmWrappedKey, wrappedKey)) { BEGIN_IPC relocate(context, contextBase, attributes, attrSize); relocate(cred, credBase); relocate(wrappingKey, wrappingKeyBase); relocate(subjectKey, subjectKeyBase); CssmData ddata(DATA(descriptiveData)); Return rKey(wrappedKey, wrappedKeyLength, wrappedKeyBase); CALL(wrapKey, (&context, hWrappingKey, wrappingKey, cred, hSubjectKey, subjectKey, descriptiveData ? &ddata : NULL, &rKey)); END_IPC(CSP) } kern_return_t tokend_server_unwrapKey(TOKEND_ARGS, CONTEXT_ARGS, KeyHandle hWrappingKey, COPY_IN(CssmKey, wrappingKey), COPY_IN(AccessCredentials, cred), COPY_IN(AclEntryPrototype, owner), KeyHandle hPublicKey, COPY_IN(CssmKey, publicKey), COPY_IN(CssmWrappedKey, wrappedKey), uint32 usage, uint32 attrs, DATA_OUT(descriptiveData), KeyHandle *hUnwrappedKey, COPY_OUT(CssmKey, unwrappedKey)) { BEGIN_IPC relocate(context, contextBase, attributes, attrSize); relocate(cred, credBase); relocate(owner, ownerBase); relocate(wrappingKey, wrappingKeyBase); relocate(publicKey, publicKeyBase); relocate(wrappedKey, wrappedKeyBase); Return rKey(unwrappedKey, unwrappedKeyLength, unwrappedKeyBase); OutputData descriptives(descriptiveData, descriptiveDataLength); CALL(unwrapKey, (&context, hWrappingKey, wrappingKey, cred, owner, hPublicKey, publicKey, wrappedKey, usage, attrs, &descriptives, hUnwrappedKey, &rKey)); END_IPC(CSP) } // // Key derivation. // kern_return_t tokend_server_deriveKey(TOKEND_ARGS, CONTEXT_ARGS, KeyHandle hBaseKey, COPY_IN(CssmKey, baseKey), COPY_IN(AccessCredentials, cred), COPY_IN(AclEntryPrototype, owner), COPY_IN(CssmDeriveData,paramInput), DATA_OUT(paramOutput), CSSM_KEYUSE usage, CSSM_KEYATTR_FLAGS attrs, KeyHandle *hKey, COPY_OUT(CssmKey, key)) { BEGIN_IPC relocate(context, contextBase, attributes, attrSize); relocate(cred, credBase); relocate(owner, ownerBase); relocate(baseKey, baseKeyBase); relocate(paramInput, paramInputBase); if (!paramInput || paramInput->algorithm != context.algorithm()) CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS); Return rKey(key, keyLength, keyBase); CALL(deriveKey, (&context, hBaseKey, baseKey, cred, owner, ¶mInput->baseData, usage, attrs, hKey, &rKey)); OutputData(paramOutput, paramOutputLength) = paramInput->baseData; END_IPC(CSP) } // // Random generation // kern_return_t tokend_server_generateRandom(TOKEND_ARGS, CONTEXT_ARGS, DATA_OUT(result)) { BEGIN_IPC relocate(context, contextBase, attributes, attrSize); OutputData results(result, resultLength); CALL(generateRandom, (&context, &results)); END_IPC(CSP) } // // ACL management. // Watch out for the memory-management tap-dance. // kern_return_t tokend_server_getOwner(TOKEND_ARGS, AclKind kind, GenericHandle hHandle, COPY_OUT(AclOwnerPrototype, owner)) { BEGIN_IPC Return proto(owner, ownerLength, ownerBase); switch (kind) { case dbAcl: CALL(getDatabaseOwner, (&proto)); break; case keyAcl: CALL(getKeyOwner, (hHandle, &proto)); break; case objectAcl: CALL(getObjectOwner, (hHandle, &proto)); break; case loginAcl: CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); } END_IPC(CSP) } kern_return_t tokend_server_setOwner(TOKEND_ARGS, AclKind kind, GenericHandle key, COPY_IN(AccessCredentials, cred), COPY_IN(AclOwnerPrototype, owner)) { BEGIN_IPC relocate(cred, credBase); relocate(owner, ownerBase); CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); END_IPC(CSP) } kern_return_t tokend_server_getAcl(TOKEND_ARGS, AclKind kind, GenericHandle hObject, boolean_t haveTag, const char *inTag, uint32 *countp, COPY_OUT(AclEntryInfo, acls)) { BEGIN_IPC const char *tag = haveTag ? inTag : NULL; AclEntryInfo *infos; switch (kind) { case dbAcl: CALL(getDatabaseAcl, (tag, countp, (CSSM_ACL_ENTRY_INFO**)&infos)); break; case keyAcl: CALL(getKeyAcl, (hObject, tag, countp, (CSSM_ACL_ENTRY_INFO**)&infos)); break; case objectAcl: CALL(getObjectAcl, (hObject, tag, countp, (CSSM_ACL_ENTRY_INFO**)&infos)); break; case loginAcl: CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); } // package up (count, infos) as a return blob Copier aclsOut(infos, *countp); *aclsLength = aclsOut.length(); *acls = *aclsBase = aclsOut; aclsOut.keep(); END_IPC(CSP) } kern_return_t tokend_server_changeAcl(TOKEND_ARGS, AclKind kind, GenericHandle key, COPY_IN(AccessCredentials, cred), CSSM_ACL_EDIT_MODE mode, CSSM_ACL_HANDLE handle, COPY_IN(AclEntryInput, acl)) { BEGIN_IPC relocate(cred, credBase); relocate(acl, aclBase); AclEdit edit(mode, handle, acl); switch (kind) { case dbAcl: CALL(changeDatabaseAcl, (cred, &edit)); break; case keyAcl: CALL(changeKeyAcl, (key, cred, &edit)); break; case objectAcl: CALL(changeObjectAcl, (key, cred, &edit)); break; case loginAcl: CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); } END_IPC(CSP) } kern_return_t tokend_server_authenticate(TOKEND_ARGS, CSSM_DB_ACCESS_TYPE mode, COPY_IN(AccessCredentials, cred)) { BEGIN_IPC relocate(cred, credBase); CALL(authenticateDatabase, (mode, cred)); END_IPC(DL) } kern_return_t tokend_server_login(TOKEND_ARGS, COPY_IN(AccessCredentials, cred), DATA_IN(name)) { BEGIN_IPC relocate(cred, credBase); //CALL(login, (cred)); END_IPC(DL) } kern_return_t tokend_server_logout(TOKEND_ARGS) { BEGIN_IPC //CALL(logout, ()); END_IPC(DL) } // // Miscellaneous CSP-related calls // kern_return_t tokend_server_getStatistics(TOKEND_ARGS, CSPOperationalStatistics *statistics) { BEGIN_IPC CALL(getStatistics, (statistics)); END_IPC(CSP) } kern_return_t tokend_server_getTime(TOKEND_ARGS, CSSM_ALGORITHMS algorithm, DATA_OUT(data)) { BEGIN_IPC OutputData datas(data, dataLength); CALL(getTime, (algorithm, &datas)); END_IPC(CSP) } kern_return_t tokend_server_getCounter(TOKEND_ARGS, DATA_OUT(data)) { BEGIN_IPC OutputData datas(data, dataLength); CALL(getCounter, (&datas)); END_IPC(CSP) } kern_return_t tokend_server_selfVerify(TOKEND_ARGS) { BEGIN_IPC CALL(selfVerify, ()); END_IPC(CSP) } // // Passthrough calls (separate for CSP and DL passthroughs) // kern_return_t tokend_server_cspPassThrough(TOKEND_ARGS, uint32 id, CONTEXT_ARGS, KeyHandle hKey, COPY_IN(CssmKey, key), DATA_IN(inData), DATA_OUT(outData)) { BEGIN_IPC relocate(context, contextBase, attributes, attrSize); relocate(key, keyBase); const CssmData inDataBlob(DATA(inData)); OutputData outputs(outData, outDataLength); CALL(cspPassThrough, (id, &context, hKey, key, inData ? &inDataBlob : NULL, &outputs)); END_IPC(CSP) } kern_return_t tokend_server_dlPassThrough(TOKEND_ARGS, uint32 id, DATA_IN(inData), DATA_OUT(outData)) { BEGIN_IPC const CssmData inDataBlob(DATA(inData)); OutputData outputs(outData, outDataLength); CALL(dlPassThrough, (id, inData ? &inDataBlob : NULL, &outputs)); END_IPC(DL) } kern_return_t tokend_server_isLocked(TOKEND_ARGS, uint32 *locked) { BEGIN_IPC CALL(isLocked, (locked)); END_IPC(DL) }