bool SystemKeychainKey::update() { // if we checked recently, just assume it's okay if (mValid && mUpdateThreshold > Time::now()) return mValid; // check the file struct stat st; if (::stat(mPath.c_str(), &st)) { // something wrong with the file; can't use it mUpdateThreshold = Time::now() + Time::Interval(checkDelay); return mValid = false; } if (mValid && Time::Absolute(st.st_mtimespec) == mCachedDate) return true; mUpdateThreshold = Time::now() + Time::Interval(checkDelay); try { secnotice("syskc", "reading system unlock record from %s", mPath.c_str()); UnixPlusPlus::AutoFileDesc fd(mPath, O_RDONLY); if (fd.read(mBlob) != sizeof(mBlob)) return false; if (mBlob.isValid()) { mCachedDate = st.st_mtimespec; return mValid = true; } else return mValid = false; } catch (...) { secnotice("syskc", "system unlock record not available"); return false; } }
// Start OTR negotiation if we haven't already done so. SOSCoderStatus SOSCoderStart(SOSCoderRef coder, CFErrorRef *error) { CFMutableStringRef action = CFStringCreateMutable(kCFAllocatorDefault, 0); CFStringRef beginState = NULL; SOSCoderStatus result = kSOSCoderFailure; CFMutableDataRef startPacket = NULL; require_action_quiet(coder->sessRef, coderFailure, CFStringAppend(action, CFSTR("*** no otr session ***"))); beginState = CFCopyDescription(coder->sessRef); require_action_quiet(!coder->waitingForDataPacket, negotiatingOut, CFStringAppend(action, CFSTR("waiting for peer to send first data packet"))); require_action_quiet(!SecOTRSGetIsReadyForMessages(coder->sessRef), coderFailure, CFStringAppend(action, CFSTR("otr session ready")); result = kSOSCoderDataReturned); require_action_quiet(SecOTRSGetIsIdle(coder->sessRef), negotiatingOut, CFStringAppend(action, CFSTR("otr negotiating already"))); require_action_quiet(startPacket = CFDataCreateMutable(kCFAllocatorDefault, 0), coderFailure, SOSCreateError(kSOSErrorAllocationFailure, CFSTR("alloc failed"), NULL, error)); require_quiet(SOSOTRSAppendStartPacket(coder->sessRef, startPacket, error), coderFailure); CFRetainAssign(coder->pendingResponse, startPacket); negotiatingOut: result = kSOSCoderNegotiating; coderFailure: // Uber state log if (result == kSOSCoderFailure && error && *error) CFStringAppendFormat(action, NULL, CFSTR(" %@"), *error); secnotice("coder", "%@ %s %@ %@ returned %s", beginState, SecOTRPacketTypeString(startPacket), action, coder->sessRef, SOSCoderString(result)); CFReleaseNull(startPacket); CFReleaseSafe(beginState); CFRelease(action); return result; }
// Convert from securityd error codes to OSStatus for legacy API. OSStatus SecErrorGetOSStatus(CFErrorRef error) { OSStatus status; if (error == NULL) { status = errSecSuccess; } else { CFStringRef domain = CFErrorGetDomain(error); if (domain == NULL) { secerror("No error domain for error: %@", error); status = errSecInternal; } else if (CFEqual(kSecErrorDomain, domain)) { status = (OSStatus)CFErrorGetCode(error); } else if (CFEqual(kSecDbErrorDomain, domain)) { status = osstatus_for_s3e((int)CFErrorGetCode(error)); } else if (CFEqual(kSecErrnoDomain, domain)) { status = (OSStatus)CFErrorGetCode(error); } else if (CFEqual(kSecKernDomain, domain)) { status = osstatus_for_kern_return(CFErrorGetCode(error)); } else if (CFEqual(sSecXPCErrorDomain, domain)) { status = osstatus_for_xpc_error(CFErrorGetCode(error)); } else if (CFEqual(sSecDERErrorDomain, domain)) { status = osstatus_for_der_error(CFErrorGetCode(error)); } else { secnotice("securityd", "unknown error domain: %@ for error: %@", domain, error); status = errSecInternal; } } return status; }
// // Construct a Process object. // Process::Process(TaskPort taskPort, const ClientSetupInfo *info, const CommonCriteria::AuditToken &audit) : mTaskPort(taskPort), mByteFlipped(false), mPid(mTaskPort.pid()), mUid(0), mGid(0) { StLock<Mutex> _(*this); // set parent session parent(Session::find(audit.sessionId(), true)); // let's take a look at our wannabe client... if (mTaskPort.pid() != mPid) { secnotice("SS", "Task/pid setup mismatch pid=%d task=%d(%d)", mPid, mTaskPort.port(), mTaskPort.pid()); CssmError::throwMe(CSSMERR_CSSM_ADDIN_AUTHENTICATE_FAILED); // you lied! } setup(info); ClientIdentification::setup(this->pid()); // NB: ServerChild::find() should only be used to determine // *existence*. Don't use the returned Child object for anything else, // as it is not protected against its underlying process's destruction. if (this->pid() == getpid() // called ourselves (through some API). Do NOT record this as a "dirty" transaction || ServerChild::find<ServerChild>(this->pid())) // securityd's child; do not mark this txn dirty VProc::Transaction::deactivate(); secinfo("SS", "%p client new: pid:%d session:%d %s taskPort:%d uid:%d gid:%d", this, this->pid(), this->session().sessionId(), (char *)codePath(this->processCode()).c_str(), taskPort.port(), mUid, mGid); }
CFDataRef SOSUserKeyCreateGenerateParameters(CFErrorRef *error) { size_t saltlen = SALTMAX; uint8_t salt[saltlen]; size_t iterations = ITERATIONMIN; size_t keysize = 256; if(CCRandomCopyBytes(kCCRandomDefault, salt, sizeof(salt)) != kCCSuccess) { SOSCreateError(kSOSErrorProcessingFailure, CFSTR("CCRandomCopyBytes failed"), NULL, error); return NULL; } CFMutableDataRef result = CFDataCreateMutable(kCFAllocatorDefault, 0); CFDataSetLength(result, der_sizeof_pbkdf2_params(saltlen, salt, iterations, keysize)); uint8_t * encode = der_encode_pbkdf2_params(saltlen, salt, iterations, keysize, CFDataGetBytePtr(result), CFDataGetMutableBytePtr(result) + CFDataGetLength(result)); if (!encode) CFReleaseNull(result); if (result) { secnotice("keygen", "Created new parameters: iterations %zd, keysize %zd: %@", iterations, keysize, result); } return result; }
static void asynchttp_timer_proc(asynchttp_t *http) { CFStringRef req_meth = http->request ? CFHTTPMessageCopyRequestMethod(http->request) : NULL; CFURLRef req_url = http->request ? CFHTTPMessageCopyRequestURL(http->request) : NULL; secnotice("http", "Timeout during %@ %@.", req_meth, req_url); CFReleaseSafe(req_url); CFReleaseSafe(req_meth); asynchttp_complete(http); }
void UnixDb::close() { if (mDb) { secnotice("unixdb", "close(%p)", mDb); mDb->close(mDb); mDb = NULL; setFd(invalidFd); } }
static xpc_connection_t swca_create_connection(const char *name) { if (!name) name = kSWCAXPCServiceName; xpc_connection_t connection; connection = xpc_connection_create_mach_service(name, NULL, 0); xpc_connection_set_event_handler(connection, ^(xpc_object_t event) { const char *description = xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION); secnotice("xpc", "got event: %s", description); });
void UnixDb::open(const char *path, int flags, int mode, DBTYPE type) { if (DB* newDb = ::dbopen(path, flags, mode, type, NULL)) { close(); mDb = newDb; setFd(mDb->fd(mDb)); secnotice("unixdb", "open(%s,0x%x,0x%x,type=%d)=%p", path, flags, mode, type, mDb); } else UnixError::throwMe(); }
static CFDataRef SOSKeychainCopySavedAccountData() { CFErrorRef error = NULL; CFDataRef accountData = SOSItemCopy(kSOSAccountLabel, &error); if (!accountData) secnotice("account", "Failed to load account: %@", error); CFReleaseNull(error); return accountData; }
bool UnixDb::put(const CssmData &key, const CssmData &value, int flags) { Data dKey(key); Data dValue(value); int rc = mDb->put(mDb, &dKey, &dValue, flags); secnotice("unixdb", "put(%p,[:%ld],[:%ld],flags=0x%x)=%d", mDb, key.length(), value.length(), flags, rc); checkError(rc); return !rc; }
// // Screen a process setup request for an existing process. // This means the client has requested intialization even though we remember having // talked to it in the past. This could either be an exec(2), or the client could just // have forgotten all about its securityd client state. Or it could be an attack... // void Process::reset(TaskPort taskPort, const ClientSetupInfo *info, const CommonCriteria::AuditToken &audit) { StLock<Mutex> _(*this); if (taskPort != mTaskPort) { secnotice("SS", "Process %p(%d) reset mismatch (tp %d-%d)", this, pid(), taskPort.port(), mTaskPort.port()); //@@@ CssmError::throwMe(CSSM_ERRCODE_VERIFICATION_FAILURE); // liar } setup(info); CFCopyRef<SecCodeRef> oldCode = processCode(); ClientIdentification::setup(this->pid()); // re-constructs processCode() if (CFEqual(oldCode, processCode())) { secnotice("SS", "%p Client reset amnesia", this); } else { secnotice("SS", "%p Client reset full", this); CodeSigningHost::reset(); } }
SOSCoderRef SOSCoderCreate(SOSPeerInfoRef peerInfo, SOSFullPeerInfoRef myPeerInfo, CFErrorRef *error) { CFAllocatorRef allocator = CFGetAllocator(peerInfo); SOSCoderRef coder = calloc(1, sizeof(struct __OpaqueSOSCoder)); CFErrorRef localError = NULL; SecOTRFullIdentityRef myRef = NULL; SecOTRPublicIdentityRef peerRef = NULL; SecKeyRef privateKey = NULL; SecKeyRef publicKey = NULL; if (myPeerInfo && peerInfo) { privateKey = SOSFullPeerInfoCopyDeviceKey(myPeerInfo, &localError); require_quiet(privateKey, errOut); myRef = SecOTRFullIdentityCreateFromSecKeyRef(allocator, privateKey, &localError); require_quiet(myRef, errOut); CFReleaseNull(privateKey); publicKey = SOSPeerInfoCopyPubKey(peerInfo); peerRef = SecOTRPublicIdentityCreateFromSecKeyRef(allocator, publicKey, &localError); require_quiet(peerRef, errOut); coder->sessRef = SecOTRSessionCreateFromID(allocator, myRef, peerRef); require(coder->sessRef, errOut); coder->waitingForDataPacket = false; coder->pendingResponse = NULL; CFReleaseNull(publicKey); CFReleaseNull(privateKey); CFReleaseNull(myRef); CFReleaseNull(peerRef); } else { secnotice("coder", "NULL Coder requested, no transport security"); } SOSCoderStart(coder, NULL); return coder; errOut: secerror("Coder create failed: %@\n", localError ? localError : (CFTypeRef)CFSTR("No local error in SOSCoderCreate")); secerror("Coder create failed: %@\n", error ? *error : (CFTypeRef)CFSTR("WTF NULL?")); CFReleaseNull(myRef); CFReleaseNull(peerRef); CFReleaseNull(publicKey); CFReleaseNull(privateKey); free(coder); return NULL; }
void debugDumpUserParameters(CFStringRef message, CFDataRef parameters) { size_t saltlen = 0; const uint8_t *salt = NULL; size_t iterations = 0; size_t keysize = 0; const uint8_t *der = CFDataGetBytePtr(parameters); const uint8_t *der_end = der + CFDataGetLength(parameters); der = der_decode_pbkdf2_params(&saltlen, &salt, &iterations, &keysize, der, der_end); if (der == NULL) { secnotice("keygen", "failed to decode pbkdf2 params"); return; } BufferPerformWithHexString(salt, saltlen, ^(CFStringRef saltHex) { CFDataPerformWithHexString(parameters, ^(CFStringRef parametersHex) { secnotice("keygen", "%@ <Params: count: %zd, keysize: %zd, salt: %@, raw: %@>]", message, iterations, keysize, saltHex, parametersHex); });
SOSCoderStatus SOSCoderResendDH(SOSCoderRef coder, CFErrorRef *error) { if(coder->sessRef == NULL) return kSOSCoderDataReturned; CFMutableDataRef startPacket = CFDataCreateMutable(kCFAllocatorDefault, 0); SOSCoderStatus result = kSOSCoderFailure; require_noerr_quiet(SecOTRSAppendRestartPacket(coder->sessRef, startPacket), exit); secnotice("coder", "Resending OTR Start %@", startPacket); CFRetainAssign(coder->pendingResponse, startPacket); result = kSOSCoderNegotiating; exit: CFReleaseNull(startPacket); return result; }
uint32 CommonBlob::getCurrentVersionForDb(const char* dbName) { // Currently, the scheme is as follows: // in ~/Library/Keychains: // version_partition // Elsewhere: // version_MacOS_10_0` if(pathInHomeLibraryKeychains(dbName)) { return CommonBlob::getCurrentVersion(); } secnotice("integrity", "outside ~/Library/Keychains/; creating a old-style keychain"); return version_MacOS_10_0; }
uint32 CommonBlob::getCurrentVersion() { uint32 ret = version_MacOS_10_0; // If the integrity protections are turned on, use version_partition. // else, use version_MacOS_10_0. CFTypeRef integrity = (CFNumberRef)CFPreferencesCopyValue(CFSTR("KeychainIntegrity"), CFSTR("com.apple.security"), kCFPreferencesAnyUser, kCFPreferencesCurrentHost); if (integrity && CFGetTypeID(integrity) == CFBooleanGetTypeID()) { bool integrityProtections = CFBooleanGetValue((CFBooleanRef)integrity); if(integrityProtections) { secnotice("integrity", "creating a partition keychain; global is on"); ret = version_partition; } else { secnotice("integrity", "creating a old-style keychain; global is off"); ret = version_MacOS_10_0; } } else { secnotice("integrity", "global integrity not set, defaulting to on"); ret = version_partition; } CFReleaseSafe(integrity); return ret; }
bool UnixDb::get(const CssmData &key, CssmData &value, int flags) const { Data dKey(key); Data val; int rc = mDb->get(mDb, &dKey, &val, flags); secnotice("unixdb", "get(%p,[:%ld],flags=0x%x)=%d[:%ld]", mDb, key.length(), flags, rc, value.length()); checkError(rc); if (!rc) { value = val; return true; } else return false; }
SOSCoderStatus SOSCoderWrap(SOSCoderRef coder, CFDataRef message, CFMutableDataRef *codedMessage, CFStringRef clientId, CFErrorRef *error) { CFMutableStringRef action = CFStringCreateMutable(kCFAllocatorDefault, 0); SOSCoderStatus result = kSOSCoderDataReturned; CFStringRef beginState = NULL; CFMutableDataRef encoded = NULL; OSStatus otrStatus = 0; require_action_quiet(coder->sessRef, errOut, CFStringAppend(action, CFSTR("*** using null coder ***")); result = nullCoder(message, codedMessage)); beginState = CFCopyDescription(coder->sessRef); require_action_quiet(SecOTRSGetIsReadyForMessages(coder->sessRef), errOut, CFStringAppend(action, CFSTR("not ready")); result = kSOSCoderNegotiating); require_action_quiet(!coder->waitingForDataPacket, errOut, CFStringAppend(action, CFSTR("waiting for peer to send data packet first")); result = kSOSCoderNegotiating); require_action_quiet(encoded = CFDataCreateMutable(kCFAllocatorDefault, 0), errOut, SOSCreateErrorWithFormat(kSOSErrorAllocationFailure, NULL, error, NULL, CFSTR("%@ alloc failed"), clientId); result = kSOSCoderFailure); require_noerr_action_quiet(otrStatus = SecOTRSSignAndProtectMessage(coder->sessRef, message, encoded), errOut, SOSCreateErrorWithFormat(kSOSErrorEncodeFailure, (error != NULL) ? *error : NULL, error, NULL, CFSTR("%@ cannot protect message: %" PRIdOSStatus), clientId, otrStatus); CFReleaseNull(encoded); result = kSOSCoderFailure); *codedMessage = encoded; errOut: // Uber state log if (result == kSOSCoderFailure && error && *error) CFStringAppendFormat(action, NULL, CFSTR(" %@"), *error); secnotice("coder", "%@ %@ %s %@ %@ returned %s", clientId, beginState, SecOTRPacketTypeString(encoded), action, coder->sessRef, SOSCoderString(result)); CFReleaseSafe(beginState); CFRelease(action); return result; }
// // Main driver // int main(int argc, char *argv[]) { // clear the umask - we know what we're doing secnotice("SS", "starting umask was 0%o", ::umask(0)); ::umask(0); // tell the keychain (client) layer to turn off the server interface SecKeychainSetServerMode(); // program arguments (preset to defaults) bool debugMode = false; const char *bootstrapName = NULL; const char* messagingName = SharedMemoryCommon::kDefaultSecurityMessagesName; bool doFork = false; bool reExecute = false; int workerTimeout = 0; int maxThreads = 0; bool waitForClients = true; bool mdsIsInstalled = false; const char *tokenCacheDir = "/var/db/TokenCache"; const char *smartCardOptions = getenv("SMARTCARDS"); uint32_t keychainAclDefault = CSSM_ACL_KEYCHAIN_PROMPT_INVALID | CSSM_ACL_KEYCHAIN_PROMPT_UNSIGNED; unsigned int verbose = 0; // check for the Installation-DVD environment and modify some default arguments if found if (access("/etc/rc.cdrom", F_OK) == 0) { // /etc/rc.cdrom exists secnotice("SS", "starting in installmode"); smartCardOptions = "off"; // needs writable directories that aren't } // parse command line arguments extern char *optarg; extern int optind; int arg; while ((arg = getopt(argc, argv, "c:dE:imN:s:t:T:uvWX")) != -1) { switch (arg) { case 'c': tokenCacheDir = optarg; break; case 'd': debugMode = true; break; case 'E': /* was entropyFile, kept to preserve ABI */ break; case 'i': keychainAclDefault &= ~CSSM_ACL_KEYCHAIN_PROMPT_INVALID; break; case 'm': mdsIsInstalled = true; break; case 'N': bootstrapName = optarg; break; case 's': smartCardOptions = optarg; break; case 't': if ((maxThreads = atoi(optarg)) < 0) maxThreads = 0; break; case 'T': if ((workerTimeout = atoi(optarg)) < 0) workerTimeout = 0; break; case 'W': waitForClients = false; break; case 'u': keychainAclDefault &= ~CSSM_ACL_KEYCHAIN_PROMPT_UNSIGNED; break; case 'v': verbose++; break; case 'X': doFork = true; reExecute = true; break; default: usage(argv[0]); } } // take no non-option arguments if (optind < argc) usage(argv[0]); // figure out the bootstrap name if (!bootstrapName) { bootstrapName = getenv(SECURITYSERVER_BOOTSTRAP_ENV); if (!bootstrapName) { bootstrapName = SECURITYSERVER_BOOTSTRAP_NAME; } else { messagingName = bootstrapName; } } else { messagingName = bootstrapName; } // configure logging first if (debugMode) { Syslog::open(bootstrapName, LOG_AUTHPRIV, LOG_PERROR); Syslog::notice("%s started in debug mode", argv[0]); } else { Syslog::open(bootstrapName, LOG_AUTHPRIV, LOG_CONS); } // if we're not running as root in production mode, fail // in debug mode, issue a warning if (uid_t uid = getuid()) { #if defined(NDEBUG) Syslog::alert("Tried to run securityd as user %d: aborted", uid); fprintf(stderr, "You are not allowed to run securityd\n"); exit(1); #else fprintf(stderr, "securityd is unprivileged (uid=%d); some features may not work.\n", uid); #endif //NDEBUG } // turn into a properly diabolical daemon unless debugMode is on if (!debugMode && getppid() != 1) { if (!Daemon::incarnate(doFork)) exit(1); // can't daemonize if (reExecute && !Daemon::executeSelf(argv)) exit(1); // can't self-execute } // arm signal handlers; code below may generate signals we want to see if (signal(SIGCHLD, handleSignals) == SIG_ERR || signal(SIGINT, handleSignals) == SIG_ERR || signal(SIGTERM, handleSignals) == SIG_ERR || signal(SIGPIPE, handleSignals) == SIG_ERR #if !defined(NDEBUG) || signal(SIGUSR1, handleSignals) == SIG_ERR #endif //NDEBUG || signal(SIGUSR2, handleSignals) == SIG_ERR) { perror("signal"); exit(1); } // introduce all supported ACL subject types new AnyAclSubject::Maker(); new PasswordAclSubject::Maker(); new ProtectedPasswordAclSubject::Maker(); new PromptedAclSubject::Maker(); new ThresholdAclSubject::Maker(); new CommentAclSubject::Maker(); new ProcessAclSubject::Maker(); new CodeSignatureAclSubject::Maker(); new KeychainPromptAclSubject::Maker(keychainAclDefault); new PartitionAclSubject::Maker(); new PreAuthorizationAcls::OriginMaker(); new PreAuthorizationAcls::SourceMaker(); // establish the code equivalents database CodeSignatures codeSignatures; // create the main server object and register it Server server(codeSignatures, bootstrapName); // Remember the primary service port to send signal events to gMainServerPort = server.primaryServicePort(); // set server configuration from arguments, if specified if (workerTimeout) server.timeout(workerTimeout); if (maxThreads) server.maxThreads(maxThreads); server.floatingThread(true); server.waitForClients(waitForClients); server.verbosity(verbose); // create a smartcard monitor to manage external token devices gPCSC = new PCSCMonitor(server, tokenCacheDir, scOptions(smartCardOptions)); // create the RootSession object (if -d, give it graphics and tty attributes) RootSession rootSession(debugMode ? (sessionHasGraphicAccess | sessionHasTTY) : 0, server); // create a monitor thread to watch for audit session events AuditMonitor audits(gMainServerPort); audits.run(); // install MDS (if needed) and initialize the local CSSM server.loadCssm(mdsIsInstalled); // create the shared memory notification hub #ifndef __clang_analyzer__ new SharedMemoryListener(messagingName, kSharedMemoryPoolSize); #endif // __clang_analyzer__ // okay, we're ready to roll secnotice("SS", "Entering service as %s", (char*)bootstrapName); Syslog::notice("Entering service"); // go server.run(); // fell out of runloop (should not happen) Syslog::alert("Aborting"); return 1; }
// // Handle signals. // We send ourselves a message (through the "self" service), so actual // actions happen on the normal event loop path. Note that another thread // may be picking up the message immediately. // static void handleSignals(int sig) { secnotice("SS", "signal received: %d", sig); if (kern_return_t rc = self_client_handleSignal(gMainServerPort, mach_task_self(), sig)) Syslog::error("self-send failed (mach error %d)", rc); }
// // Change the session of a process. // This is the result of SessionCreate from a known process client. // void Process::changeSession(Session::SessionId sessionId) { // re-parent parent(Session::find(sessionId, true)); secnotice("SS", "%p client change session to %d", this, this->session().sessionId()); }
SOSCoderStatus SOSCoderUnwrap(SOSCoderRef coder, CFDataRef codedMessage, CFMutableDataRef *message, CFStringRef clientId, CFErrorRef *error) { if(codedMessage == NULL) return kSOSCoderDataReturned; if(coder->sessRef == NULL) return nullCoder(codedMessage, message); CFMutableStringRef action = CFStringCreateMutable(kCFAllocatorDefault, 0); /* This should be the "normal" case. We just use OTR to unwrap the received message. */ SOSCoderStatus result = kSOSCoderFailure; CFStringRef beginState = CFCopyDescription(coder->sessRef); enum SecOTRSMessageKind kind = SecOTRSGetMessageKind(coder->sessRef, codedMessage); switch (kind) { case kOTRNegotiationPacket: { /* If we're in here we haven't completed negotiating a session. Use SecOTRSProcessPacket() to go through the negotiation steps and immediately send a reply back if necessary using the sendBlock. This assumes the sendBlock is still available. */ CFMutableDataRef response = CFDataCreateMutable(kCFAllocatorDefault, 0); OSStatus ppstatus = errSecSuccess; if (response) { switch (ppstatus = SecOTRSProcessPacket(coder->sessRef, codedMessage, response)) { case errSecSuccess: if (CFDataGetLength(response) > 1) { CFStringAppendFormat(action, NULL, CFSTR("Sending OTR Response %s"), SecOTRPacketTypeString(response)); CFRetainAssign(coder->pendingResponse, response); result = kSOSCoderNegotiating; if (SecOTRSGetIsReadyForMessages(coder->sessRef)) { CFStringAppend(action, CFSTR(" begin waiting for data packet")); coder->waitingForDataPacket = true; } } else if(!SecOTRSGetIsReadyForMessages(coder->sessRef)) { CFStringAppend(action, CFSTR("stuck?")); result = kSOSCoderNegotiating; } else { CFStringAppend(action, CFSTR("completed negotiation")); result = kSOSCoderNegotiationCompleted; coder->waitingForDataPacket = false; } break; case errSecDecode: CFStringAppend(action, CFSTR("resending dh")); result = SOSCoderResendDH(coder, error); break; default: SOSCreateErrorWithFormat(kSOSErrorEncodeFailure, (error != NULL) ? *error : NULL, error, NULL, CFSTR("%@ Cannot negotiate session (%ld)"), clientId, (long)ppstatus); result = kSOSCoderFailure; break; }; } else { SOSCreateErrorWithFormat(kSOSErrorAllocationFailure, (error != NULL) ? *error : NULL, error, NULL, CFSTR("%@ Cannot allocate CFData"), clientId); result = kSOSCoderFailure; } CFReleaseNull(response); break; } case kOTRDataPacket: if(!SecOTRSGetIsReadyForMessages(coder->sessRef)) { CFStringAppend(action, CFSTR("not ready, resending DH packet")); SetCloudKeychainTraceValueForKey(kCloudKeychainNumberOfTimesSyncFailed, 1); CFStringAppend(action, CFSTR("not ready for data; resending dh")); result = SOSCoderResendDH(coder, error); } else { if (coder->waitingForDataPacket) { CFStringAppend(action, CFSTR("got data packet we were waiting for ")); coder->waitingForDataPacket = false; } CFMutableDataRef exposed = CFDataCreateMutable(0, 0); OSStatus otrResult = SecOTRSVerifyAndExposeMessage(coder->sessRef, codedMessage, exposed); CFStringAppend(action, CFSTR("verify and expose message")); if (otrResult) { if (otrResult == errSecOTRTooOld) { CFStringAppend(action, CFSTR(" too old")); result = kSOSCoderStaleEvent; } else { SecError(otrResult, error, CFSTR("%@ Cannot expose message: %" PRIdOSStatus), clientId, otrResult); secerror("%@ Decode OTR Protected Packet: %@", clientId, error ? *error : NULL); result = kSOSCoderFailure; } } else { CFStringAppend(action, CFSTR("decoded OTR protected packet")); *message = exposed; exposed = NULL; result = kSOSCoderDataReturned; } CFReleaseNull(exposed); } break; default: secerror("%@ Unknown packet type: %@", clientId, codedMessage); SOSCreateError(kSOSErrorDecodeFailure, CFSTR("Unknown packet type"), (error != NULL) ? *error : NULL, error); result = kSOSCoderFailure; break; }; // Uber state log if (result == kSOSCoderFailure && error && *error) CFStringAppendFormat(action, NULL, CFSTR(" %@"), *error); secnotice("coder", "%@ %@ %s %@ %@ returned %s", clientId, beginState, SecOTRPacketTypeString(codedMessage), action, coder->sessRef, SOSCoderString(result)); CFReleaseSafe(beginState); CFRelease(action); return result; }
void UnixDb::erase(const CssmData &key, int flags) { Data dKey(key); secnotice("unixdb", "delete(%p,[:%ld],flags=0x%x)", mDb, key.length(), flags); checkError(mDb->del(mDb, &dKey, flags)); }
SecKeyRef SOSUserKeygen(CFDataRef password, CFDataRef parameters, CFErrorRef *error) { size_t saltlen; const uint8_t *salt = NULL; size_t iterations = 0; size_t keysize = 0; const uint8_t *der = CFDataGetBytePtr(parameters); const uint8_t *der_end = der + CFDataGetLength(parameters); der = der_decode_pbkdf2_params(&saltlen, &salt, &iterations, &keysize, der, der_end); if (der == NULL) { SOSCreateErrorWithFormat(kSOSErrorDecodeFailure, NULL, error, NULL, CFSTR("Bad paramter encoding, got: %@"), parameters); return NULL; } if (keysize != 256) { SOSCreateErrorWithFormat(kSOSErrorUnsupported, NULL, error, NULL, CFSTR("Key size not supported, requested %zd."), keysize); return NULL; } if (saltlen < 4) { SOSCreateErrorWithFormat(kSOSErrorUnsupported, NULL, error, NULL, CFSTR("Salt length not supported, requested %zd."), saltlen); return NULL; } if (iterations < ITERATIONMIN) { SOSCreateErrorWithFormat(kSOSErrorUnsupported, NULL, error, NULL, CFSTR("Too few iterations, params suggested %zd."), iterations); return NULL; } const uint8_t *password_bytes = CFDataGetBytePtr(password); size_t password_length = CFDataGetLength(password); const size_t maxbytes = 128; ccec_const_cp_t cp = ccec_get_cp(keysize); struct ccrng_pbkdf2_prng_state pbkdf2_prng; ccec_full_ctx_decl_cp(cp, tmpkey); secnotice("keygen", "Generating key for: iterations %zd, keysize %zd: %@", iterations, keysize, parameters); if (ccrng_pbkdf2_prng_init(&pbkdf2_prng, maxbytes, password_length, password_bytes, saltlen, salt, iterations)) { SOSCreateError(kSOSErrorProcessingFailure, CFSTR("prng init failed"), NULL, error); return NULL; } if (ccec_generate_key(cp, (struct ccrng_state *)&pbkdf2_prng, tmpkey)) { SOSCreateError(kSOSErrorProcessingFailure, CFSTR("Keygen failed"), NULL, error); return NULL; } return ccec2SecKey(tmpkey); }