From 0e1db9d189370fed9f1993183ec38d748a8812f7 Mon Sep 17 00:00:00 2001 From: Apple Date: Thu, 6 Dec 2018 05:21:02 +0000 Subject: [PATCH] Security-58286.220.15.tar.gz --- Analytics/SFAnalytics.h | 1 + Analytics/SFAnalytics.m | 12 +- CircleJoinRequested/CircleJoinRequested.m | 54 ++- ....dfr.prompts-BBBAA77A32-C4EBFEA440.strings | 2 +- .../en.lproj/authorization.prompts.strings | 2 +- .../lib/SecRequirement.cpp | 10 +- .../lib/codedirectory.cpp | 18 +- OSX/libsecurity_codesigning/lib/policydb.cpp | 8 +- OSX/libsecurity_codesigning/lib/resources.cpp | 13 +- OSX/libsecurity_smime/lib/cmsasn1.c | 12 +- OSX/libsecurity_smime/lib/cmsreclist.c | 2 +- OSX/libsecurity_smime/lib/cmstpriv.h | 6 +- OSX/libsecurity_smime/lib/smimeutil.c | 8 +- OSX/libsecurity_utilities/lib/mach++.cpp | 17 + OSX/libsecurity_utilities/lib/mach++.h | 1 + OSX/libsecurity_utilities/lib/machserver.cpp | 7 + .../SecureObjectSync/SOSAccountRecovery.m | 2 +- .../SecureObjectSync/SOSEnsureBackup.m | 5 + .../Regressions/secitem/si-66-smime.c | 3 +- .../secitem/si-66-smime/smime_attr_emails.h | 279 ++++++++++++ OSX/sec/Security/SecAccessControl.c | 3 +- OSX/sec/Security/SecExports.exp-in | 2 + OSX/sec/Security/SecItemConstants.c | 2 + OSX/sec/SharedWebCredential/swcagent.m | 7 +- OSX/sec/securityd/OTATrustUtilities.h | 7 +- OSX/sec/securityd/OTATrustUtilities.m | 396 ++++++++++++++---- OSX/sec/securityd/SOSCloudCircleServer.m | 11 +- OSX/sec/securityd/SecPinningDb.h | 4 +- OSX/sec/securityd/SecPinningDb.m | 20 +- OSX/sec/securityd/SecRevocationNetworking.m | 19 +- OSX/sec/securityd/SecRevocationServer.c | 2 - OSX/shared_regressions/si-44-seckey-aks.m | 19 +- .../KeychainDataclassOwner.m | 3 +- keychain/SecItemPriv.h | 5 + keychain/ckks/CKKSKeychainView.m | 2 + keychain/ckks/CKKSViewManager.m | 5 + libsecurity_smime/lib/cmsasn1.c | 12 +- libsecurity_smime/lib/cmsreclist.c | 2 +- libsecurity_smime/lib/cmstpriv.h | 6 +- libsecurity_smime/lib/crypto-embedded.c | 6 +- libsecurity_smime/lib/smimeutil.c | 8 +- trust/SecTrust.h | 7 +- 42 files changed, 819 insertions(+), 191 deletions(-) diff --git a/Analytics/SFAnalytics.h b/Analytics/SFAnalytics.h index 130aec0f..9a135bd2 100644 --- a/Analytics/SFAnalytics.h +++ b/Analytics/SFAnalytics.h @@ -51,6 +51,7 @@ extern const NSTimeInterval SFAnalyticsSamplerIntervalOncePerReport; - (void)noteEventNamed:(NSString*)eventName; - (void)logResultForEvent:(NSString*)eventName hardFailure:(bool)hardFailure result:(NSError*)eventResultError; +- (void)logResultForEvent:(NSString*)eventName hardFailure:(bool)hardFailure result:(NSError*)eventResultError withAttributes:(NSDictionary*)attributes; // Track the state of a named value over time - (SFAnalyticsSampler*)addMetricSamplerForName:(NSString*)samplerName withTimeInterval:(NSTimeInterval)timeInterval block:(NSNumber* (^)(void))block; diff --git a/Analytics/SFAnalytics.m b/Analytics/SFAnalytics.m index 28e674cb..5f2d531a 100644 --- a/Analytics/SFAnalytics.m +++ b/Analytics/SFAnalytics.m @@ -310,12 +310,22 @@ const NSTimeInterval SFAnalyticsSamplerIntervalOncePerReport = -1.0; } - (void)logResultForEvent:(NSString*)eventName hardFailure:(bool)hardFailure result:(NSError*)eventResultError +{ + [self logResultForEvent:eventName hardFailure:hardFailure result:eventResultError withAttributes:nil]; +} + +- (void)logResultForEvent:(NSString*)eventName hardFailure:(bool)hardFailure result:(NSError*)eventResultError withAttributes:(NSDictionary*)attributes { if(!eventResultError) { [self logSuccessForEventNamed:eventName]; } else { // Make an Attributes dictionary - NSMutableDictionary* eventAttributes = [NSMutableDictionary dictionary]; + NSMutableDictionary* eventAttributes = nil; + if (attributes) { + eventAttributes = [attributes mutableCopy]; + } else { + eventAttributes = [NSMutableDictionary dictionary]; + } /* if we have underlying errors, capture the chain below the top-most error */ NSError *underlyingError = eventResultError.userInfo[NSUnderlyingErrorKey]; diff --git a/CircleJoinRequested/CircleJoinRequested.m b/CircleJoinRequested/CircleJoinRequested.m index 4f6ed2e2..1cbf8ad1 100644 --- a/CircleJoinRequested/CircleJoinRequested.m +++ b/CircleJoinRequested/CircleJoinRequested.m @@ -89,6 +89,12 @@ NSString *rejoinICDPUrl = @"prefs:root=APPLE_ACCOUNT&aaaction=CDP&command=re BOOL processRequests(CFErrorRef *error); +static bool PSKeychainSyncPrimaryAcccountExists(void) +{ + ACAccountStore *accountStore = [[ACAccountStore alloc] init]; + return [accountStore aa_primaryAppleAccount] != NULL; +} + static void PSKeychainSyncIsUsingICDP(void) { ACAccountStore *accountStore = [[ACAccountStore alloc] init]; @@ -753,7 +759,7 @@ static bool processEvents() CFErrorRef error = NULL; CFErrorRef departError = NULL; - SOSCCStatus circleStatus = SOSCCThisDeviceIsInCircle(&error); + SOSCCStatus circleStatus = SOSCCThisDeviceIsInCircleNonCached(&error); enum DepartureReason departureReason = SOSCCGetLastDepartureReason(&departError); // Error due to XPC failure does not provide information about the circle. @@ -782,29 +788,37 @@ static bool processEvents() } PSKeychainSyncIsUsingICDP(); - + + // Refresh because sometimes we're fixed elsewhere before we get here. + CFReleaseNull(error); + circleStatus = SOSCCThisDeviceIsInCircleNonCached(&error); + + /* + * Double check that the account still exists before doing anything rash (like posting a CFU or throw up a dialog) + */ + + if (!PSKeychainSyncPrimaryAcccountExists()) { + secnotice("cjr", "no primary account, bailing"); + return true; + } + if(_isAccountICDP){ if((circleStatus == kSOSCCError || circleStatus == kSOSCCCircleAbsent || circleStatus == kSOSCCNotInCircle) && _hasPostedFollowupAndStillInError == false) { - secnotice("cjr", "error from SOSCCThisDeviceIsInCircle: %@", error); + if(circleStatus == kSOSCCError) { + secnotice("cjr", "error from SOSCCThisDeviceIsInCircle: %@", error); + } secnotice("cjr", "iCDP: We need to get back into the circle"); doOnceInMain(^{ - if(_isAccountICDP){ - NSError *localError = nil; - CDPFollowUpController *cdpd = [[CDPFollowUpController alloc] init]; - CDPFollowUpContext *context = [CDPFollowUpContext contextForStateRepair]; - [cdpd postFollowUpWithContext:context error:&localError ]; - if(localError){ - secnotice("cjr", "request to CoreCDP to follow up failed: %@", localError); - } - else{ - secnotice("cjr", "CoreCDP handling follow up"); - _hasPostedFollowupAndStillInError = true; - } + NSError *localError = nil; + CDPFollowUpController *cdpd = [[CDPFollowUpController alloc] init]; + CDPFollowUpContext *context = [CDPFollowUpContext contextForStateRepair]; + [cdpd postFollowUpWithContext:context error:&localError ]; + if(localError){ + secnotice("cjr", "request to CoreCDP to follow up failed: %@", localError); } else{ - postKickedOutAlert(kSOSPasswordChanged); - state.lastCircleStatus = kSOSCCError; - [state writeToStorage]; + secnotice("cjr", "CoreCDP handling follow up"); + _hasPostedFollowupAndStillInError = true; } }); state.lastCircleStatus = circleStatus; @@ -821,9 +835,7 @@ static bool processEvents() _executeProcessEventsOnce = true; return false; } - } - else if(circleStatus == kSOSCCError && state.lastCircleStatus != kSOSCCError && (departureReason == kSOSNeverLeftCircle) - && !_isAccountICDP) { + } else if(circleStatus == kSOSCCError && state.lastCircleStatus != kSOSCCError && (departureReason == kSOSNeverLeftCircle)) { secnotice("cjr", "SA: error from SOSCCThisDeviceIsInCircle: %@", error); CFIndex errorCode = CFErrorGetCode(error); if(errorCode == kSOSErrorPublicKeyAbsent){ diff --git a/OSX/lib/en.lproj/authorization.dfr.prompts-BBBAA77A32-C4EBFEA440.strings b/OSX/lib/en.lproj/authorization.dfr.prompts-BBBAA77A32-C4EBFEA440.strings index 6ef38307..7cb67dfb 100644 --- a/OSX/lib/en.lproj/authorization.dfr.prompts-BBBAA77A32-C4EBFEA440.strings +++ b/OSX/lib/en.lproj/authorization.dfr.prompts-BBBAA77A32-C4EBFEA440.strings @@ -160,7 +160,7 @@ "com.apple.configurationprofiles.userprofile.trustcert" = "Touch ID to Trust a Certificate from a User Configuration Profile."; -"com.apple.app-sandbox.create-symlink" = "Touch ID to Install a Symlink into /usr/local/bin."; +"com.apple.app-sandbox.create-symlink" = "Touch ID to Install Symlinks into /usr/local."; "com.apple.app-sandbox.set-attributes" = "Touch ID to Change the Permissions of a Privileged File."; diff --git a/OSX/lib/en.lproj/authorization.prompts.strings b/OSX/lib/en.lproj/authorization.prompts.strings index 0253a7c5..932855d9 100644 --- a/OSX/lib/en.lproj/authorization.prompts.strings +++ b/OSX/lib/en.lproj/authorization.prompts.strings @@ -162,7 +162,7 @@ "com.apple.configurationprofiles.userprofile.trustcert" = "__APPNAME__ is trying to trust a certificate from a user configuration profile."; -"com.apple.app-sandbox.create-symlink" = "__APPNAME__ wants to install a symlink into /usr/local/bin."; +"com.apple.app-sandbox.create-symlink" = "__APPNAME__ wants to install symlinks in /usr/local."; "com.apple.app-sandbox.set-attributes" = "__APPNAME__ wants to change permissions of a privileged file."; diff --git a/OSX/libsecurity_codesigning/lib/SecRequirement.cpp b/OSX/libsecurity_codesigning/lib/SecRequirement.cpp index 1ed75082..7c44fcf6 100644 --- a/OSX/libsecurity_codesigning/lib/SecRequirement.cpp +++ b/OSX/libsecurity_codesigning/lib/SecRequirement.cpp @@ -217,13 +217,13 @@ OSStatus SecRequirementsCreateFromRequirements(CFDictionaryRef requirements, Sec if (requirements == NULL) return errSecCSObjectRequired; CFIndex count = CFDictionaryGetCount(requirements); - CFNumberRef keys[count]; - SecRequirementRef reqs[count]; - CFDictionaryGetKeysAndValues(requirements, (const void **)keys, (const void **)reqs); + vector keys_vector(count, NULL); + vector reqs_vector(count, NULL); + CFDictionaryGetKeysAndValues(requirements, (const void **)keys_vector.data(), (const void **)reqs_vector.data()); Requirements::Maker maker; for (CFIndex n = 0; n < count; n++) { - const Requirement *req = SecRequirement::required(reqs[n])->requirement(); - maker.add(cfNumber(keys[n]), req->clone()); + const Requirement *req = SecRequirement::required(reqs_vector[n])->requirement(); + maker.add(cfNumber(keys_vector[n]), req->clone()); } Requirements *reqset = maker.make(); // malloc'ed CodeSigning::Required(requirementSet) = makeCFDataMalloc(*reqset); // takes ownership of reqs diff --git a/OSX/libsecurity_codesigning/lib/codedirectory.cpp b/OSX/libsecurity_codesigning/lib/codedirectory.cpp index 5218ef4b..4d3c1c80 100644 --- a/OSX/libsecurity_codesigning/lib/codedirectory.cpp +++ b/OSX/libsecurity_codesigning/lib/codedirectory.cpp @@ -211,9 +211,9 @@ bool CodeDirectory::validateSlot(const void *data, size_t length, Slot slot, boo { secinfo("codedir", "%p validating slot %d", this, int(slot)); MakeHash hasher(this); - Hashing::Byte digest[hasher->digestLength()]; - generateHash(hasher, data, length, digest); - return memcmp(digest, getSlot(slot, preEncrypt), hasher->digestLength()) == 0; + vector digest_vector(hasher->digestLength()); + generateHash(hasher, data, length, digest_vector.data()); + return memcmp(digest_vector.data(), getSlot(slot, preEncrypt), hasher->digestLength()) == 0; } @@ -224,9 +224,9 @@ bool CodeDirectory::validateSlot(const void *data, size_t length, Slot slot, boo bool CodeDirectory::validateSlot(FileDesc fd, size_t length, Slot slot, bool preEncrypt) const { MakeHash hasher(this); - Hashing::Byte digest[hasher->digestLength()]; - generateHash(hasher, fd, digest, length); - return memcmp(digest, getSlot(slot, preEncrypt), hasher->digestLength()) == 0; + vector digest_vector(hasher->digestLength()); + generateHash(hasher, fd, digest_vector.data(), length); + return memcmp(digest_vector.data(), getSlot(slot, preEncrypt), hasher->digestLength()) == 0; } @@ -337,10 +337,10 @@ bool CodeDirectory::verifyMemoryContent(CFDataRef data, const Byte* digest) cons CFDataRef CodeDirectory::cdhash(bool truncate) const { MakeHash hash(this); - Hashing::Byte digest[hash->digestLength()]; + vector digest_vector(hash->digestLength()); hash->update(this, this->length()); - hash->finish(digest); - return makeCFData(digest, + hash->finish(digest_vector.data()); + return makeCFData(digest_vector.data(), truncate ? min(hash->digestLength(), size_t(kSecCodeCDHashLength)) : hash->digestLength()); } diff --git a/OSX/libsecurity_codesigning/lib/policydb.cpp b/OSX/libsecurity_codesigning/lib/policydb.cpp index 0be1a6cf..9e330e17 100644 --- a/OSX/libsecurity_codesigning/lib/policydb.cpp +++ b/OSX/libsecurity_codesigning/lib/policydb.cpp @@ -370,14 +370,14 @@ void PolicyDatabase::installExplicitSet(const char *authfile, const char *sigfil // load new data CFIndex count = CFDictionaryGetCount(content); - CFStringRef keys[count]; - CFDictionaryRef values[count]; - CFDictionaryGetKeysAndValues(content, (const void **)keys, (const void **)values); + vector keys_vector(count, NULL); + vector values_vector(count, NULL); + CFDictionaryGetKeysAndValues(content, (const void **)keys_vector.data(), (const void **)values_vector.data()); SQLite::Statement insert(*this, "INSERT INTO authority (type, allow, requirement, label, filter_unsigned, flags, remarks)" " VALUES (:type, 1, :requirement, 'GKE', :filter, :flags, :path)"); for (CFIndex n = 0; n < count; n++) { - CFDictionary info(values[n], errSecCSDbCorrupt); + CFDictionary info(values_vector[n], errSecCSDbCorrupt); uint32_t flags = kAuthorityFlagWhitelist; if (CFNumberRef versionRef = info.get("version")) { int version = cfNumber(versionRef); diff --git a/OSX/libsecurity_codesigning/lib/resources.cpp b/OSX/libsecurity_codesigning/lib/resources.cpp index 25ddade7..2c8a43ef 100644 --- a/OSX/libsecurity_codesigning/lib/resources.cpp +++ b/OSX/libsecurity_codesigning/lib/resources.cpp @@ -286,9 +286,10 @@ CFDataRef ResourceBuilder::hashFile(const char *path, CodeDirectory::HashAlgorit fd.fcntl(F_NOCACHE, true); // turn off page caching (one-pass) RefPointer hasher(CodeDirectory::hashFor(type)); hashFileData(fd, hasher.get()); - Hashing::Byte digest[hasher->digestLength()]; - hasher->finish(digest); - return CFDataCreate(NULL, digest, sizeof(digest)); + vector digest_vector(hasher->digestLength()); + hasher->finish(digest_vector.data()); + return CFDataCreate(NULL, digest_vector.data(), + digest_vector.size() * sizeof(Hashing::Byte)); } @@ -306,9 +307,9 @@ CFMutableDictionaryRef ResourceBuilder::hashFile(const char *path, CodeDirectory CFMutableDictionaryRef resultRef = result; CodeDirectory::multipleHashFileData(fd, 0, types, ^(CodeDirectory::HashAlgorithm type, Security::DynamicHash *hasher) { size_t length = hasher->digestLength(); - Hashing::Byte digest[length]; - hasher->finish(digest); - CFDictionaryAddValue(resultRef, CFTempString(hashName(type)), CFTempData(digest, length)); + vector digest_vector(length); + hasher->finish(digest_vector.data()); + CFDictionaryAddValue(resultRef, CFTempString(hashName(type)), CFTempData(digest_vector.data(), length)); }); return result.yield(); } diff --git a/OSX/libsecurity_smime/lib/cmsasn1.c b/OSX/libsecurity_smime/lib/cmsasn1.c index 7a70f886..bbb53f57 100644 --- a/OSX/libsecurity_smime/lib/cmsasn1.c +++ b/OSX/libsecurity_smime/lib/cmsasn1.c @@ -322,11 +322,13 @@ static const SecAsn1Template SecCmsOriginatorIdentifierOrKeyTemplate[] = { const SecAsn1Template SecCmsRecipientKeyIdentifierTemplate[] = { { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SecCmsRecipientKeyIdentifier) }, - { SEC_ASN1_OCTET_STRING, - offsetof(SecCmsRecipientKeyIdentifier,subjectKeyIdentifier) }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_OCTET_STRING, - offsetof(SecCmsRecipientKeyIdentifier,date) }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_OCTET_STRING, + { SEC_ASN1_INLINE | SEC_ASN1_OCTET_STRING, + offsetof(SecCmsRecipientKeyIdentifier,subjectKeyIdentifier), + SEC_ASN1_SUB(kSecAsn1OctetStringTemplate) }, + { SEC_ASN1_INLINE | SEC_ASN1_OPTIONAL | SEC_ASN1_GENERALIZED_TIME, + offsetof(SecCmsRecipientKeyIdentifier,date), + SEC_ASN1_SUB(kSecAsn1GeneralizedTimeTemplate) }, + { SEC_ASN1_INLINE | SEC_ASN1_OPTIONAL | SEC_ASN1_ANY, offsetof(SecCmsRecipientKeyIdentifier,other) }, { 0 } }; diff --git a/OSX/libsecurity_smime/lib/cmsreclist.c b/OSX/libsecurity_smime/lib/cmsreclist.c index cfadee8c..ecf3179e 100644 --- a/OSX/libsecurity_smime/lib/cmsreclist.c +++ b/OSX/libsecurity_smime/lib/cmsreclist.c @@ -98,7 +98,7 @@ nss_cms_recipients_traverse(SecCmsRecipientInfoRef *recipientinfos, SecCmsRecipi break; case SecCmsKeyAgreeRecipientIDRKeyID: rle->kind = RLSubjKeyID; - rle->id.subjectKeyID = rek->recipientIdentifier.id.recipientKeyIdentifier.subjectKeyIdentifier; + rle->id.subjectKeyID = &rek->recipientIdentifier.id.recipientKeyIdentifier.subjectKeyIdentifier; break; } recipient_list[rlindex++] = rle; diff --git a/OSX/libsecurity_smime/lib/cmstpriv.h b/OSX/libsecurity_smime/lib/cmstpriv.h index 5d0f5617..4c78e6e4 100644 --- a/OSX/libsecurity_smime/lib/cmstpriv.h +++ b/OSX/libsecurity_smime/lib/cmstpriv.h @@ -322,9 +322,9 @@ struct SecCmsOriginatorIdentifierOrKeyStr { typedef struct SecCmsOriginatorIdentifierOrKeyStr SecCmsOriginatorIdentifierOrKey; struct SecCmsRecipientKeyIdentifierStr { - CSSM_DATA_PTR subjectKeyIdentifier; - CSSM_DATA_PTR date; /* optional */ - CSSM_DATA_PTR other; /* optional */ + CSSM_DATA subjectKeyIdentifier; + CSSM_DATA date; /* optional */ + CSSM_DATA other; /* optional */ }; typedef struct SecCmsRecipientKeyIdentifierStr SecCmsRecipientKeyIdentifier; diff --git a/OSX/libsecurity_smime/lib/smimeutil.c b/OSX/libsecurity_smime/lib/smimeutil.c index 61bd6f05..569c7f65 100644 --- a/OSX/libsecurity_smime/lib/smimeutil.c +++ b/OSX/libsecurity_smime/lib/smimeutil.c @@ -117,8 +117,8 @@ static const SecAsn1Template smime_encryptionkeypref_template[] = { NSSSMIMEEncryptionKeyPref_IssuerSN }, { SEC_ASN1_POINTER | SEC_ASN1_CONTEXT_SPECIFIC | 1, offsetof(NSSSMIMEEncryptionKeyPreference,id.recipientKeyID), - SecCmsRecipientKeyIdentifierTemplate, - NSSSMIMEEncryptionKeyPref_IssuerSN }, + SEC_ASN1_SUB(SecCmsRecipientKeyIdentifierTemplate), + NSSSMIMEEncryptionKeyPref_RKeyID }, { SEC_ASN1_POINTER | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 2, offsetof(NSSSMIMEEncryptionKeyPreference,id.subjectKeyID), SEC_ASN1_SUB(kSecAsn1OctetStringTemplate), @@ -733,8 +733,10 @@ SecSMIMEGetCertFromEncryptionKeyPreference(SecKeychainRef keychainOrArray, CSSM_ cert = CERT_FindCertByIssuerAndSN(keychainOrArray, rawCerts, NULL, tmppoolp, ekp.id.issuerAndSN); break; case NSSSMIMEEncryptionKeyPref_RKeyID: + cert = CERT_FindCertBySubjectKeyID(keychainOrArray, rawCerts, NULL, &ekp.id.recipientKeyID->subjectKeyIdentifier); + break; case NSSSMIMEEncryptionKeyPref_SubjectKeyID: - cert = CERT_FindCertBySubjectKeyID(keychainOrArray, rawCerts, NULL, ekp.id.subjectKeyID); + cert = CERT_FindCertBySubjectKeyID(keychainOrArray, rawCerts, NULL, ekp.id.subjectKeyID); break; default: PORT_Assert(0); diff --git a/OSX/libsecurity_utilities/lib/mach++.cpp b/OSX/libsecurity_utilities/lib/mach++.cpp index c8271d94..ab6bb982 100644 --- a/OSX/libsecurity_utilities/lib/mach++.cpp +++ b/OSX/libsecurity_utilities/lib/mach++.cpp @@ -418,6 +418,23 @@ bool Message::sendReceive(mach_port_t receivePort, NULL, 0)); } +/* cribbed from libdispatch: _dispatch_mach_msg_get_audit_trailer */ +mach_msg_audit_trailer_t * +Message::auditTrailer() +{ + mach_msg_header_t *hdr = &mBuffer->Head; + mach_msg_trailer_t *tlr = NULL; + mach_msg_audit_trailer_t *audit_tlr = NULL; + tlr = (mach_msg_trailer_t *)((unsigned char *)hdr + + round_msg(hdr->msgh_size)); + // The trailer should always be of format zero. + if (tlr->msgh_trailer_type == MACH_MSG_TRAILER_FORMAT_0) { + if (tlr->msgh_trailer_size >= sizeof(mach_msg_audit_trailer_t)) { + audit_tlr = (mach_msg_audit_trailer_t *)tlr; + } + } + return audit_tlr; +} // // Debug dumping of ports etc. diff --git a/OSX/libsecurity_utilities/lib/mach++.h b/OSX/libsecurity_utilities/lib/mach++.h index b2fe9425..dba14c37 100644 --- a/OSX/libsecurity_utilities/lib/mach++.h +++ b/OSX/libsecurity_utilities/lib/mach++.h @@ -292,6 +292,7 @@ public: mach_msg_id_t msgId() const { return mBuffer->Head.msgh_id; } mach_msg_bits_t bits() const { return mBuffer->Head.msgh_bits; } kern_return_t returnCode() const { return mBuffer->RetCode; } + mach_msg_audit_trailer_t *auditTrailer(); void localPort(mach_port_t p) { mBuffer->Head.msgh_local_port = p; } void remotePort(mach_port_t p) { mBuffer->Head.msgh_remote_port = p; } diff --git a/OSX/libsecurity_utilities/lib/machserver.cpp b/OSX/libsecurity_utilities/lib/machserver.cpp index 8f825ba2..29ffa83a 100644 --- a/OSX/libsecurity_utilities/lib/machserver.cpp +++ b/OSX/libsecurity_utilities/lib/machserver.cpp @@ -40,6 +40,8 @@ # include #endif +#define SEC_MACH_AUDIT_TOKEN_PID (5) + namespace Security { namespace MachPlusPlus { @@ -245,6 +247,11 @@ void MachServer::runServerThread(bool doTimeout) bufRequest.msgId() <= MACH_NOTIFY_LAST) { // mach kernel notification message // we assume this is quick, so no thread arbitration here + mach_msg_audit_trailer_t *tlr = bufRequest.auditTrailer(); + if (tlr == NULL || tlr->msgh_audit.val[SEC_MACH_AUDIT_TOKEN_PID] != 0) { + secnotice("machserver", "ignoring invalid notify message"); + continue; + } cdsa_notify_server(bufRequest, bufReply); } else { // normal request message diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSAccountRecovery.m b/OSX/sec/SOSCircle/SecureObjectSync/SOSAccountRecovery.m index b93c6b5e..e9757938 100644 --- a/OSX/sec/SOSCircle/SecureObjectSync/SOSAccountRecovery.m +++ b/OSX/sec/SOSCircle/SecureObjectSync/SOSAccountRecovery.m @@ -229,7 +229,7 @@ void SOSAccountEnsureRecoveryRing(SOSAccount* account) { return; } - CFStringRef accountDSID = SOSAccountGetValue(account, kSOSDSIDKey, NULL); // murfxxx this needs to be consulted still + CFStringRef accountDSID = SOSAccountGetValue(account, kSOSDSIDKey, NULL); SOSRecoveryKeyBagRef acctRKBG = SOSAccountCopyRecoveryKeyBagEntry(kCFAllocatorDefault, account, NULL); SOSRecoveryKeyBagRef ringRKBG = SOSAccountCopyRecoveryKeyBag(kCFAllocatorDefault, account, NULL); if(!SOSRecoveryKeyBagDSIDIs(ringRKBG, accountDSID)) CFReleaseNull(ringRKBG); diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSEnsureBackup.m b/OSX/sec/SOSCircle/SecureObjectSync/SOSEnsureBackup.m index be8a73fc..e9389196 100644 --- a/OSX/sec/SOSCircle/SecureObjectSync/SOSEnsureBackup.m +++ b/OSX/sec/SOSCircle/SecureObjectSync/SOSEnsureBackup.m @@ -50,6 +50,11 @@ void SOSEnsureBackupWhileUnlocked(void) { secnotice("engine", "Performing keychain backup after unlock because backing up while locked failed"); SOSAccount *account = (__bridge SOSAccount *)(SOSKeychainAccountGetSharedAccount()); + if(!account) { + secnotice("ckks", "Failed to get account object"); + return; + } + [account performTransaction:^(SOSAccountTransaction *transaction) { CFErrorRef error = NULL; NSSet* set = CFBridgingRelease(SOSAccountCopyBackupPeersAndForceSync(transaction, &error)); diff --git a/OSX/sec/Security/Regressions/secitem/si-66-smime.c b/OSX/sec/Security/Regressions/secitem/si-66-smime.c index 8fc837e5..0ad24d90 100644 --- a/OSX/sec/Security/Regressions/secitem/si-66-smime.c +++ b/OSX/sec/Security/Regressions/secitem/si-66-smime.c @@ -2799,6 +2799,7 @@ out: static void test_smime_attrs(void) { testEncKeyPrefs(_thunderbird_ua_content, sizeof(_thunderbird_ua_content), _thunderbird_ua_cms, sizeof(_thunderbird_ua_cms)); testEncKeyPrefs(_outlook15_ua_content, sizeof(_outlook15_ua_content), _outlook15_ua_cms, sizeof(_outlook15_ua_cms)); + testEncKeyPrefs(_recipientKeyID_content, sizeof(_recipientKeyID_content), _recipientKeyID_cms, sizeof(_recipientKeyID_cms)); } static void test_sign_no_priv(void) { @@ -2874,7 +2875,7 @@ out: int si_66_smime(int argc, char *const *argv) { - plan_tests(33+2+9); + plan_tests(33+3+9); tests(); test_smime_attrs(); diff --git a/OSX/sec/Security/Regressions/secitem/si-66-smime/smime_attr_emails.h b/OSX/sec/Security/Regressions/secitem/si-66-smime/smime_attr_emails.h index 8a77186f..7dfe2bb5 100644 --- a/OSX/sec/Security/Regressions/secitem/si-66-smime/smime_attr_emails.h +++ b/OSX/sec/Security/Regressions/secitem/si-66-smime/smime_attr_emails.h @@ -1320,3 +1320,282 @@ unsigned char _outlook15_ua_cms[] = { 0x17, 0x00, 0x20, 0xfd, 0x36, 0x18, 0x75, 0x77, 0x10, 0x57, 0x39, 0xf7, 0xe2, 0x52, 0x92, 0xa3, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +uint8_t _recipientKeyID_content[] = { + 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, + 0x6c, 0x61, 0x69, 0x6e, 0x3b, 0x20, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x22, 0x49, 0x53, 0x4f, 0x2d, 0x32, + 0x30, 0x32, 0x32, 0x2d, 0x4a, 0x50, 0x22, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x72, 0x61, + 0x6e, 0x73, 0x66, 0x65, 0x72, 0x2d, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x37, 0x62, 0x69, 0x74, + 0x0d, 0x0a, 0x0d, 0x0a, 0x0d, 0x0a, 0x2d, 0x2d, 0x20, 0x0d, 0x0a, 0x1b, 0x24, 0x42, 0x31, 0x4a, 0x30, 0x42, 0x1b, 0x28, + 0x42, 0x20, 0x1b, 0x24, 0x42, 0x4d, 0x24, 0x34, 0x75, 0x30, 0x74, 0x1b, 0x28, 0x42, 0x20, 0x28, 0x1b, 0x24, 0x42, 0x24, + 0x4a, 0x24, 0x2c, 0x24, 0x64, 0x24, 0x39, 0x1b, 0x28, 0x42, 0x20, 0x1b, 0x24, 0x42, 0x24, 0x66, 0x24, 0x2d, 0x24, 0x4e, + 0x24, 0x56, 0x1b, 0x28, 0x42, 0x29, 0x20, 0x3c, 0x6e, 0x61, 0x67, 0x61, 0x79, 0x61, 0x73, 0x75, 0x40, 0x79, 0x75, 0x6b, + 0x69, 0x6e, 0x6f, 0x62, 0x75, 0x2e, 0x6a, 0x70, 0x3e, 0x0d, 0x0a +}; + +uint8_t _recipientKeyID_cms[] = { + 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x80, 0x30, 0x82, 0x14, 0x80, 0x02, + 0x01, 0x03, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x30, + 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, 0x10, 0xfd, 0x30, 0x82, 0x05, 0x33, + 0x30, 0x82, 0x04, 0x1b, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x43, 0x3d, 0xe2, 0x93, 0xa4, 0xed, 0xf7, 0x8d, 0x8b, + 0x98, 0x93, 0x72, 0x76, 0xdd, 0x46, 0xe7, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, + 0x05, 0x00, 0x30, 0x81, 0x97, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x1b, + 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4d, 0x61, 0x6e, + 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, + 0x6c, 0x66, 0x6f, 0x72, 0x64, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x11, 0x43, 0x4f, 0x4d, 0x4f, + 0x44, 0x4f, 0x20, 0x43, 0x41, 0x20, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x31, 0x3d, 0x30, 0x3b, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x34, 0x43, 0x4f, 0x4d, 0x4f, 0x44, 0x4f, 0x20, 0x52, 0x53, 0x41, 0x20, 0x43, 0x6c, 0x69, 0x65, 0x6e, + 0x74, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x6e, 0x64, + 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, + 0x31, 0x38, 0x30, 0x32, 0x32, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x39, 0x30, 0x32, 0x32, + 0x33, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x25, 0x31, 0x23, 0x30, 0x21, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x14, 0x6e, 0x61, 0x67, 0x61, 0x79, 0x61, 0x73, 0x75, 0x40, 0x79, 0x75, 0x6b, 0x69, + 0x6e, 0x6f, 0x62, 0x75, 0x2e, 0x6a, 0x70, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, + 0xb2, 0x9b, 0x24, 0xac, 0xc7, 0x87, 0xc2, 0x39, 0xf3, 0x11, 0x57, 0x69, 0x29, 0x47, 0x52, 0x38, 0x8c, 0x2a, 0xbc, 0xdd, + 0x9e, 0xfd, 0x2e, 0x5f, 0x0c, 0x3b, 0x36, 0x66, 0x30, 0xc0, 0x7f, 0x3f, 0xff, 0xcd, 0x53, 0xfc, 0x04, 0xab, 0x94, 0xb8, + 0xfa, 0xa9, 0x65, 0xed, 0xa6, 0x40, 0x34, 0x80, 0x86, 0x61, 0xba, 0x7e, 0x2f, 0xba, 0x37, 0x97, 0x97, 0xf3, 0xe0, 0x16, + 0x50, 0x27, 0xf3, 0x52, 0xe9, 0x53, 0x2c, 0x7c, 0x30, 0x43, 0xdf, 0xa4, 0x66, 0x87, 0x26, 0x3a, 0xff, 0x68, 0x62, 0x18, + 0xbb, 0x84, 0x6d, 0x64, 0x1e, 0xc5, 0x7c, 0x91, 0xa4, 0x9c, 0xe9, 0x7d, 0x87, 0x8f, 0x22, 0xe8, 0x26, 0xa6, 0x35, 0xc9, + 0xf2, 0x61, 0xf6, 0xf3, 0x34, 0xd5, 0x06, 0x61, 0x75, 0x16, 0x57, 0xc5, 0xc9, 0x43, 0xd9, 0xf0, 0xd6, 0x3b, 0xb4, 0x17, + 0xe9, 0xc6, 0x34, 0xa1, 0xd7, 0x39, 0x14, 0x36, 0x7f, 0xb3, 0xb9, 0x9f, 0xa4, 0x2b, 0xf2, 0x28, 0xd0, 0x5d, 0xfe, 0x29, + 0x49, 0xa2, 0x18, 0x54, 0x80, 0x86, 0x13, 0x4a, 0x33, 0xb0, 0x6e, 0xf9, 0x00, 0x7e, 0x87, 0xd1, 0xc5, 0x13, 0x56, 0x94, + 0x78, 0x86, 0x7e, 0x31, 0xf5, 0x5e, 0xc8, 0x9b, 0x41, 0x4f, 0x8a, 0x76, 0x0f, 0xdd, 0xe6, 0xae, 0x08, 0x58, 0xae, 0x8d, + 0xd1, 0x2f, 0x3d, 0x06, 0xc5, 0xef, 0xbc, 0xce, 0x38, 0x47, 0xfd, 0x7f, 0x5b, 0x84, 0x31, 0xb1, 0x41, 0x1d, 0xfd, 0x7c, + 0x65, 0xc5, 0x0d, 0x82, 0x6a, 0xc1, 0x82, 0x42, 0xc0, 0xdb, 0x21, 0x15, 0x8a, 0x76, 0x69, 0x4a, 0x98, 0x69, 0x85, 0x0c, + 0x82, 0x88, 0xb0, 0xf7, 0x8d, 0x91, 0x9a, 0xe8, 0xf8, 0xb0, 0x9a, 0x86, 0xf8, 0x3d, 0x2f, 0xba, 0x16, 0x0f, 0x45, 0x30, + 0xb3, 0xfd, 0xf2, 0xd0, 0xb8, 0x86, 0x76, 0x69, 0x83, 0xd8, 0xae, 0x51, 0xdc, 0x71, 0xf3, 0x5d, 0x02, 0x03, 0x01, 0x00, + 0x01, 0xa3, 0x82, 0x01, 0xea, 0x30, 0x82, 0x01, 0xe6, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, + 0x80, 0x14, 0x82, 0xaf, 0x6c, 0x8c, 0xf8, 0xc5, 0xfe, 0x96, 0x61, 0x7c, 0xe8, 0x1f, 0x3d, 0x2b, 0x71, 0x48, 0x5e, 0xc4, + 0x8b, 0xc0, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x31, 0x34, 0xad, 0xb0, 0xf8, 0xc0, 0x87, + 0x77, 0xe5, 0x9b, 0x2a, 0xda, 0x75, 0x10, 0x98, 0x65, 0xae, 0xac, 0xfc, 0x84, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, + 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, + 0x02, 0x30, 0x00, 0x30, 0x20, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x19, 0x30, 0x17, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, + 0x05, 0x07, 0x03, 0x04, 0x06, 0x0b, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xb2, 0x31, 0x01, 0x03, 0x05, 0x02, 0x30, 0x11, 0x06, + 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x01, 0x04, 0x04, 0x03, 0x02, 0x05, 0x20, 0x30, 0x46, 0x06, 0x03, + 0x55, 0x1d, 0x20, 0x04, 0x3f, 0x30, 0x3d, 0x30, 0x3b, 0x06, 0x0c, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xb2, 0x31, 0x01, 0x02, + 0x01, 0x01, 0x01, 0x30, 0x2b, 0x30, 0x29, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x1d, 0x68, + 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, + 0x2e, 0x6e, 0x65, 0x74, 0x2f, 0x43, 0x50, 0x53, 0x30, 0x5a, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x53, 0x30, 0x51, 0x30, + 0x4f, 0xa0, 0x4d, 0xa0, 0x4b, 0x86, 0x49, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x63, 0x6f, + 0x6d, 0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x43, 0x4f, 0x4d, 0x4f, 0x44, 0x4f, 0x52, 0x53, 0x41, + 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x61, 0x6e, 0x64, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x43, 0x41, 0x2e, 0x63, 0x72, 0x6c, + 0x30, 0x81, 0x8b, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x7f, 0x30, 0x7d, 0x30, 0x55, 0x06, + 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x49, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, + 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x43, 0x4f, 0x4d, 0x4f, 0x44, + 0x4f, 0x52, 0x53, 0x41, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6e, 0x64, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x43, 0x41, + 0x2e, 0x63, 0x72, 0x74, 0x30, 0x24, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x18, 0x68, 0x74, + 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, 0x63, + 0x6f, 0x6d, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x11, 0x04, 0x18, 0x30, 0x16, 0x81, 0x14, 0x6e, 0x61, 0x67, 0x61, 0x79, + 0x61, 0x73, 0x75, 0x40, 0x79, 0x75, 0x6b, 0x69, 0x6e, 0x6f, 0x62, 0x75, 0x2e, 0x6a, 0x70, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0xb5, 0x1e, 0xd2, 0xd6, 0x87, + 0x90, 0x6b, 0x00, 0x9d, 0xed, 0x82, 0x7d, 0xc3, 0x47, 0xbf, 0xb3, 0x7a, 0x0d, 0x3d, 0xf8, 0x6d, 0xb7, 0x7c, 0x4a, 0xd9, + 0xb1, 0x4f, 0x1e, 0x10, 0x69, 0x19, 0x39, 0x65, 0x2d, 0x0d, 0x92, 0x0f, 0x5e, 0xf1, 0x0a, 0x66, 0x5a, 0x55, 0x52, 0x96, + 0x48, 0x95, 0x4a, 0x4f, 0xf5, 0x12, 0x6c, 0x31, 0x9f, 0x92, 0x71, 0xa8, 0x1d, 0x06, 0x62, 0xe7, 0xed, 0xb0, 0x18, 0x84, + 0xdf, 0x60, 0x94, 0xb2, 0x59, 0x05, 0xe5, 0xac, 0xc7, 0xc4, 0xe0, 0xd7, 0xea, 0xfb, 0x53, 0xbe, 0x9c, 0x6a, 0xa6, 0x80, + 0x84, 0xc3, 0x2a, 0xb5, 0x20, 0xe6, 0x7d, 0x27, 0x8c, 0xc1, 0x9d, 0x2b, 0xb3, 0x03, 0x68, 0x5a, 0xdb, 0xce, 0xc9, 0xdf, + 0x51, 0xc6, 0xf2, 0x5f, 0x1f, 0x8c, 0xb1, 0x4a, 0x32, 0x49, 0x7a, 0x57, 0xee, 0xea, 0xf0, 0x38, 0x6a, 0x48, 0xcc, 0xd0, + 0xce, 0x12, 0xf6, 0x71, 0xc0, 0xbe, 0xe0, 0x62, 0x37, 0xc0, 0x92, 0xfa, 0x95, 0xc0, 0x2e, 0x71, 0x05, 0x40, 0x0b, 0xec, + 0xe3, 0x0c, 0x72, 0x6c, 0x7a, 0x1a, 0x67, 0xe8, 0x3c, 0xc4, 0x80, 0x44, 0xb0, 0xc5, 0x6d, 0x66, 0x70, 0x15, 0x94, 0xa4, + 0x68, 0x34, 0xb1, 0x3d, 0x40, 0xb1, 0x87, 0x98, 0xd0, 0xee, 0x07, 0x98, 0x21, 0xa3, 0x09, 0x97, 0xcf, 0x93, 0x17, 0x3a, + 0xd7, 0xb8, 0xa8, 0xaa, 0x18, 0xc9, 0x12, 0xd8, 0x46, 0x04, 0x15, 0xaa, 0xe4, 0xce, 0x39, 0xf2, 0xbd, 0x0c, 0xc6, 0xc7, + 0xb7, 0xe4, 0x0e, 0x87, 0xb3, 0x9e, 0x6a, 0xce, 0x7a, 0x35, 0x84, 0xce, 0xbf, 0x7f, 0x2c, 0x93, 0xea, 0x47, 0x98, 0x98, + 0xf7, 0xec, 0xdc, 0x4f, 0x31, 0xe7, 0x11, 0x27, 0x4e, 0x4d, 0x7b, 0x04, 0xb2, 0x23, 0xa2, 0xfa, 0x96, 0xa6, 0x90, 0x73, + 0x80, 0x06, 0x69, 0x24, 0x1e, 0x49, 0xaf, 0xd0, 0xe3, 0x76, 0x8a, 0x30, 0x82, 0x05, 0xd8, 0x30, 0x82, 0x03, 0xc0, 0xa0, + 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x4c, 0xaa, 0xf9, 0xca, 0xdb, 0x63, 0x6f, 0xe0, 0x1f, 0xf7, 0x4e, 0xd8, 0x5b, 0x03, + 0x86, 0x9d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0c, 0x05, 0x00, 0x30, 0x81, 0x85, + 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, + 0x04, 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4d, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x74, + 0x65, 0x72, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6c, 0x66, 0x6f, 0x72, 0x64, + 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x11, 0x43, 0x4f, 0x4d, 0x4f, 0x44, 0x4f, 0x20, 0x43, 0x41, + 0x20, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x31, 0x2b, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x22, 0x43, + 0x4f, 0x4d, 0x4f, 0x44, 0x4f, 0x20, 0x52, 0x53, 0x41, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x30, 0x30, + 0x31, 0x31, 0x39, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x33, 0x38, 0x30, 0x31, 0x31, 0x38, 0x32, 0x33, + 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x81, 0x85, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, + 0x42, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, + 0x4d, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, + 0x07, 0x53, 0x61, 0x6c, 0x66, 0x6f, 0x72, 0x64, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x11, 0x43, + 0x4f, 0x4d, 0x4f, 0x44, 0x4f, 0x20, 0x43, 0x41, 0x20, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x31, 0x2b, 0x30, 0x29, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x22, 0x43, 0x4f, 0x4d, 0x4f, 0x44, 0x4f, 0x20, 0x52, 0x53, 0x41, 0x20, 0x43, 0x65, + 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, + 0x79, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, + 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0x91, 0xe8, 0x54, 0x92, 0xd2, 0x0a, + 0x56, 0xb1, 0xac, 0x0d, 0x24, 0xdd, 0xc5, 0xcf, 0x44, 0x67, 0x74, 0x99, 0x2b, 0x37, 0xa3, 0x7d, 0x23, 0x70, 0x00, 0x71, + 0xbc, 0x53, 0xdf, 0xc4, 0xfa, 0x2a, 0x12, 0x8f, 0x4b, 0x7f, 0x10, 0x56, 0xbd, 0x9f, 0x70, 0x72, 0xb7, 0x61, 0x7f, 0xc9, + 0x4b, 0x0f, 0x17, 0xa7, 0x3d, 0xe3, 0xb0, 0x04, 0x61, 0xee, 0xff, 0x11, 0x97, 0xc7, 0xf4, 0x86, 0x3e, 0x0a, 0xfa, 0x3e, + 0x5c, 0xf9, 0x93, 0xe6, 0x34, 0x7a, 0xd9, 0x14, 0x6b, 0xe7, 0x9c, 0xb3, 0x85, 0xa0, 0x82, 0x7a, 0x76, 0xaf, 0x71, 0x90, + 0xd7, 0xec, 0xfd, 0x0d, 0xfa, 0x9c, 0x6c, 0xfa, 0xdf, 0xb0, 0x82, 0xf4, 0x14, 0x7e, 0xf9, 0xbe, 0xc4, 0xa6, 0x2f, 0x4f, + 0x7f, 0x99, 0x7f, 0xb5, 0xfc, 0x67, 0x43, 0x72, 0xbd, 0x0c, 0x00, 0xd6, 0x89, 0xeb, 0x6b, 0x2c, 0xd3, 0xed, 0x8f, 0x98, + 0x1c, 0x14, 0xab, 0x7e, 0xe5, 0xe3, 0x6e, 0xfc, 0xd8, 0xa8, 0xe4, 0x92, 0x24, 0xda, 0x43, 0x6b, 0x62, 0xb8, 0x55, 0xfd, + 0xea, 0xc1, 0xbc, 0x6c, 0xb6, 0x8b, 0xf3, 0x0e, 0x8d, 0x9a, 0xe4, 0x9b, 0x6c, 0x69, 0x99, 0xf8, 0x78, 0x48, 0x30, 0x45, + 0xd5, 0xad, 0xe1, 0x0d, 0x3c, 0x45, 0x60, 0xfc, 0x32, 0x96, 0x51, 0x27, 0xbc, 0x67, 0xc3, 0xca, 0x2e, 0xb6, 0x6b, 0xea, + 0x46, 0xc7, 0xc7, 0x20, 0xa0, 0xb1, 0x1f, 0x65, 0xde, 0x48, 0x08, 0xba, 0xa4, 0x4e, 0xa9, 0xf2, 0x83, 0x46, 0x37, 0x84, + 0xeb, 0xe8, 0xcc, 0x81, 0x48, 0x43, 0x67, 0x4e, 0x72, 0x2a, 0x9b, 0x5c, 0xbd, 0x4c, 0x1b, 0x28, 0x8a, 0x5c, 0x22, 0x7b, + 0xb4, 0xab, 0x98, 0xd9, 0xee, 0xe0, 0x51, 0x83, 0xc3, 0x09, 0x46, 0x4e, 0x6d, 0x3e, 0x99, 0xfa, 0x95, 0x17, 0xda, 0x7c, + 0x33, 0x57, 0x41, 0x3c, 0x8d, 0x51, 0xed, 0x0b, 0xb6, 0x5c, 0xaf, 0x2c, 0x63, 0x1a, 0xdf, 0x57, 0xc8, 0x3f, 0xbc, 0xe9, + 0x5d, 0xc4, 0x9b, 0xaf, 0x45, 0x99, 0xe2, 0xa3, 0x5a, 0x24, 0xb4, 0xba, 0xa9, 0x56, 0x3d, 0xcf, 0x6f, 0xaa, 0xff, 0x49, + 0x58, 0xbe, 0xf0, 0xa8, 0xff, 0xf4, 0xb8, 0xad, 0xe9, 0x37, 0xfb, 0xba, 0xb8, 0xf4, 0x0b, 0x3a, 0xf9, 0xe8, 0x43, 0x42, + 0x1e, 0x89, 0xd8, 0x84, 0xcb, 0x13, 0xf1, 0xd9, 0xbb, 0xe1, 0x89, 0x60, 0xb8, 0x8c, 0x28, 0x56, 0xac, 0x14, 0x1d, 0x9c, + 0x0a, 0xe7, 0x71, 0xeb, 0xcf, 0x0e, 0xdd, 0x3d, 0xa9, 0x96, 0xa1, 0x48, 0xbd, 0x3c, 0xf7, 0xaf, 0xb5, 0x0d, 0x22, 0x4c, + 0xc0, 0x11, 0x81, 0xec, 0x56, 0x3b, 0xf6, 0xd3, 0xa2, 0xe2, 0x5b, 0xb7, 0xb2, 0x04, 0x22, 0x52, 0x95, 0x80, 0x93, 0x69, + 0xe8, 0x8e, 0x4c, 0x65, 0xf1, 0x91, 0x03, 0x2d, 0x70, 0x74, 0x02, 0xea, 0x8b, 0x67, 0x15, 0x29, 0x69, 0x52, 0x02, 0xbb, + 0xd7, 0xdf, 0x50, 0x6a, 0x55, 0x46, 0xbf, 0xa0, 0xa3, 0x28, 0x61, 0x7f, 0x70, 0xd0, 0xc3, 0xa2, 0xaa, 0x2c, 0x21, 0xaa, + 0x47, 0xce, 0x28, 0x9c, 0x06, 0x45, 0x76, 0xbf, 0x82, 0x18, 0x27, 0xb4, 0xd5, 0xae, 0xb4, 0xcb, 0x50, 0xe6, 0x6b, 0xf4, + 0x4c, 0x86, 0x71, 0x30, 0xe9, 0xa6, 0xdf, 0x16, 0x86, 0xe0, 0xd8, 0xff, 0x40, 0xdd, 0xfb, 0xd0, 0x42, 0x88, 0x7f, 0xa3, + 0x33, 0x3a, 0x2e, 0x5c, 0x1e, 0x41, 0x11, 0x81, 0x63, 0xce, 0x18, 0x71, 0x6b, 0x2b, 0xec, 0xa6, 0x8a, 0xb7, 0x31, 0x5c, + 0x3a, 0x6a, 0x47, 0xe0, 0xc3, 0x79, 0x59, 0xd6, 0x20, 0x1a, 0xaf, 0xf2, 0x6a, 0x98, 0xaa, 0x72, 0xbc, 0x57, 0x4a, 0xd2, + 0x4b, 0x9d, 0xbb, 0x10, 0xfc, 0xb0, 0x4c, 0x41, 0xe5, 0xed, 0x1d, 0x3d, 0x5e, 0x28, 0x9d, 0x9c, 0xcc, 0xbf, 0xb3, 0x51, + 0xda, 0xa7, 0x47, 0xe5, 0x84, 0x53, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x42, 0x30, 0x40, 0x30, 0x1d, 0x06, 0x03, 0x55, + 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xbb, 0xaf, 0x7e, 0x02, 0x3d, 0xfa, 0xa6, 0xf1, 0x3c, 0x84, 0x8e, 0xad, 0xee, 0x38, + 0x98, 0xec, 0xd9, 0x32, 0x32, 0xd4, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, + 0x01, 0x06, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0c, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x0a, + 0xf1, 0xd5, 0x46, 0x84, 0xb7, 0xae, 0x51, 0xbb, 0x6c, 0xb2, 0x4d, 0x41, 0x14, 0x00, 0x93, 0x4c, 0x9c, 0xcb, 0xe5, 0xc0, + 0x54, 0xcf, 0xa0, 0x25, 0x8e, 0x02, 0xf9, 0xfd, 0xb0, 0xa2, 0x0d, 0xf5, 0x20, 0x98, 0x3c, 0x13, 0x2d, 0xac, 0x56, 0xa2, + 0xb0, 0xd6, 0x7e, 0x11, 0x92, 0xe9, 0x2e, 0xba, 0x9e, 0x2e, 0x9a, 0x72, 0xb1, 0xbd, 0x19, 0x44, 0x6c, 0x61, 0x35, 0xa2, + 0x9a, 0xb4, 0x16, 0x12, 0x69, 0x5a, 0x8c, 0xe1, 0xd7, 0x3e, 0xa4, 0x1a, 0xe8, 0x2f, 0x03, 0xf4, 0xae, 0x61, 0x1d, 0x10, + 0x1b, 0x2a, 0xa4, 0x8b, 0x7a, 0xc5, 0xfe, 0x05, 0xa6, 0xe1, 0xc0, 0xd6, 0xc8, 0xfe, 0x9e, 0xae, 0x8f, 0x2b, 0xba, 0x3d, + 0x99, 0xf8, 0xd8, 0x73, 0x09, 0x58, 0x46, 0x6e, 0xa6, 0x9c, 0xf4, 0xd7, 0x27, 0xd3, 0x95, 0xda, 0x37, 0x83, 0x72, 0x1c, + 0xd3, 0x73, 0xe0, 0xa2, 0x47, 0x99, 0x03, 0x38, 0x5d, 0xd5, 0x49, 0x79, 0x00, 0x29, 0x1c, 0xc7, 0xec, 0x9b, 0x20, 0x1c, + 0x07, 0x24, 0x69, 0x57, 0x78, 0xb2, 0x39, 0xfc, 0x3a, 0x84, 0xa0, 0xb5, 0x9c, 0x7c, 0x8d, 0xbf, 0x2e, 0x93, 0x62, 0x27, + 0xb7, 0x39, 0xda, 0x17, 0x18, 0xae, 0xbd, 0x3c, 0x09, 0x68, 0xff, 0x84, 0x9b, 0x3c, 0xd5, 0xd6, 0x0b, 0x03, 0xe3, 0x57, + 0x9e, 0x14, 0xf7, 0xd1, 0xeb, 0x4f, 0xc8, 0xbd, 0x87, 0x23, 0xb7, 0xb6, 0x49, 0x43, 0x79, 0x85, 0x5c, 0xba, 0xeb, 0x92, + 0x0b, 0xa1, 0xc6, 0xe8, 0x68, 0xa8, 0x4c, 0x16, 0xb1, 0x1a, 0x99, 0x0a, 0xe8, 0x53, 0x2c, 0x92, 0xbb, 0xa1, 0x09, 0x18, + 0x75, 0x0c, 0x65, 0xa8, 0x7b, 0xcb, 0x23, 0xb7, 0x1a, 0xc2, 0x28, 0x85, 0xc3, 0x1b, 0xff, 0xd0, 0x2b, 0x62, 0xef, 0xa4, + 0x7b, 0x09, 0x91, 0x98, 0x67, 0x8c, 0x14, 0x01, 0xcd, 0x68, 0x06, 0x6a, 0x63, 0x21, 0x75, 0x03, 0x80, 0x88, 0x8a, 0x6e, + 0x81, 0xc6, 0x85, 0xf2, 0xa9, 0xa4, 0x2d, 0xe7, 0xf4, 0xa5, 0x24, 0x10, 0x47, 0x83, 0xca, 0xcd, 0xf4, 0x8d, 0x79, 0x58, + 0xb1, 0x06, 0x9b, 0xe7, 0x1a, 0x2a, 0xd9, 0x9d, 0x01, 0xd7, 0x94, 0x7d, 0xed, 0x03, 0x4a, 0xca, 0xf0, 0xdb, 0xe8, 0xa9, + 0x01, 0x3e, 0xf5, 0x56, 0x99, 0xc9, 0x1e, 0x8e, 0x49, 0x3d, 0xbb, 0xe5, 0x09, 0xb9, 0xe0, 0x4f, 0x49, 0x92, 0x3d, 0x16, + 0x82, 0x40, 0xcc, 0xcc, 0x59, 0xc6, 0xe6, 0x3a, 0xed, 0x12, 0x2e, 0x69, 0x3c, 0x6c, 0x95, 0xb1, 0xfd, 0xaa, 0x1d, 0x7b, + 0x7f, 0x86, 0xbe, 0x1e, 0x0e, 0x32, 0x46, 0xfb, 0xfb, 0x13, 0x8f, 0x75, 0x7f, 0x4c, 0x8b, 0x4b, 0x46, 0x63, 0xfe, 0x00, + 0x34, 0x40, 0x70, 0xc1, 0xc3, 0xb9, 0xa1, 0xdd, 0xa6, 0x70, 0xe2, 0x04, 0xb3, 0x41, 0xbc, 0xe9, 0x80, 0x91, 0xea, 0x64, + 0x9c, 0x7a, 0xe1, 0x22, 0x03, 0xa9, 0x9c, 0x6e, 0x6f, 0x0e, 0x65, 0x4f, 0x6c, 0x87, 0x87, 0x5e, 0xf3, 0x6e, 0xa0, 0xf9, + 0x75, 0xa5, 0x9b, 0x40, 0xe8, 0x53, 0xb2, 0x27, 0x9d, 0x4a, 0xb9, 0xc0, 0x77, 0x21, 0x8d, 0xff, 0x87, 0xf2, 0xde, 0xbc, + 0x8c, 0xef, 0x17, 0xdf, 0xb7, 0x49, 0x0b, 0xd1, 0xf2, 0x6e, 0x30, 0x0b, 0x1a, 0x0e, 0x4e, 0x76, 0xed, 0x11, 0xfc, 0xf5, + 0xe9, 0x56, 0xb2, 0x7d, 0xbf, 0xc7, 0x6d, 0x0a, 0x93, 0x8c, 0xa5, 0xd0, 0xc0, 0xb6, 0x1d, 0xbe, 0x3a, 0x4e, 0x94, 0xa2, + 0xd7, 0x6e, 0x6c, 0x0b, 0xc2, 0x8a, 0x7c, 0xfa, 0x20, 0xf3, 0xc4, 0xe4, 0xe5, 0xcd, 0x0d, 0xa8, 0xcb, 0x91, 0x92, 0xb1, + 0x7c, 0x85, 0xec, 0xb5, 0x14, 0x69, 0x66, 0x0e, 0x82, 0xe7, 0xcd, 0xce, 0xc8, 0x2d, 0xa6, 0x51, 0x7f, 0x21, 0xc1, 0x35, + 0x53, 0x85, 0x06, 0x4a, 0x5d, 0x9f, 0xad, 0xbb, 0x1b, 0x5f, 0x74, 0x30, 0x82, 0x05, 0xe6, 0x30, 0x82, 0x03, 0xce, 0xa0, + 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x6a, 0x9b, 0xe1, 0x38, 0x3b, 0xff, 0x2b, 0x6b, 0x9f, 0x01, 0xd5, 0xd9, 0xb8, 0xa7, + 0x52, 0x56, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0c, 0x05, 0x00, 0x30, 0x81, 0x85, + 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, + 0x04, 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4d, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x74, + 0x65, 0x72, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6c, 0x66, 0x6f, 0x72, 0x64, + 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x11, 0x43, 0x4f, 0x4d, 0x4f, 0x44, 0x4f, 0x20, 0x43, 0x41, + 0x20, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x31, 0x2b, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x22, 0x43, + 0x4f, 0x4d, 0x4f, 0x44, 0x4f, 0x20, 0x52, 0x53, 0x41, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x33, 0x30, + 0x31, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x32, 0x38, 0x30, 0x31, 0x30, 0x39, 0x32, 0x33, + 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x81, 0x97, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, + 0x42, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, + 0x4d, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, + 0x07, 0x53, 0x61, 0x6c, 0x66, 0x6f, 0x72, 0x64, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x11, 0x43, + 0x4f, 0x4d, 0x4f, 0x44, 0x4f, 0x20, 0x43, 0x41, 0x20, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x31, 0x3d, 0x30, 0x3b, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x34, 0x43, 0x4f, 0x4d, 0x4f, 0x44, 0x4f, 0x20, 0x52, 0x53, 0x41, 0x20, 0x43, 0x6c, + 0x69, 0x65, 0x6e, 0x74, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, + 0x61, 0x6e, 0x64, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x20, 0x43, 0x41, 0x30, + 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, + 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xbe, 0xb3, 0x9e, 0x57, 0xac, 0x28, 0x76, 0x75, + 0x40, 0x16, 0xc7, 0x38, 0x03, 0x98, 0xd3, 0xc6, 0x18, 0x76, 0x21, 0x50, 0xf3, 0x25, 0x79, 0x0b, 0x4c, 0xb5, 0xa0, 0xd1, + 0x7d, 0x3a, 0x58, 0x3e, 0x9c, 0xa7, 0x31, 0x2e, 0xa7, 0xf6, 0x34, 0x76, 0xd9, 0x84, 0x6a, 0xda, 0xd0, 0x3d, 0x34, 0x48, + 0xe4, 0xea, 0xf5, 0xbb, 0xac, 0xdf, 0xf9, 0xb1, 0x81, 0x4b, 0x20, 0xfd, 0x68, 0x7f, 0x79, 0x74, 0x34, 0xa6, 0x7a, 0x7c, + 0xb5, 0x9f, 0x17, 0x65, 0x60, 0x27, 0x97, 0x22, 0x8c, 0xa6, 0x32, 0xfe, 0xa9, 0x40, 0x72, 0x46, 0x35, 0xc2, 0x03, 0xa4, + 0x50, 0xc8, 0x33, 0x2a, 0x55, 0xa5, 0x54, 0x91, 0xb2, 0x2b, 0xe5, 0x25, 0x34, 0x44, 0x35, 0xff, 0x91, 0x2b, 0x0a, 0xc1, + 0xea, 0xf7, 0x1f, 0x5a, 0x53, 0xfc, 0x75, 0x2b, 0x04, 0xdd, 0x17, 0xf2, 0xc2, 0xad, 0x3d, 0x37, 0x46, 0x5f, 0xc5, 0xc0, + 0x5a, 0xdf, 0xd5, 0x74, 0xc2, 0xc1, 0xad, 0x90, 0x65, 0x82, 0xf9, 0xe4, 0x0a, 0x8b, 0x3e, 0x29, 0x05, 0x96, 0x0a, 0x8e, + 0xb7, 0x39, 0x34, 0xea, 0x46, 0xf6, 0xaa, 0xf1, 0xa5, 0x9c, 0x72, 0x6f, 0x8a, 0x38, 0xc8, 0xd3, 0x70, 0x4e, 0xac, 0xda, + 0x68, 0xfa, 0x46, 0x46, 0xa5, 0xc1, 0xec, 0x83, 0x23, 0xb5, 0xfe, 0xed, 0x4e, 0x65, 0x36, 0x8e, 0xa3, 0xcc, 0x2f, 0x11, + 0x4d, 0x7b, 0x55, 0x57, 0x8f, 0xd5, 0xc1, 0xd6, 0xb1, 0xef, 0x6d, 0x18, 0xa4, 0xc3, 0xc9, 0x41, 0xa0, 0xda, 0x12, 0x59, + 0x8e, 0xba, 0x9c, 0x93, 0x7f, 0x54, 0x22, 0x6f, 0xe7, 0x29, 0xba, 0x43, 0x49, 0x9d, 0x09, 0xb0, 0xca, 0x08, 0xc3, 0xf2, + 0x6d, 0x38, 0xe8, 0x34, 0x24, 0x2e, 0x7a, 0x57, 0x34, 0x20, 0x06, 0x8e, 0xe2, 0x72, 0xd4, 0x5e, 0x4d, 0x01, 0x39, 0x2c, + 0x52, 0xc6, 0xdf, 0x24, 0x0a, 0xfb, 0x14, 0xb5, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0x3c, 0x30, 0x82, 0x01, + 0x38, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xbb, 0xaf, 0x7e, 0x02, 0x3d, 0xfa, + 0xa6, 0xf1, 0x3c, 0x84, 0x8e, 0xad, 0xee, 0x38, 0x98, 0xec, 0xd9, 0x32, 0x32, 0xd4, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, + 0x0e, 0x04, 0x16, 0x04, 0x14, 0x82, 0xaf, 0x6c, 0x8c, 0xf8, 0xc5, 0xfe, 0x96, 0x61, 0x7c, 0xe8, 0x1f, 0x3d, 0x2b, 0x71, + 0x48, 0x5e, 0xc4, 0x8b, 0xc0, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, + 0x86, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, + 0x00, 0x30, 0x11, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x0a, 0x30, 0x08, 0x30, 0x06, 0x06, 0x04, 0x55, 0x1d, 0x20, 0x00, + 0x30, 0x4c, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x45, 0x30, 0x43, 0x30, 0x41, 0xa0, 0x3f, 0xa0, 0x3d, 0x86, 0x3b, 0x68, + 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x43, 0x4f, 0x4d, 0x4f, 0x44, 0x4f, 0x52, 0x53, 0x41, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x71, + 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x65, 0x30, 0x63, 0x30, 0x3b, 0x06, 0x08, 0x2b, 0x06, + 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x2f, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x74, 0x2e, 0x63, + 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x43, 0x4f, 0x4d, 0x4f, 0x44, 0x4f, 0x52, 0x53, + 0x41, 0x41, 0x64, 0x64, 0x54, 0x72, 0x75, 0x73, 0x74, 0x43, 0x41, 0x2e, 0x63, 0x72, 0x74, 0x30, 0x24, 0x06, 0x08, 0x2b, + 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x18, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, + 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0c, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x78, 0x5c, 0xb2, 0x81, 0x28, 0x34, 0x4f, + 0x3c, 0xee, 0x5f, 0x56, 0xce, 0x9f, 0x97, 0x56, 0xec, 0x8f, 0xa2, 0x6b, 0x17, 0xf6, 0xf3, 0xf6, 0x49, 0x08, 0x06, 0xd4, + 0xd8, 0x2f, 0x35, 0xcd, 0xdf, 0x40, 0xfe, 0xd3, 0x71, 0xe3, 0xe8, 0xec, 0x42, 0x0c, 0x11, 0x1a, 0x21, 0xe3, 0x66, 0xb0, + 0x18, 0x6b, 0x26, 0x6b, 0xae, 0x6e, 0xfc, 0x84, 0xec, 0x7b, 0x68, 0x4a, 0x64, 0x7c, 0xd3, 0xd0, 0x20, 0x71, 0x86, 0xe8, + 0x5b, 0xea, 0xdc, 0x4c, 0xd6, 0x7f, 0xf2, 0xef, 0xc7, 0xbf, 0xe1, 0x93, 0xac, 0xd2, 0x3f, 0x02, 0x1a, 0x97, 0xdb, 0xf9, + 0x22, 0x40, 0xdc, 0x66, 0x81, 0x43, 0xed, 0xfd, 0xe2, 0x4f, 0xb3, 0xdd, 0x90, 0x72, 0x58, 0xf4, 0x1e, 0x75, 0x72, 0xcb, + 0xd4, 0xe7, 0x4a, 0xf1, 0xa4, 0x48, 0x35, 0x3b, 0x23, 0x93, 0xf1, 0xf9, 0x36, 0xce, 0xfb, 0xcf, 0x06, 0xe3, 0x38, 0xa9, + 0x03, 0x6a, 0x6c, 0x65, 0xa5, 0x9e, 0x13, 0x29, 0x20, 0xcc, 0x29, 0x59, 0x94, 0xfc, 0xf5, 0x16, 0x34, 0xc2, 0x92, 0x4e, + 0xfb, 0x65, 0x7a, 0x79, 0x71, 0x06, 0x18, 0x7b, 0x11, 0x3a, 0xcd, 0xe7, 0x8d, 0xe3, 0xfd, 0x0e, 0xaa, 0xaa, 0x00, 0x96, + 0x81, 0x6b, 0x8c, 0x01, 0x78, 0xa3, 0x9d, 0x18, 0x25, 0xa7, 0xd7, 0xf2, 0x69, 0xda, 0x86, 0x3a, 0x77, 0x23, 0x66, 0x36, + 0x9a, 0x48, 0xe1, 0x93, 0x4c, 0x50, 0x7e, 0x13, 0x6a, 0x6f, 0x39, 0x4b, 0x58, 0xfa, 0x13, 0xde, 0x6e, 0xe3, 0xed, 0x4d, + 0xba, 0xbb, 0xbc, 0xe0, 0xea, 0xcc, 0x23, 0x3a, 0xaf, 0x21, 0x21, 0x36, 0x1c, 0xdf, 0xf9, 0xe9, 0xe6, 0xd3, 0x39, 0x69, + 0x5c, 0xae, 0xea, 0xdf, 0x7d, 0xa7, 0x5e, 0xdb, 0x4d, 0xb6, 0x3b, 0xfb, 0x54, 0x53, 0x58, 0x1b, 0xe2, 0x37, 0xd6, 0x09, + 0xcc, 0xaf, 0x07, 0xc7, 0x33, 0x9b, 0x5d, 0x85, 0x81, 0x7f, 0xf2, 0xfe, 0x54, 0x63, 0x98, 0x36, 0xc4, 0x03, 0x4f, 0x10, + 0x24, 0xd0, 0x76, 0xef, 0x6f, 0x58, 0xfa, 0x2a, 0x35, 0x21, 0x83, 0xb7, 0xce, 0xdb, 0xde, 0x05, 0xdb, 0xd4, 0x08, 0x86, + 0x19, 0xa2, 0x34, 0xea, 0xfc, 0xe0, 0x91, 0xe8, 0xcb, 0xe7, 0xcd, 0x2e, 0x97, 0xef, 0x61, 0xcf, 0xd0, 0xf4, 0x4b, 0x45, + 0x38, 0x8e, 0x48, 0x49, 0x88, 0x0e, 0xc4, 0xb9, 0x37, 0x9c, 0x3f, 0xf0, 0x85, 0xb5, 0x1e, 0xf6, 0xb9, 0x84, 0x41, 0x72, + 0xe9, 0xf0, 0xc0, 0x7d, 0xdf, 0x72, 0x23, 0xe3, 0xbe, 0x20, 0xc3, 0x00, 0x8f, 0x52, 0x9c, 0x2f, 0xf6, 0x68, 0xf6, 0x3c, + 0xc9, 0xd7, 0xa1, 0xce, 0xe6, 0x6e, 0xb4, 0xb6, 0xd9, 0x75, 0x12, 0x79, 0x3c, 0x31, 0x09, 0x33, 0xfd, 0x6d, 0xc9, 0x94, + 0x76, 0x9e, 0x23, 0x98, 0x8a, 0x16, 0x7e, 0x14, 0x26, 0xed, 0x7f, 0x70, 0xfd, 0x98, 0x1d, 0x76, 0x0f, 0x89, 0x67, 0xf6, + 0x27, 0x20, 0x73, 0xb0, 0xb0, 0x6b, 0x1a, 0x4d, 0x48, 0x23, 0xed, 0xf2, 0x2f, 0xc6, 0xa8, 0xad, 0x87, 0xb0, 0xe8, 0x24, + 0x2f, 0x75, 0x58, 0x9f, 0x0b, 0x71, 0xed, 0xc2, 0x54, 0x9a, 0x9b, 0xd5, 0x75, 0x9e, 0x28, 0x82, 0x7c, 0xe0, 0x5e, 0xd8, + 0x2d, 0x76, 0x4d, 0xd2, 0x86, 0xbb, 0x4e, 0x4b, 0x58, 0x80, 0x37, 0x66, 0x41, 0x5c, 0x58, 0x91, 0x9a, 0x35, 0x73, 0x99, + 0xe8, 0x68, 0x32, 0x87, 0xf4, 0xea, 0xbd, 0x71, 0xb9, 0xbf, 0xbc, 0xe6, 0x11, 0x50, 0xcd, 0x5c, 0x59, 0xc7, 0x9f, 0xdb, + 0x45, 0xa4, 0xca, 0x4e, 0x52, 0xfc, 0x61, 0x72, 0xc8, 0xf2, 0x70, 0x1b, 0x47, 0xd1, 0xd6, 0x74, 0x5a, 0xb3, 0x70, 0xea, + 0x01, 0xfe, 0x1c, 0x5f, 0x13, 0x22, 0x10, 0xa7, 0x1f, 0x7f, 0xb3, 0xcd, 0x6b, 0x83, 0x37, 0x44, 0x64, 0xea, 0x1f, 0x4a, + 0x56, 0x47, 0xca, 0x7a, 0x12, 0x31, 0x82, 0x03, 0x5a, 0x30, 0x82, 0x03, 0x56, 0x02, 0x01, 0x01, 0x30, 0x81, 0xac, 0x30, + 0x81, 0x97, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x1b, 0x30, 0x19, 0x06, + 0x03, 0x55, 0x04, 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4d, 0x61, 0x6e, 0x63, 0x68, 0x65, + 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6c, 0x66, 0x6f, + 0x72, 0x64, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x11, 0x43, 0x4f, 0x4d, 0x4f, 0x44, 0x4f, 0x20, + 0x43, 0x41, 0x20, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x31, 0x3d, 0x30, 0x3b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x34, 0x43, 0x4f, 0x4d, 0x4f, 0x44, 0x4f, 0x20, 0x52, 0x53, 0x41, 0x20, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x65, + 0x63, 0x75, 0x72, 0x65, 0x20, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x20, 0x43, 0x41, 0x02, 0x10, 0x43, 0x3d, 0xe2, 0x93, 0xa4, + 0xed, 0xf7, 0x8d, 0x8b, 0x98, 0x93, 0x72, 0x76, 0xdd, 0x46, 0xe7, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, + 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0xa0, 0x82, 0x01, 0x7e, 0x30, 0x18, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x09, 0x03, 0x31, 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x30, 0x1c, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x05, 0x31, 0x0f, 0x17, 0x0d, 0x31, 0x38, 0x30, 0x33, 0x30, 0x31, 0x31, + 0x32, 0x33, 0x33, 0x32, 0x33, 0x5a, 0x30, 0x27, 0x06, 0x0b, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x02, + 0x0b, 0x31, 0x18, 0xa1, 0x16, 0x04, 0x14, 0x31, 0x34, 0xad, 0xb0, 0xf8, 0xc0, 0x87, 0x77, 0xe5, 0x9b, 0x2a, 0xda, 0x75, + 0x10, 0x98, 0x65, 0xae, 0xac, 0xfc, 0x84, 0x30, 0x3f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x04, + 0x31, 0x32, 0x04, 0x30, 0xe4, 0xea, 0x14, 0xe1, 0x6d, 0x9c, 0xf0, 0x0e, 0xf6, 0x14, 0x3c, 0xb5, 0x7e, 0x13, 0x05, 0x33, + 0x7b, 0x64, 0xb5, 0xa6, 0x15, 0x4e, 0x06, 0x16, 0x7c, 0x69, 0x46, 0x93, 0xc9, 0xf9, 0x3d, 0x83, 0xc0, 0xe3, 0x54, 0x97, + 0xb3, 0x4d, 0x97, 0x7f, 0xfa, 0xd6, 0x3a, 0x3c, 0x0c, 0xf5, 0xfa, 0xa9, 0x30, 0x81, 0xd9, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x0f, 0x31, 0x81, 0xcb, 0x30, 0x81, 0xc8, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, + 0x65, 0x03, 0x04, 0x01, 0x2a, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x16, 0x30, 0x0b, + 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x02, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x03, 0x07, 0x30, 0x16, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x03, 0x08, 0x30, 0x0a, 0x02, 0x01, 0x10, + 0x02, 0x02, 0x00, 0xff, 0x02, 0x01, 0x40, 0x30, 0x15, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x03, 0x08, 0x30, + 0x09, 0x02, 0x01, 0x10, 0x02, 0x01, 0x10, 0x02, 0x01, 0x40, 0x30, 0x0e, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x03, 0x02, 0x02, 0x02, 0x00, 0x80, 0x30, 0x16, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x03, 0x08, 0x30, 0x0a, + 0x02, 0x01, 0x08, 0x02, 0x02, 0x00, 0xff, 0x02, 0x01, 0x40, 0x30, 0x15, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x03, 0x08, 0x30, 0x09, 0x02, 0x01, 0x08, 0x02, 0x01, 0x10, 0x02, 0x01, 0x40, 0x30, 0x0d, 0x06, 0x08, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x03, 0x02, 0x02, 0x01, 0x40, 0x30, 0x0d, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x03, 0x02, + 0x02, 0x01, 0x28, 0x30, 0x07, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x07, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0x21, 0x05, 0x42, 0x5d, 0x88, 0x06, 0x2c, 0xf5, 0x83, + 0xe8, 0xbe, 0x16, 0x66, 0x90, 0x37, 0xa6, 0x6a, 0x73, 0xa9, 0x78, 0xc8, 0x0d, 0xe4, 0xfe, 0xfc, 0xa2, 0x79, 0xdd, 0x9b, + 0xf3, 0xef, 0x19, 0x2f, 0x4a, 0x9a, 0x46, 0xf8, 0x13, 0x7f, 0x77, 0xa5, 0x67, 0x2e, 0xf1, 0x0c, 0xff, 0x25, 0x9e, 0xfd, + 0x68, 0x02, 0x61, 0x53, 0x7c, 0x4d, 0xa4, 0xa6, 0x14, 0x43, 0x70, 0x29, 0xc2, 0x5b, 0xe7, 0x7a, 0xcd, 0xe8, 0x78, 0xa3, + 0xd5, 0x36, 0x21, 0x50, 0xf6, 0xb1, 0xcc, 0xfc, 0x18, 0xd4, 0x8a, 0x7b, 0x19, 0x6e, 0x5c, 0x19, 0xe2, 0xb2, 0xc3, 0x82, + 0x3f, 0x77, 0x8f, 0x70, 0x6b, 0xf4, 0x21, 0x81, 0x05, 0x96, 0xd9, 0xa3, 0xa4, 0xb6, 0xe0, 0x22, 0x48, 0x9d, 0xb4, 0x39, + 0x03, 0x4b, 0xa2, 0x1a, 0xe4, 0x40, 0x8a, 0x7d, 0xfe, 0x42, 0xca, 0x20, 0x7e, 0xca, 0x88, 0xb5, 0x4a, 0x82, 0x9b, 0x1b, + 0x40, 0x0f, 0x35, 0xdf, 0x52, 0x7d, 0x64, 0xfb, 0xab, 0x60, 0x11, 0xfc, 0x38, 0x84, 0xbd, 0xd8, 0xe1, 0x06, 0xdb, 0x2e, + 0x8d, 0x03, 0x4c, 0x8a, 0x93, 0xde, 0x37, 0xf5, 0xc0, 0x16, 0x57, 0x13, 0x47, 0x06, 0x6d, 0xd0, 0x70, 0xd1, 0x57, 0x5b, + 0xbd, 0x4d, 0xe2, 0xca, 0x01, 0xef, 0x61, 0xbf, 0xc6, 0x4b, 0x30, 0x92, 0x8b, 0x58, 0xb8, 0xe4, 0xf6, 0x42, 0xb4, 0x37, + 0xda, 0xe6, 0x76, 0xe0, 0xcf, 0xf8, 0xec, 0xeb, 0x96, 0x9e, 0x04, 0x39, 0x17, 0x32, 0xf6, 0x0b, 0xe7, 0x8b, 0x62, 0xa6, + 0x31, 0x42, 0xa6, 0x3d, 0xb0, 0x37, 0x98, 0x52, 0xe2, 0x59, 0xa1, 0x48, 0x58, 0x75, 0x23, 0x35, 0x84, 0x88, 0x08, 0xe6, + 0xea, 0xca, 0x28, 0x8e, 0x14, 0x98, 0xe8, 0x68, 0x43, 0x9f, 0x23, 0xd1, 0x22, 0x44, 0x95, 0xd8, 0x34, 0x3a, 0xaa, 0x4a, + 0x01, 0xb7, 0xe5, 0x10, 0x98, 0x22, 0x7c, 0x00, 0x00, 0x00, 0x00 +}; diff --git a/OSX/sec/Security/SecAccessControl.c b/OSX/sec/Security/SecAccessControl.c index 8dab3c49..ed8671b4 100644 --- a/OSX/sec/Security/SecAccessControl.c +++ b/OSX/sec/Security/SecAccessControl.c @@ -251,7 +251,8 @@ bool SecAccessControlSetProtection(SecAccessControlRef access_control, CFTypeRef kSecAttrAccessibleWhenUnlocked, kSecAttrAccessibleAlwaysThisDeviceOnlyPrivate, kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly, kSecAttrAccessibleWhenUnlockedThisDeviceOnly, - kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly), + kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, + kSecAttrAccessibleUntilReboot), CFSTR("SecAccessControl: invalid protection")); } diff --git a/OSX/sec/Security/SecExports.exp-in b/OSX/sec/Security/SecExports.exp-in index 20fa2fd8..d9f013ec 100644 --- a/OSX/sec/Security/SecExports.exp-in +++ b/OSX/sec/Security/SecExports.exp-in @@ -1260,6 +1260,7 @@ _kSecAttrAccessibleWhenUnlocked _kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly _kSecAttrAccessibleAlwaysThisDeviceOnly _kSecAttrAccessibleAlwaysThisDeviceOnlyPrivate +_kSecAttrAccessibleUntilReboot _kSecAttrAccessibleWhenUnlockedThisDeviceOnly _kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly _kSecAttrAccount @@ -1394,6 +1395,7 @@ _kSecAttrAccessibleAlways _kSecAttrAccessibleAlwaysPrivate _kSecAttrAccessibleAlwaysThisDeviceOnly _kSecAttrAccessibleAlwaysThisDeviceOnlyPrivate +_kSecAttrAccessibleUntilReboot _kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly _kSecAttrAccessibleWhenUnlocked _kSecAttrAccessibleWhenUnlockedThisDeviceOnly diff --git a/OSX/sec/Security/SecItemConstants.c b/OSX/sec/Security/SecItemConstants.c index 0c1822a8..3231cbc3 100644 --- a/OSX/sec/Security/SecItemConstants.c +++ b/OSX/sec/Security/SecItemConstants.c @@ -173,6 +173,8 @@ SEC_CONST_DECL (kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, "akpu"); /* kSecAttrAccessible Value Constants (Private). */ SEC_CONST_DECL (kSecAttrAccessibleAlwaysPrivate, "dk"); SEC_CONST_DECL (kSecAttrAccessibleAlwaysThisDeviceOnlyPrivate, "dku"); +/* _kSecAttrAccessibleUntilReboot for class F. */ +SEC_CONST_DECL (kSecAttrAccessibleUntilReboot, "f"); /* kSecAttrProtocol Value Constants. */ SEC_CONST_DECL (kSecAttrProtocolFTP, "ftp "); diff --git a/OSX/sec/SharedWebCredential/swcagent.m b/OSX/sec/SharedWebCredential/swcagent.m index 862b8376..a9377667 100644 --- a/OSX/sec/SharedWebCredential/swcagent.m +++ b/OSX/sec/SharedWebCredential/swcagent.m @@ -331,6 +331,7 @@ static CFOptionFlags swca_handle_request(enum SWCAXPCOperation operation, Client CFUserNotificationRef notification = NULL; NSMutableDictionary *notification_dictionary = NULL; NSString *request_key; + NSString *request_format; NSString *default_button_key; NSString *alternate_button_key; NSString *other_button_key; @@ -389,12 +390,16 @@ check_database: goto out; } request_key = [NSString stringWithFormat:@"SWC_REQUEST_%s", op]; + request_format = NSLocalizedStringFromTableInBundle(request_key, swca_string_table, swca_get_security_bundle(), nil); alternate_button_key = (op) ? [NSString stringWithFormat:@"SWC_ALLOW_%s", op] : nil; default_button_key = @"SWC_NEVER"; other_button_key = @"SWC_DENY"; info_message_key = @"SWC_INFO_MESSAGE"; - notification_dictionary[(__bridge NSString *)kCFUserNotificationAlertHeaderKey] = NSLocalizedStringFromTableInBundle(request_key, swca_string_table, swca_get_security_bundle(), nil);; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wformat-nonliteral" + notification_dictionary[(__bridge NSString *)kCFUserNotificationAlertHeaderKey] = [NSString stringWithFormat:request_format, client.client_name, domain]; +#pragma clang diagnostic pop notification_dictionary[(__bridge NSString *)kCFUserNotificationAlertMessageKey] = NSLocalizedStringFromTableInBundle(info_message_key, swca_string_table, swca_get_security_bundle(), nil); notification_dictionary[(__bridge NSString *)kCFUserNotificationDefaultButtonTitleKey] = NSLocalizedStringFromTableInBundle(default_button_key, swca_string_table, swca_get_security_bundle(), nil); notification_dictionary[(__bridge NSString *)kCFUserNotificationAlternateButtonTitleKey] = NSLocalizedStringFromTableInBundle(alternate_button_key, swca_string_table, swca_get_security_bundle(), nil); diff --git a/OSX/sec/securityd/OTATrustUtilities.h b/OSX/sec/securityd/OTATrustUtilities.h index 71ccc3b6..74f33fe5 100644 --- a/OSX/sec/securityd/OTATrustUtilities.h +++ b/OSX/sec/securityd/OTATrustUtilities.h @@ -128,10 +128,15 @@ uint64_t SecOTAPKIGetTrustStoreVersion(SecOTAPKIRef otapkiRef); CF_EXPORT uint64_t SecOTAPKIGetAssetVersion(SecOTAPKIRef otapkiRef); -// Accessor to retrieve the last check in time for the OTAPKI asset +// Accessors to retrieve the last check in time for the OTAPKI asset CF_EXPORT CFDateRef SecOTAPKICopyLastAssetCheckInDate(SecOTAPKIRef otapkiRef); +#define kSecOTAPKIAssetStalenessAtRisk (60*60*24*30) // 30 days +#define kSecOTAPKIAssetStalenessWarning (60*60*24*45) // 45 days +#define kSecOTAPKIAssetStalenessDisable (60*60*24*60) // 60 days +bool SecOTAPKIAssetStalenessLessThanSeconds(SecOTAPKIRef otapkiRef, CFTimeInterval seconds); + #if __OBJC__ // SPI to return the current sampling rate for the event name // This rate is actually n where we sample 1 out of every n diff --git a/OSX/sec/securityd/OTATrustUtilities.m b/OSX/sec/securityd/OTATrustUtilities.m index 6431ac00..4582e3da 100644 --- a/OSX/sec/securityd/OTATrustUtilities.m +++ b/OSX/sec/securityd/OTATrustUtilities.m @@ -63,6 +63,10 @@ #import #endif +#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR +#import +#endif + #if TARGET_OS_OSX #import #endif @@ -79,6 +83,10 @@ static inline bool isNSArray(id nsType) { return nsType && [nsType isKindOfClass:[NSArray class]]; } +static inline bool isNSDate(id nsType) { + return nsType && [nsType isKindOfClass:[NSDate class]]; +} + #define SECURITYD_ROLE_ACCOUNT 64 #define ROOT_ACCOUNT 0 @@ -169,11 +177,18 @@ static CFDataRef SecSystemTrustStoreCopyResourceContents(CFStringRef resourceNam /* MARK: - */ /* MARK: MobileAsset Updates */ // MARK: Forward Declarations -static uint64_t GetAssetVersion(void); +static uint64_t GetAssetVersion(CFErrorRef *error); +static uint64_t GetSystemVersion(CFStringRef key); #if !TARGET_OS_BRIDGE -static BOOL UpdateFromAsset(NSURL *localURL, NSNumber *asset_version); +static BOOL UpdateFromAsset(NSURL *localURL, NSNumber *asset_version, NSError **error); static BOOL UpdateOTACheckInDate(void); #endif +#if TARGET_OS_IPHONE +static void TriggerUnlockNotificationOTATrustAssetCheck(dispatch_queue_t queue); +#endif + +/* This queue is for fetching changes to the OTAPKI reference or otherwise doing maintenance activities */ +static dispatch_queue_t kOTABackgroundQueue = NULL; // MARK: Constants NSString *kOTATrustContentVersionKey = @"MobileAssetContentVersion"; @@ -199,6 +214,7 @@ const CFStringRef kSecSUScanPrefConfigDataInstallKey = CFSTR("ConfigDataInstall" // MARK: Helper functions typedef enum { + OTATrustLogLevelNone, OTATrustLogLevelDebug, OTATrustLogLevelInfo, OTATrustLogLevelNotice, @@ -206,9 +222,18 @@ typedef enum { } OTATrustLogLevel; static void MakeOTATrustError(NSError **error, OTATrustLogLevel level, NSErrorDomain errDomain, OSStatus errCode, NSString *format,...) NS_FORMAT_FUNCTION(5,6); +static void MakeOTATrustErrorWithAttributes(NSError **error, OTATrustLogLevel level, NSErrorDomain errDomain, OSStatus errCode, + NSDictionary *attributes, NSString *format,...) + NS_FORMAT_FUNCTION(6,7); + +static void MakeOTATrustErrorArgs(NSError **error, OTATrustLogLevel level, NSErrorDomain errDomain, OSStatus errCode, + NSDictionary *attributes, NSString *format, va_list arguments) + NS_FORMAT_FUNCTION(6,0); static void LogLocally(OTATrustLogLevel level, NSString *errorString) { switch (level) { + case OTATrustLogLevelNone: + break; case OTATrustLogLevelDebug: secdebug("OTATrust", "%@", errorString); break; @@ -224,20 +249,23 @@ static void LogLocally(OTATrustLogLevel level, NSString *errorString) { } } -static void LogRemotely(OTATrustLogLevel level, NSError **error) { +static void LogRemotelyWithAttributes(OTATrustLogLevel level, NSError **error, NSDictionary *attributes) { #if ENABLE_TRUSTD_ANALYTICS /* only report errors and notices */ if (error && level == OTATrustLogLevelError) { - [[TrustdHealthAnalytics logger] logResultForEvent:TrustdHealthAnalyticsEventOTAPKIEvent hardFailure:YES result:*error]; + [[TrustdHealthAnalytics logger] logResultForEvent:TrustdHealthAnalyticsEventOTAPKIEvent hardFailure:YES result:*error withAttributes:attributes]; } else if (error && level == OTATrustLogLevelNotice) { - [[TrustdHealthAnalytics logger] logResultForEvent:TrustdHealthAnalyticsEventOTAPKIEvent hardFailure:NO result:*error]; + [[TrustdHealthAnalytics logger] logResultForEvent:TrustdHealthAnalyticsEventOTAPKIEvent hardFailure:NO result:*error withAttributes:attributes]; } #endif // ENABLE_TRUSTD_ANALYTICS } -static void MakeOTATrustError(NSError **error, OTATrustLogLevel level, NSErrorDomain errDomain, OSStatus errCode, NSString *format,...) { - va_list args; - va_start(args, format); +static void LogRemotely(OTATrustLogLevel level, NSError **error) { + LogRemotelyWithAttributes(level, error, nil); +} + +static void MakeOTATrustErrorArgs(NSError **error, OTATrustLogLevel level, NSErrorDomain errDomain, OSStatus errCode, + NSDictionary *attributes, NSString *format, va_list args) { NSString *formattedString = nil; if (format) { formattedString = [[NSString alloc] initWithFormat:format arguments:args]; @@ -248,13 +276,30 @@ static void MakeOTATrustError(NSError **error, OTATrustLogLevel level, NSErrorDo if (format) { [userInfo setObject:formattedString forKey:NSLocalizedDescriptionKey]; } + if (error && *error) { + userInfo[NSUnderlyingErrorKey] = *error; + } localError = [NSError errorWithDomain:errDomain code:errCode userInfo:userInfo]; LogLocally(level, formattedString); - LogRemotely(level, &localError); + LogRemotelyWithAttributes(level, &localError, attributes); if (error) { *error = localError; } +} + +static void MakeOTATrustErrorWithAttributes(NSError **error, OTATrustLogLevel level, NSErrorDomain errDomain, OSStatus errCode, + NSDictionary *attributes, NSString *format,...) { + va_list args; + va_start(args, format); + MakeOTATrustErrorArgs(error, level, errDomain, errCode, attributes, format, args); + va_end(args); +} + +static void MakeOTATrustError(NSError **error, OTATrustLogLevel level, NSErrorDomain errDomain, OSStatus errCode, NSString *format,...) { + va_list args; + va_start(args, format); + MakeOTATrustErrorArgs(error, level, errDomain, errCode, nil, format, args); va_end(args); } @@ -344,16 +389,7 @@ static void DeleteFileWithName(NSString *filename) { } } -static void DeleteAssetFromDisk(void) { - if (SecOTAPKIIsSystemTrustd()) { - DeleteFileWithName(kOTATrustContextFilename); - DeleteFileWithName(kOTATrustTrustedCTLogsFilename); - DeleteFileWithName(kOTATrustAnalyticsSamplingRatesFilename); - DeleteFileWithName(kOTATrustAppleCertifcateAuthoritiesFilename); - } -} - -static BOOL UpdateOTAContextOnDisk(NSString *key, id value) { +static BOOL UpdateOTAContextOnDisk(NSString *key, id value, NSError **error) { if (SecOTAPKIIsSystemTrustd()) { /* Get current context, if applicable, and update/add key/value */ NSURL *otaContextFile = GetAssetFileURL(kOTATrustContextFilename); @@ -367,11 +403,9 @@ static BOOL UpdateOTAContextOnDisk(NSString *key, id value) { newContext[key] = value; /* Write dictionary to disk */ - NSError *error = nil; - [newContext writeToURL:otaContextFile error:&error]; - if (error) { - secerror("OTATrust: unable to write asset version to disk: %@", error); - LogRemotely(OTATrustLogLevelError, &error); + if (![newContext writeToURL:otaContextFile error:error]) { + secerror("OTATrust: unable to write OTA Context to disk: %@", error ? *error : nil); + LogRemotely(OTATrustLogLevelError, error); return NO; } return YES; @@ -379,7 +413,31 @@ static BOOL UpdateOTAContextOnDisk(NSString *key, id value) { return NO; } -static BOOL CopyFileToDisk(NSString *filename, NSURL *localURL) { +static BOOL UpdateOTAContext(NSNumber *asset_version, NSError **error) { + return UpdateOTAContextOnDisk(kOTATrustContentVersionKey, asset_version, error) && UpdateOTACheckInDate(); +} + +/* Delete only the asset data but not the check-in time. */ +static void DeleteOldAssetData(void) { + if (SecOTAPKIIsSystemTrustd()) { + /* Delete the asset files, but keep the check-in time and version */ + DeleteFileWithName(kOTATrustTrustedCTLogsFilename); + DeleteFileWithName(kOTATrustAnalyticsSamplingRatesFilename); + DeleteFileWithName(kOTATrustAppleCertifcateAuthoritiesFilename); + } +} + +/* Delete all asset data, intended for error cases */ +static BOOL DeleteAssetFromDisk(void) { + if (SecOTAPKIIsSystemTrustd()) { + DeleteOldAssetData(); + DeleteFileWithName(kOTATrustContextFilename); + return YES; + } + return NO; +} + +static BOOL CopyFileToDisk(NSString *filename, NSURL *localURL, NSError **error) { if (SecOTAPKIIsSystemTrustd()) { NSURL *toFileURL = GetAssetFileURL(filename); secdebug("OTATrust", "will copy asset file data from \"%@\"", localURL); @@ -388,7 +446,8 @@ static BOOL CopyFileToDisk(NSString *filename, NSURL *localURL) { state, COPYFILE_DATA); copyfile_state_free(state); if (retval < 0) { - secerror("OTATrust: copyfile error for asset %d", retval); + MakeOTATrustError(error, OTATrustLogLevelError, NSPOSIXErrorDomain, errno, + @"copyfile error for asset %d: %s", errno, strerror(errno)); return NO; } else { return YES; @@ -400,8 +459,8 @@ static BOOL CopyFileToDisk(NSString *filename, NSURL *localURL) { // MARK: Fetch and Update Functions #if TARGET_OS_IPHONE static NSNumber *UpdateAndPurgeAsset(MAAsset *asset, NSNumber *asset_version, NSError **error) { - if (SecPinningDbUpdateFromURL((__bridge CFURLRef)[asset getLocalFileUrl]) && - UpdateFromAsset([asset getLocalFileUrl], asset_version)) { + if (SecPinningDbUpdateFromURL([asset getLocalFileUrl], error) && + UpdateFromAsset([asset getLocalFileUrl], asset_version, error)) { secnotice("OTATrust", "finished update to version %@ from installed asset. purging asset.", asset_version); #if ENABLE_TRUSTD_ANALYTICS [[TrustdHealthAnalytics logger] logSuccessForEventNamed:TrustdHealthAnalyticsEventOTAPKIEvent]; @@ -419,6 +478,33 @@ static NSNumber *UpdateAndPurgeAsset(MAAsset *asset, NSNumber *asset_version, NS } } +static MADownloadOptions *GetMADownloadOptions(BOOL wait) { + /* default behavior */ + MADownloadOptions *options = [[MADownloadOptions alloc] init]; + options.discretionary = YES; + options.allowsCellularAccess = NO; + + /* If an XPC interface is waiting on this, all expenses allowed */ + if (wait) { + options.discretionary = NO; + options.allowsCellularAccess = YES; + return options; + } + + /* If last asset check-in was too long ago, use more expensive options */ + SecOTAPKIRef otapkiref = SecOTAPKICopyCurrentOTAPKIRef(); + if (!SecOTAPKIAssetStalenessLessThanSeconds(otapkiref, kSecOTAPKIAssetStalenessWarning)) { + secnotice("OTATrust", "Asset staleness state: warning"); + options.allowsCellularAccess = YES; + options.discretionary = NO; + } else if (!SecOTAPKIAssetStalenessLessThanSeconds(otapkiref, kSecOTAPKIAssetStalenessAtRisk)) { + secnotice("OTATrust", "Asset staleness state: at risk"); + options.discretionary = NO; + } + CFReleaseNull(otapkiref); + return options; +} + static BOOL DownloadOTATrustAsset(BOOL isLocalOnly, BOOL wait, NSError **error) { if (!CanCheckMobileAsset()) { MakeOTATrustError(error, OTATrustLogLevelNotice, NSOSStatusErrorDomain, errSecServiceNotAvailable, @@ -430,12 +516,16 @@ static BOOL DownloadOTATrustAsset(BOOL isLocalOnly, BOOL wait, NSError **error) __block dispatch_semaphore_t done = wait ? dispatch_semaphore_create(0) : nil; __block NSError *ma_error = nil; secnotice("OTATrust", "begin MobileAsset query for catalog"); - [MAAsset startCatalogDownload:(NSString *)OTATrustMobileAssetType then:^(MADownLoadResult result) { + [MAAsset startCatalogDownload:(NSString *)OTATrustMobileAssetType options:GetMADownloadOptions(wait) then:^(MADownLoadResult result) { @autoreleasepool { os_transaction_t transaction = os_transaction_create("com.apple.trustd.PKITrustSupplementals.download"); if (result != MADownloadSucceesful) { MakeOTATrustError(&ma_error, OTATrustLogLevelError, @"MADownLoadResult", result, @"failed to download catalog: %ld", (long)result); + if (result == MADownloadDaemonNotReady) { + /* mobileassetd has to wait for first unlock to downalod. trustd usually launches before first unlock. */ + TriggerUnlockNotificationOTATrustAssetCheck(kOTABackgroundQueue); + } return; } MAAssetQuery *query = [[MAAssetQuery alloc] initWithType:(NSString *)OTATrustMobileAssetType]; @@ -466,14 +556,18 @@ static BOOL DownloadOTATrustAsset(BOOL isLocalOnly, BOOL wait, NSError **error) continue; } - /* We got an Asset that this device could use; write the last check-in time as now. */ - (void)UpdateOTACheckInDate(); - /* Check Content Version against the current content version */ NSNumber *asset_version = [asset assetProperty:@"_ContentVersion"]; if (!ShouldUpdateWithAsset(asset_version)) { - MakeOTATrustError(&ma_error, OTATrustLogLevelNotice, NSOSStatusErrorDomain, errSecDuplicateItem, - @"skipping asset because we already have _ContentVersion %@ (or newer)", asset_version); + /* write the version and last (successful) check-in time */ + UpdateOTAContext(asset_version, &ma_error); + NSDictionary *eventAttributes = @{ + @"assetVersion" : asset_version, + @"systemVersion" : @(GetSystemVersion((__bridge CFStringRef)kOTATrustContentVersionKey)), + @"installedVersion" : @(SecOTAPKIGetCurrentAssetVersion(nil)), + }; + MakeOTATrustErrorWithAttributes(&ma_error, OTATrustLogLevelNotice, NSOSStatusErrorDomain, errSecDuplicateItem, eventAttributes, + @"skipping asset because we already have _ContentVersion %@ (or newer)", asset_version); continue; } @@ -497,7 +591,7 @@ static BOOL DownloadOTATrustAsset(BOOL isLocalOnly, BOOL wait, NSError **error) case MANotPresent: secnotice("OTATrust", "begin download of OTATrust asset"); began_async_job = true; - [asset startDownload:^(MADownLoadResult downloadResult) { + [asset startDownload:GetMADownloadOptions(wait) then:^(MADownLoadResult downloadResult) { @autoreleasepool { os_transaction_t inner_transaction = os_transaction_create("com.apple.trustd.PKITrustSupplementals.downloadAsset"); if (downloadResult != MADownloadSucceesful) { @@ -548,11 +642,29 @@ static BOOL DownloadOTATrustAsset(BOOL isLocalOnly, BOOL wait, NSError **error) } return result; } + +static void TriggerUnlockNotificationOTATrustAssetCheck(dispatch_queue_t queue) { + SecOTAPKIRef otapkiref = SecOTAPKICopyCurrentOTAPKIRef(); + /* If the last check-in is recent enough, wait for our regularly scheduled check-in. */ + if (SecOTAPKIAssetStalenessLessThanSeconds(otapkiref, kSecOTAPKIAssetStalenessAtRisk)) { + CFReleaseNull(otapkiref); + return; + } +#if !TARGET_OS_SIMULATOR + /* register for unlock notifications */ + int out_token = 0; + notify_register_dispatch(kMobileKeyBagLockStatusNotificationID, &out_token, queue, ^(int token) { + secnotice("OTATrust", "Got lock status notification for at-risk last check-in after MA daemon error"); + (void)DownloadOTATrustAsset(NO, NO, nil); + notify_cancel(token); + }); +#endif +} #else /* !TARGET_OS_IPHONE */ /* MobileAssetV2 fails on macOS, so use V1 */ static NSNumber *UpdateAndPurgeAsset(ASAsset *asset, NSNumber *asset_version, NSError **error) { - if (SecPinningDbUpdateFromURL((__bridge CFURLRef)[asset localURL]) && - UpdateFromAsset([asset localURL], asset_version)) { + if (SecPinningDbUpdateFromURL([asset localURL], error) && + UpdateFromAsset([asset localURL], asset_version, error)) { secnotice("OTATrust", "finished update to version %@ from installed asset. purging asset.", asset_version); #if ENABLE_TRUSTD_ANALYTICS [[TrustdHealthAnalytics logger] logSuccessForEventNamed:TrustdHealthAnalyticsEventOTAPKIEvent]; @@ -570,6 +682,32 @@ static NSNumber *UpdateAndPurgeAsset(ASAsset *asset, NSNumber *asset_version, NS } } +static NSDictionary *GetASDownloadOptions(BOOL wait) { + /* default behavior */ + NSMutableDictionary *options = [NSMutableDictionary dictionary]; + options[ASDownloadOptionPriority] = ASDownloadPriorityNormal; + + /* If an XPC interface is waiting on this, all expenses allowed */ + if (wait) { + options[ASDownloadOptionPriority] = ASDownloadPriorityHigh; + options[ASDownloadOptionAllowBatteryPower] = @YES; + return options; + } + + /* If last asset check-in was too long ago, use more expensive options */ + SecOTAPKIRef otapkiref = SecOTAPKICopyCurrentOTAPKIRef(); + if (!SecOTAPKIAssetStalenessLessThanSeconds(otapkiref, kSecOTAPKIAssetStalenessWarning)) { + secnotice("OTATrust", "Asset staleness state: warning"); + options[ASDownloadOptionPriority] = ASDownloadPriorityHigh; + options[ASDownloadOptionAllowBatteryPower] = @YES; + } else if (!SecOTAPKIAssetStalenessLessThanSeconds(otapkiref, kSecOTAPKIAssetStalenessAtRisk)) { + secnotice("OTATrust", "Asset staleness state: at risk"); + options[ASDownloadOptionPriority] = ASDownloadPriorityHigh; + } + CFReleaseNull(otapkiref); + return options; +} + static BOOL DownloadOTATrustAsset(BOOL isLocalOnly, BOOL wait, NSError **error) { if (!CanCheckMobileAsset()) { MakeOTATrustError(error, OTATrustLogLevelNotice, NSOSStatusErrorDomain, errSecServiceNotAvailable, @@ -606,21 +744,25 @@ static BOOL DownloadOTATrustAsset(BOOL isLocalOnly, BOOL wait, NSError **error) continue; } - /* We got an Asset that this device could use; write the last check-in time as now. */ - (void)UpdateOTACheckInDate(); - /* Check Content Version against the current content version */ NSNumber *contentVersion = [attributes objectForKey:ASAttributeContentVersion]; if (!ShouldUpdateWithAsset(contentVersion)) { - MakeOTATrustError(error, OTATrustLogLevelNotice, NSOSStatusErrorDomain, errSecDuplicateItem, - @"skipping asset because we already have _ContentVersion %@ (or newer)", contentVersion); + /* write the version and last (successful) check-in time */ + UpdateOTAContext(contentVersion, error); + NSDictionary *eventAttributes = @{ + @"assetVersion" : contentVersion, + @"systemVersion" : @(GetSystemVersion((__bridge CFStringRef)kOTATrustContentVersionKey)), + @"installedVersion" : @(SecOTAPKIGetCurrentAssetVersion(nil)), + }; + MakeOTATrustErrorWithAttributes(error, OTATrustLogLevelNotice, NSOSStatusErrorDomain, errSecDuplicateItem, eventAttributes, + @"skipping asset because we already have _ContentVersion %@ (or newer)", contentVersion); continue; } ASProgressHandler OTATrustHandler = ^(NSDictionary *state, NSError *progressError){ NSString *operationState = nil; if (progressError) { - secerror("progress handler failed: %@", progressError); + secerror("OTATrust: progress handler failed: %@", progressError); LogRemotely(OTATrustLogLevelError, &progressError); handler_error = [progressError copy]; if (wait) { @@ -631,7 +773,7 @@ static BOOL DownloadOTATrustAsset(BOOL isLocalOnly, BOOL wait, NSError **error) if (!state) { MakeOTATrustError(&handler_error, OTATrustLogLevelError, NSOSStatusErrorDomain, errSecInternal, - @"OTATrust: no asset state in progress handler"); + @"no asset state in progress handler"); if (wait) { dispatch_semaphore_signal(done); } @@ -647,7 +789,7 @@ static BOOL DownloadOTATrustAsset(BOOL isLocalOnly, BOOL wait, NSError **error) dispatch_semaphore_signal(done); } } - /* Other states keep calling our progress handler until so don't signal */ + /* Other states keep calling our progress handler until completed so don't signal */ }; switch ([asset state]) { @@ -655,7 +797,7 @@ static BOOL DownloadOTATrustAsset(BOOL isLocalOnly, BOOL wait, NSError **error) secdebug("OTATrust", "OTATrust asset needs to be downloaded"); asset.progressHandler= OTATrustHandler; asset.userInitiatedDownload = YES; - [asset beginDownloadWithOptions:@{ASDownloadOptionPriority : ASDownloadPriorityNormal}]; + [asset beginDownloadWithOptions:GetASDownloadOptions(wait)]; began_async_job = true; break; case ASAssetStateInstalled: @@ -667,6 +809,7 @@ static BOOL DownloadOTATrustAsset(BOOL isLocalOnly, BOOL wait, NSError **error) secdebug("OTATrust", "OTATrust asset download paused"); asset.progressHandler = OTATrustHandler; asset.userInitiatedDownload = YES; + [asset adjustDownloadOptions:GetASDownloadOptions(wait) completion:nil]; if (![asset resumeDownloadAndReturnError:&localError]) { if (localError) { secerror("OTATrust: failed to resume download of asset: %@", localError); @@ -681,6 +824,7 @@ static BOOL DownloadOTATrustAsset(BOOL isLocalOnly, BOOL wait, NSError **error) secdebug("OTATrust", "OTATrust asset downloading"); asset.progressHandler = OTATrustHandler; asset.userInitiatedDownload = YES; + [asset adjustDownloadOptions:GetASDownloadOptions(wait) completion:nil]; began_async_job = true; break; default: @@ -740,7 +884,19 @@ static void InitializeOTATrustAsset(dispatch_queue_t queue) { int out_token = 0; notify_register_dispatch(kOTATrustOnDiskAssetNotification, &out_token, queue, ^(int __unused token) { secnotice("OTATrust", "Got notification about a new PKITrustSupplementals asset from system trustd."); - UpdateFromAsset(GetAssetFileURL(nil), [NSNumber numberWithUnsignedLongLong:GetAssetVersion()]); + NSError *nserror = nil; + CFErrorRef error = nil; + NSNumber *asset_version = [NSNumber numberWithUnsignedLongLong:GetAssetVersion(&error)]; + if (error) { + nserror = CFBridgingRelease(error); + } + if (!UpdateFromAsset(GetAssetFileURL(nil), asset_version, &nserror)) { + secerror("OTATrust: failed to update from asset after notification: %@", nserror); + /* Reset our last check-in time and reset the asset version to the system asset version -- even + * though we may be using something newer than that (but not as new as what's on disk). On re-launch + * (provided reading from disk still fails) we'd be using the system asset version anyway. */ + SecOTAPKIResetCurrentAssetVersion(&error); + } }); int out_token2 = 0; notify_register_dispatch(kOTATrustCheckInNotification, &out_token2, queue, ^(int __unused token) { @@ -753,6 +909,7 @@ static void InitializeOTATrustAsset(dispatch_queue_t queue) { static void TriggerPeriodicOTATrustAssetChecks(dispatch_queue_t queue) { if (SecOTAPKIIsSystemTrustd()) { static sec_action_t action; + static bool first_launch = true; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:@"com.apple.security"]; @@ -767,7 +924,10 @@ static void TriggerPeriodicOTATrustAssetChecks(dispatch_queue_t queue) { secnotice("OTATrust", "Setting periodic update delta to %d seconds", delta); action = sec_action_create_with_queue(queue,"OTATrust", delta); sec_action_set_handler(action, ^{ - (void)DownloadOTATrustAsset(NO, NO, nil); + if (!first_launch) { + (void)DownloadOTATrustAsset(NO, NO, nil); + } + first_launch = false; }); }); sec_action_perform(action); @@ -814,13 +974,15 @@ static uint64_t GetSystemVersion(CFStringRef key) { return system_version; } +static bool initialization_error_from_asset_data = false; + static bool ShouldInitializeWithAsset(void) { uint64_t system_version = GetSystemVersion((__bridge CFStringRef)kOTATrustContentVersionKey); - uint64_t asset_version = GetAssetVersion(); + uint64_t asset_version = GetAssetVersion(nil); if (asset_version > system_version) { secnotice("OTATrust", "Using asset v%llu instead of system v%llu", asset_version, system_version); - return true; + return !initialization_error_from_asset_data; } return false; } @@ -883,11 +1045,16 @@ static CF_RETURNS_RETAINED CFDictionaryRef InitializeAllowList() { static CF_RETURNS_RETAINED CFArrayRef InitializeTrustedCTLogs() { NSArray *trustedCTLogs = nil; + NSError *error = nil; #if !TARGET_OS_BRIDGE if (ShouldInitializeWithAsset()) { - trustedCTLogs = [NSArray arrayWithContentsOfURL:GetAssetFileURL(kOTATrustTrustedCTLogsFilename)]; + trustedCTLogs = [NSArray arrayWithContentsOfURL:GetAssetFileURL(kOTATrustTrustedCTLogsFilename) error:&error]; if (!isNSArray(trustedCTLogs)) { - DeleteAssetFromDisk(); + secerror("OTATrust: failed to read CT list from asset data: %@", error); + LogRemotely(OTATrustLogLevelError, &error); + if (!DeleteAssetFromDisk()) { + initialization_error_from_asset_data = true; + } } } #endif @@ -1212,11 +1379,16 @@ static void InitializeEscrowCertificates(CFArrayRef *escrowRoots, CFArrayRef *es static CF_RETURNS_RETAINED CFDictionaryRef InitializeEventSamplingRates() { NSDictionary *analyticsSamplingRates = nil; NSDictionary *eventSamplingRates = nil; + NSError *error = nil; #if !TARGET_OS_BRIDGE if (ShouldInitializeWithAsset()) { - analyticsSamplingRates = [NSDictionary dictionaryWithContentsOfURL:GetAssetFileURL(kOTATrustAnalyticsSamplingRatesFilename)]; + analyticsSamplingRates = [NSDictionary dictionaryWithContentsOfURL:GetAssetFileURL(kOTATrustAnalyticsSamplingRatesFilename) error:&error]; if (!isNSDictionary(analyticsSamplingRates)) { - DeleteAssetFromDisk(); + secerror("OTATrust: failed to read sampling rates from asset data: %@", error); + LogRemotely(OTATrustLogLevelError, &error); + if (!DeleteAssetFromDisk()) { + initialization_error_from_asset_data = true; + } } eventSamplingRates = analyticsSamplingRates[@"Events"]; } @@ -1235,11 +1407,16 @@ static CF_RETURNS_RETAINED CFDictionaryRef InitializeEventSamplingRates() { static CF_RETURNS_RETAINED CFArrayRef InitializeAppleCertificateAuthorities() { NSArray *appleCAs = nil; + NSError *error = nil; #if !TARGET_OS_BRIDGE if (ShouldInitializeWithAsset()) { - appleCAs = [NSArray arrayWithContentsOfURL:GetAssetFileURL(kOTATrustAppleCertifcateAuthoritiesFilename)]; + appleCAs = [NSArray arrayWithContentsOfURL:GetAssetFileURL(kOTATrustAppleCertifcateAuthoritiesFilename) error:&error]; if (!isNSArray(appleCAs)) { - DeleteAssetFromDisk(); + secerror("OTATrust: failed to read Apple CAs list from asset data: %@", error); + LogRemotely(OTATrustLogLevelError, &error); + if (!DeleteAssetFromDisk()) { + initialization_error_from_asset_data = true; + } } } #endif @@ -1259,8 +1436,6 @@ static CF_RETURNS_RETAINED CFArrayRef InitializeAppleCertificateAuthorities() { static SecOTAPKIRef kCurrentOTAPKIRef = NULL; /* This queue is for making changes to the OTAPKI reference */ static dispatch_queue_t kOTAQueue = NULL; -/* This queue is for fetching changes to the OTAPKI reference or otherwise doing maintenance activities */ -static dispatch_queue_t kOTABackgroundQueue = NULL; struct _OpaqueSecOTAPKI { CFRuntimeBase _base; @@ -1323,26 +1498,38 @@ static uint64_t GetSystemTrustStoreVersion(void) { return GetSystemVersion(CFSTR("VersionNumber")); } -static uint64_t GetAssetVersion(void) { +static uint64_t GetAssetVersion(CFErrorRef *error) { @autoreleasepool { /* Get system asset version */ uint64_t version = GetSystemVersion((__bridge CFStringRef)kOTATrustContentVersionKey); #if !TARGET_OS_BRIDGE uint64_t asset_version = 0; - NSDictionary *OTAPKIContext = [NSDictionary dictionaryWithContentsOfURL:GetAssetFileURL(kOTATrustContextFilename)]; + NSError *nserror = nil; + NSDictionary *OTAPKIContext = [NSDictionary dictionaryWithContentsOfURL:GetAssetFileURL(kOTATrustContextFilename) error:&nserror]; if (isNSDictionary(OTAPKIContext)) { NSNumber *tmpNumber = OTAPKIContext[kOTATrustContentVersionKey]; if (isNSNumber(tmpNumber)) { asset_version = [tmpNumber unsignedLongLongValue]; + } else if (error) { + MakeOTATrustError(&nserror, OTATrustLogLevelNotice, NSOSStatusErrorDomain, errSecInvalidValue, + @"OTAContext.plist missing version"); } + } else if (error) { + MakeOTATrustError(&nserror, OTATrustLogLevelNotice, NSOSStatusErrorDomain, errSecMissingValue, + @"OTAContext.plist missing dictionary"); } if (asset_version > version) { return asset_version; } else { - /* Delete old data */ - DeleteAssetFromDisk(); + /* Don't delete the last check-in time so that we know we're up to date with the MobileAsset. */ + if (error) { + /* only log this if we're tracking errors */ + secnotice("OTATrust", "asset (%llu) is not newer than the system version (%llu); deleting stale data", asset_version, version); + *error = CFRetainSafe((__bridge CFErrorRef)nserror); + } + DeleteOldAssetData(); } #endif return version; @@ -1351,10 +1538,19 @@ static uint64_t GetAssetVersion(void) { static CF_RETURNS_RETAINED CFDateRef InitializeLastAssetCheckIn(void) { #if !TARGET_OS_BRIDGE - NSDictionary *OTAPKIContext = [NSDictionary dictionaryWithContentsOfURL:GetAssetFileURL(kOTATrustContextFilename)]; + NSError *error = nil; + NSDictionary *OTAPKIContext = [NSDictionary dictionaryWithContentsOfURL:GetAssetFileURL(kOTATrustContextFilename) error:&error]; if (isNSDictionary(OTAPKIContext)) { NSDate *checkIn = OTAPKIContext[kOTATrustLastCheckInKey]; - return CFRetainSafe((__bridge CFDateRef)checkIn); + if (isNSDate(checkIn)) { + return CFRetainSafe((__bridge CFDateRef)checkIn); + } else { + MakeOTATrustError(&error, OTATrustLogLevelNotice, NSOSStatusErrorDomain, errSecInvalidValue, + @"OTAContext.plist missing check-in"); + } + } else { + MakeOTATrustError(&error, OTATrustLogLevelNotice, NSOSStatusErrorDomain, errSecMissingValue, + @"OTAContext.plist missing dictionary"); } #endif return NULL; @@ -1408,9 +1604,15 @@ static SecOTAPKIRef SecOTACreate() { // Get the list of CAs used by Apple otapkiref->_appleCAs = InitializeAppleCertificateAuthorities(); - // Get the asset version (after possible reset due to missing asset date) - otapkiref->_assetVersion = GetAssetVersion(); - otapkiref->_lastAssetCheckIn = InitializeLastAssetCheckIn(); + // Get the asset version (after possible reset due to missing asset data) + if (!initialization_error_from_asset_data) { + CFErrorRef error = nil; + otapkiref->_assetVersion = GetAssetVersion(&error); + otapkiref->_lastAssetCheckIn = InitializeLastAssetCheckIn(); + CFReleaseNull(error); + } else { + otapkiref->_assetVersion = GetSystemVersion((__bridge CFStringRef)kOTATrustContentVersionKey); + } // Get the valid update snapshot version and format CFIndex update_format = 0; @@ -1498,15 +1700,21 @@ static BOOL UpdateOTACheckInDate(void) { notify_post(kOTATrustCheckInNotification); /* Update the on-disk check-in date, so when we re-launch we remember */ - return UpdateOTAContextOnDisk(kOTATrustLastCheckInKey, checkIn); + NSError *error = nil; + BOOL result = NO; + if (!(result = UpdateOTAContextOnDisk(kOTATrustLastCheckInKey, checkIn, &error))) { + secerror("OTATrust: failed to write last check-in time: %@", error); + } + return result; } else { return NO; } } -static BOOL UpdateFromAsset(NSURL *localURL, NSNumber *asset_version) { +static BOOL UpdateFromAsset(NSURL *localURL, NSNumber *asset_version, NSError **error) { if (!localURL || !asset_version) { - secerror("OTATrust: missing url and version for downloaded asset"); + MakeOTATrustError(error, OTATrustLogLevelError, NSOSStatusErrorDomain, errSecInternal, + @"missing url and version for downloaded asset"); return NO; } __block NSArray *newTrustedCTLogs = NULL; @@ -1516,25 +1724,28 @@ static BOOL UpdateFromAsset(NSURL *localURL, NSNumber *asset_version) { NSURL *TrustedCTLogsFileLoc = [NSURL URLWithString:kOTATrustTrustedCTLogsFilename relativeToURL:localURL]; - newTrustedCTLogs = [NSArray arrayWithContentsOfURL:TrustedCTLogsFileLoc]; + newTrustedCTLogs = [NSArray arrayWithContentsOfURL:TrustedCTLogsFileLoc error:error]; if (!newTrustedCTLogs) { - secerror("OTATrust: unable to create TrustedCTLogs from asset file: %@", TrustedCTLogsFileLoc); + secerror("OTATrust: unable to create TrustedCTLogs from asset file: %@", error ? *error: nil); + LogRemotely(OTATrustLogLevelError, error); return NO; } NSURL *AnalyticsSamplingRatesFileLoc = [NSURL URLWithString:kOTATrustAnalyticsSamplingRatesFilename relativeToURL:localURL]; - newAnalyticsSamplingRates = [NSDictionary dictionaryWithContentsOfURL:AnalyticsSamplingRatesFileLoc]; + newAnalyticsSamplingRates = [NSDictionary dictionaryWithContentsOfURL:AnalyticsSamplingRatesFileLoc error:error]; if (!newAnalyticsSamplingRates) { - secerror("OTATrust: unable to create AnalyticsSamplingRates from asset file: %@", AnalyticsSamplingRatesFileLoc); + secerror("OTATrust: unable to create AnalyticsSamplingRates from asset file: %@", error ? *error: nil); + LogRemotely(OTATrustLogLevelError, error); return NO; } NSURL *AppleCAsFileLoc = [NSURL URLWithString:kOTATrustAppleCertifcateAuthoritiesFilename relativeToURL:localURL]; - newAppleCAs = [NSArray arrayWithContentsOfURL:AppleCAsFileLoc]; + newAppleCAs = [NSArray arrayWithContentsOfURL:AppleCAsFileLoc error:error]; if (!newAppleCAs) { - secerror("OTATrust: unable to create AppleCAs from asset file: %@", AppleCAsFileLoc); + secerror("OTATrust: unable to create AppleCAs from asset file: %@", error ? *error: nil); + LogRemotely(OTATrustLogLevelError, error); return NO; } @@ -1549,12 +1760,14 @@ static BOOL UpdateFromAsset(NSURL *localURL, NSNumber *asset_version) { /* Write the data to disk (so that we don't have to re-download the asset on re-launch) */ DeleteAssetFromDisk(); - if (CopyFileToDisk(kOTATrustTrustedCTLogsFilename, TrustedCTLogsFileLoc) && - CopyFileToDisk(kOTATrustAnalyticsSamplingRatesFilename, AnalyticsSamplingRatesFileLoc) && - CopyFileToDisk(kOTATrustAppleCertifcateAuthoritiesFilename, AppleCAsFileLoc) && - UpdateOTAContextOnDisk(kOTATrustContentVersionKey, asset_version)) { + if (CopyFileToDisk(kOTATrustTrustedCTLogsFilename, TrustedCTLogsFileLoc, error) && + CopyFileToDisk(kOTATrustAnalyticsSamplingRatesFilename, AnalyticsSamplingRatesFileLoc, error) && + CopyFileToDisk(kOTATrustAppleCertifcateAuthoritiesFilename, AppleCAsFileLoc, error) && + UpdateOTAContext(asset_version, error)) { // Set version and check-in time last (after success) /* If we successfully updated the "asset" on disk, signal the other trustds to pick up the changes */ notify_post(kOTATrustOnDiskAssetNotification); + } else { + return NO; } return YES; @@ -1628,8 +1841,7 @@ CFArrayRef SecOTAPKICopyAllowListForAuthKeyID(SecOTAPKIRef otapkiRef, CFStringRe CFArrayRef SecOTAPKICopyTrustedCTLogs(SecOTAPKIRef otapkiRef) { CFArrayRef result = NULL; - if (NULL == otapkiRef) - { + if (NULL == otapkiRef) { return result; } @@ -1781,6 +1993,16 @@ CFDateRef SecOTAPKICopyLastAssetCheckInDate(SecOTAPKIRef otapkiRef) { return CFRetainSafe(otapkiRef->_lastAssetCheckIn); } +bool SecOTAPKIAssetStalenessLessThanSeconds(SecOTAPKIRef otapkiRef, CFTimeInterval seconds) { + if (NULL == otapkiRef || !isDate(otapkiRef->_lastAssetCheckIn)) { + return false; + } + if(fabs([(__bridge NSDate *)otapkiRef->_lastAssetCheckIn timeIntervalSinceNow]) < seconds) { + return true; + } + return false; +} + NSNumber *SecOTAPKIGetSamplingRateForEvent(SecOTAPKIRef otapkiRef, NSString *eventName) { if (NULL == otapkiRef) { return nil; @@ -1857,6 +2079,8 @@ uint64_t SecOTAPKIResetCurrentAssetVersion(CFErrorRef* error) { dispatch_sync(kOTAQueue, ^{ kCurrentOTAPKIRef->_assetVersion = system_version; + CFReleaseNull(kCurrentOTAPKIRef->_lastAssetCheckIn); + kCurrentOTAPKIRef->_lastAssetCheckIn = NULL; }); #if !TARGET_OS_BRIDGE @@ -1866,18 +2090,20 @@ uint64_t SecOTAPKIResetCurrentAssetVersion(CFErrorRef* error) { } uint64_t SecOTAPKISignalNewAsset(CFErrorRef* error) { + NSError *nserror = nil; + uint64_t version = 0; #if !TARGET_OS_BRIDGE if (SecOTAPKIIsSystemTrustd()) { - NSError *nserror = nil; if (!DownloadOTATrustAsset(NO, YES, &nserror) && error) { *error = CFRetainSafe((__bridge CFErrorRef)nserror); } } else { SecError(errSecServiceNotAvailable, error, CFSTR("This function may ony be performed by the system trustd.")); } - return GetAssetVersion(); + version = GetAssetVersion(nil); #else SecError(errSecUnsupportedService, error, CFSTR("This function is not available on this platform")); - return GetAssetVersion(); + version = GetAssetVersion(error); #endif + return version; } diff --git a/OSX/sec/securityd/SOSCloudCircleServer.m b/OSX/sec/securityd/SOSCloudCircleServer.m index d90097fb..d0ce6425 100644 --- a/OSX/sec/securityd/SOSCloudCircleServer.m +++ b/OSX/sec/securityd/SOSCloudCircleServer.m @@ -739,13 +739,22 @@ static bool do_with_account_while_unlocked(CFErrorRef *error, bool (^action)(SOS return result && action_result; } + + CFTypeRef SOSKeychainAccountGetSharedAccount() { __block SOSAccount* result = NULL; + CFErrorRef localError = NULL; - do_with_account(^(SOSAccountTransaction* txn) { + bool success = do_with_account_if_after_first_unlock(&localError, ^bool (SOSAccountTransaction* txn, CFErrorRef *error) { result = txn.account; + return true; }); + + if(!success) { + secnotice("secAccount", "Failed request for account object (%@)", localError); + CFReleaseNull(localError); + } return (__bridge CFTypeRef)result; } diff --git a/OSX/sec/securityd/SecPinningDb.h b/OSX/sec/securityd/SecPinningDb.h index e8e198fc..fc5a21d6 100644 --- a/OSX/sec/securityd/SecPinningDb.h +++ b/OSX/sec/securityd/SecPinningDb.h @@ -45,9 +45,9 @@ extern const CFStringRef kSecPinningDbKeyRules; CFDictionaryRef _Nullable SecPinningDbCopyMatching(CFDictionaryRef _Nonnull query); void SecPinningDbInitialize(void); -#if !TARGET_OS_BRIDGE +#if !TARGET_OS_BRIDGE && __OBJC__ /* Updating the pinning DB isn't supported on BridgeOS because we treat the disk as read-only. */ -bool SecPinningDbUpdateFromURL(CFURLRef url); +bool SecPinningDbUpdateFromURL(NSURL *url, NSError **error); #endif CFNumberRef SecPinningDbCopyContentVersion(void); diff --git a/OSX/sec/securityd/SecPinningDb.m b/OSX/sec/securityd/SecPinningDb.m index 78df4780..a93bae98 100644 --- a/OSX/sec/securityd/SecPinningDb.m +++ b/OSX/sec/securityd/SecPinningDb.m @@ -157,7 +157,7 @@ static inline bool isNSDictionary(id nsType) { return ok; } -- (BOOL) shouldUpdateContent:(NSNumber *)new_version { +- (BOOL) shouldUpdateContent:(NSNumber *)new_version error:(NSError **)nserror { __block CFErrorRef error = NULL; __block BOOL ok = YES; __block BOOL newer = NO; @@ -172,7 +172,7 @@ static inline bool isNSDictionary(id nsType) { if (!ok || error) { secerror("SecPinningDb: error reading content version from database %@", error); } - CFReleaseNull(error); + if (nserror && error) { *nserror = CFBridgingRelease(error); } return newer; } @@ -303,21 +303,25 @@ static inline bool isNSDictionary(id nsType) { } #if !TARGET_OS_BRIDGE -- (BOOL) installDbFromURL:(NSURL *)localURL { +- (BOOL) installDbFromURL:(NSURL *)localURL error:(NSError **)nserror { if (!localURL) { secerror("SecPinningDb: missing url for downloaded asset"); return NO; } NSURL *fileLoc = [NSURL URLWithString:@"CertificatePinning.plist" relativeToURL:localURL]; - __block NSArray *pinningList = [NSArray arrayWithContentsOfURL:fileLoc]; + __block NSArray *pinningList = [NSArray arrayWithContentsOfURL:fileLoc error:nserror]; if (!pinningList) { secerror("SecPinningDb: unable to create pinning list from asset file: %@", fileLoc); return NO; } NSNumber *plist_version = [pinningList objectAtIndex:0]; - if (![self shouldUpdateContent:plist_version]) { + if (![self shouldUpdateContent:plist_version error:nserror]) { + /* Something went wrong reading the DB in order to determine whether this version is new. */ + if (nserror && *nserror) { + return NO; + } /* We got a new plist but we already have that version installed. */ return YES; } @@ -341,7 +345,7 @@ static inline bool isNSDictionary(id nsType) { withAttributes:@{TrustdHealthAnalyticsAttributeAffectedDatabase : @(TAPinningDb), TrustdHealthAnalyticsAttributeDatabaseOperation : @(TAOperationWrite) }]; #endif // ENABLE_TRUSTD_ANALYTICS - CFReleaseNull(error); + if (nserror && error) { *nserror = CFBridgingRelease(error); } } return ok; @@ -817,10 +821,10 @@ CFDictionaryRef _Nullable SecPinningDbCopyMatching(CFDictionaryRef query) { } #if !TARGET_OS_BRIDGE -bool SecPinningDbUpdateFromURL(CFURLRef url) { +bool SecPinningDbUpdateFromURL(NSURL *url, NSError **error) { SecPinningDbInitialize(); - return [pinningDb installDbFromURL:(__bridge NSURL*)url]; + return [pinningDb installDbFromURL:url error:error]; } #endif diff --git a/OSX/sec/securityd/SecRevocationNetworking.m b/OSX/sec/securityd/SecRevocationNetworking.m index 9b1673b9..09eec204 100644 --- a/OSX/sec/securityd/SecRevocationNetworking.m +++ b/OSX/sec/securityd/SecRevocationNetworking.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Apple Inc. All Rights Reserved. + * Copyright (c) 2017-2018 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -530,7 +530,17 @@ bool SecValidUpdateRequest(dispatch_queue_t queue, CFStringRef server, CFIndex v CFDataRef ocspDER = CFRetainSafe(SecOCSPRequestGetDER(orvc->ocspRequest)); NSData *nsOcspDER = CFBridgingRelease(ocspDER); NSString *ocspBase64 = [nsOcspDER base64EncodedStringWithOptions:0]; - NSString *escapedRequest = [ocspBase64 stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLPathAllowedCharacterSet]]; + + /* Ensure that we percent-encode specific characters in the base64 path + which are defined as delimiters in RFC 3986 [2.2]. + */ + static NSMutableCharacterSet *allowedSet = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + allowedSet = [[NSCharacterSet URLPathAllowedCharacterSet] mutableCopy]; + [allowedSet removeCharactersInString:@":/?#[]@!$&'()*+,;="]; + }); + NSString *escapedRequest = [ocspBase64 stringByAddingPercentEncodingWithAllowedCharacters:allowedSet]; NSURLRequest *request = nil; /* Interesting tidbit from rfc5019 @@ -540,9 +550,10 @@ bool SecValidUpdateRequest(dispatch_queue_t queue, CFStringRef server, CFIndex v use the GET method (to enable OCSP response caching). OCSP requests larger than 255 bytes SHOULD be submitted using the POST method. */ - if ([escapedRequest length] < 256) { + if (([[uri absoluteString] length] + 1 + [escapedRequest length]) < 256) { /* Use a GET */ - NSURL *requestURL = [uri URLByAppendingPathComponent:escapedRequest]; + NSString *requestString = [NSString stringWithFormat:@"%@/%@", [uri absoluteString], escapedRequest]; + NSURL *requestURL = [NSURL URLWithString:requestString]; request = [NSURLRequest requestWithURL:requestURL]; } else { /* Use a POST */ diff --git a/OSX/sec/securityd/SecRevocationServer.c b/OSX/sec/securityd/SecRevocationServer.c index c23ea89e..512dd6fd 100644 --- a/OSX/sec/securityd/SecRevocationServer.c +++ b/OSX/sec/securityd/SecRevocationServer.c @@ -1075,8 +1075,6 @@ void SecPathBuilderCheckKnownIntermediateConstraints(SecPathBuilderRef builder) if (analytics) { analytics->valid_unknown_intermediate = true; } - /* [40648172] For now, log this error but do not fail the evaluation. */ - certIX = -1; } SecCertificatePathVCSetUnknownCAIndex(path, certIX); SecCertificatePathVCSetCheckedIssuers(path, true); diff --git a/OSX/shared_regressions/si-44-seckey-aks.m b/OSX/shared_regressions/si-44-seckey-aks.m index 6ba2ecf9..a6568eea 100644 --- a/OSX/shared_regressions/si-44-seckey-aks.m +++ b/OSX/shared_regressions/si-44-seckey-aks.m @@ -14,8 +14,8 @@ #import "shared_regressions.h" -static id generateKey(id keyType) { - id accessControl = (__bridge_transfer id)SecAccessControlCreateWithFlags(NULL, kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly, kSecAccessControlPrivateKeyUsage, NULL); +static id generateKey(id keyType, CFStringRef protection) { + id accessControl = (__bridge_transfer id)SecAccessControlCreateWithFlags(NULL, protection, kSecAccessControlPrivateKeyUsage, NULL); NSDictionary *keyAttributes = @{ (id)kSecAttrTokenID : (id)kSecAttrTokenIDAppleKeyStore, (id)kSecAttrKeyType : keyType, (id)kSecAttrAccessControl : accessControl, @@ -34,7 +34,7 @@ static void secKeySepTest(BOOL testPKA) { keyTypes = @[(id)kSecAttrKeyTypeECSECPrimeRandom, (id)kSecAttrKeyTypeSecureEnclaveAttestation]; } for (id keyType in keyTypes) { - id privateKey = generateKey((id)keyType); + id privateKey = generateKey((id)keyType, kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly); ok(privateKey, "failed to create key '%@'", keyType); id publicKey = (__bridge_transfer id)SecKeyCopyPublicKey((SecKeyRef)privateKey); @@ -83,12 +83,12 @@ static void secKeySepTest(BOOL testPKA) { } } -static void attestationTest(void) { +static void attestationTest(CFStringRef protection) { NSError *error; - id privKey = generateKey((id)kSecAttrKeyTypeECSECPrimeRandom); - id uik = generateKey((id)kSecAttrKeyTypeSecureEnclaveAttestation); + id privKey = generateKey((id)kSecAttrKeyTypeECSECPrimeRandom, protection); + id uik = generateKey((id)kSecAttrKeyTypeSecureEnclaveAttestation, protection); id sik = CFBridgingRelease(SecKeyCopyAttestationKey(kSecKeyAttestationKeyTypeSIK, (void *)&error)); - ok(sik != nil, "get SIk key: %@", error); + ok(sik != nil, "get SIK key: %@", error); id pubSIK = CFBridgingRelease(SecKeyCopyPublicKey((__bridge SecKeyRef)sik)); ok(pubSIK != nil, "get SIK pubkey"); @@ -196,9 +196,10 @@ int si_44_seckey_aks(int argc, char *const *argv) { testPKA = NO; #endif - plan_tests(testPKA ? 66 : 51); + plan_tests(testPKA ? 95 : 80); secKeySepTest(testPKA); - attestationTest(); + attestationTest(kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly); + attestationTest(kSecAttrAccessibleUntilReboot); return 0; } } diff --git a/keychain/KeychainDataclassOwner/KeychainDataclassOwner.m b/keychain/KeychainDataclassOwner/KeychainDataclassOwner.m index af2ef1dd..ff923758 100644 --- a/keychain/KeychainDataclassOwner/KeychainDataclassOwner.m +++ b/keychain/KeychainDataclassOwner/KeychainDataclassOwner.m @@ -72,7 +72,8 @@ static NSString* const KeychainDataclass = @"KeychainDataclass"; NSDictionary* baseQuery = @{ (id)kSecAttrSynchronizable : @(YES), (id)kSecAttrAccessGroup : @"com.apple.cfnetwork", (id)kSecAttrNoLegacy : @(YES), - (id)kSecAttrTombstone : @(NO) }; + (id)kSecAttrTombstone : @(NO), + (id)kSecUseTombstones : @(NO) }; NSMutableDictionary* inetQuery = baseQuery.mutableCopy; inetQuery[(id)kSecClass] = (id)kSecClassInternetPassword; OSStatus inetResult = SecItemDelete((__bridge CFDictionaryRef)inetQuery); diff --git a/keychain/SecItemPriv.h b/keychain/SecItemPriv.h index 9e4f9d77..0476998d 100644 --- a/keychain/SecItemPriv.h +++ b/keychain/SecItemPriv.h @@ -330,11 +330,16 @@ extern const CFStringRef kSecAttrSecureEnclaveKeyBlob which is going to be deprecated for 3rd party use. @constant kSecAttrAccessibleAlwaysThisDeviceOnlyPrivate for kSecAttrAccessibleAlwaysThisDeviceOnly, which is going to be deprecated for 3rd party use. + @constant kSecAttrAccessibleUntilReboot Not usable for keychain item. Can be used only + for generating non-permanent SEP-based SecKey. Such key does not need any keybag loaded and + is valid only until next reboot. Also known as class F protection. */ extern const CFStringRef kSecAttrAccessibleAlwaysPrivate ;//%%% __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); extern const CFStringRef kSecAttrAccessibleAlwaysThisDeviceOnlyPrivate ;//%%% __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); +extern const CFStringRef kSecAttrAccessibleUntilReboot +API_AVAILABLE(macos(10.14.1), ios(12.1), tvos(12.1), watchos(5.1)); /* View Hint Constants */ diff --git a/keychain/ckks/CKKSKeychainView.m b/keychain/ckks/CKKSKeychainView.m index d603cf4a..4a958f08 100644 --- a/keychain/ckks/CKKSKeychainView.m +++ b/keychain/ckks/CKKSKeychainView.m @@ -1361,6 +1361,7 @@ [existingPeerShare.receiver.publicEncryptionKey isEqual:self.currentSelfPeers.currentSelf.publicEncryptionKey]) { ckksnotice("ckksshare", self, "Local peer %@ is shared %@ via self: %@", peer, key, existingPeerShare); alreadyShared = true; + break; } else { ckksnotice("ckksshare", self, "Local peer %@ is shared %@ via trusted %@, but that's not good enough", peer, key, existingPeerShare); } @@ -1371,6 +1372,7 @@ // Some other peer has a trusted share. Cool! ckksnotice("ckksshare", self, "Peer %@ is shared %@ via trusted %@", peer, key, existingPeerShare); alreadyShared = true; + break; } else { ckksnotice("ckksshare", self, "Peer %@ has a share for %@, but to old keys: %@", peer, key, existingPeerShare); } diff --git a/keychain/ckks/CKKSViewManager.m b/keychain/ckks/CKKSViewManager.m index f3dea667..e5a09126 100644 --- a/keychain/ckks/CKKSViewManager.m +++ b/keychain/ckks/CKKSViewManager.m @@ -626,6 +626,11 @@ dispatch_once_t globalZoneStateQueueOnce; - (void)syncBackupAndNotifyAboutSync { SOSAccount* account = (__bridge SOSAccount*)SOSKeychainAccountGetSharedAccount(); + + if(!account) { + secnotice("ckks", "Failed to get account object"); + return; + } [account performTransaction:^(SOSAccountTransaction * _Nonnull txn) { CFErrorRef error = NULL; diff --git a/libsecurity_smime/lib/cmsasn1.c b/libsecurity_smime/lib/cmsasn1.c index 91448a7e..eadf40ec 100644 --- a/libsecurity_smime/lib/cmsasn1.c +++ b/libsecurity_smime/lib/cmsasn1.c @@ -321,11 +321,13 @@ static const SecAsn1Template SecCmsOriginatorIdentifierOrKeyTemplate[] = { const SecAsn1Template SecCmsRecipientKeyIdentifierTemplate[] = { { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SecCmsRecipientKeyIdentifier) }, - { SEC_ASN1_OCTET_STRING, - offsetof(SecCmsRecipientKeyIdentifier,subjectKeyIdentifier) }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_OCTET_STRING, - offsetof(SecCmsRecipientKeyIdentifier,date) }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_OCTET_STRING, + { SEC_ASN1_INLINE | SEC_ASN1_OCTET_STRING, + offsetof(SecCmsRecipientKeyIdentifier,subjectKeyIdentifier), + SEC_ASN1_SUB(kSecAsn1OctetStringTemplate) }, + { SEC_ASN1_INLINE | SEC_ASN1_OPTIONAL | SEC_ASN1_GENERALIZED_TIME, + offsetof(SecCmsRecipientKeyIdentifier,date), + SEC_ASN1_SUB(kSecAsn1GeneralizedTimeTemplate) }, + { SEC_ASN1_INLINE | SEC_ASN1_OPTIONAL | SEC_ASN1_ANY, offsetof(SecCmsRecipientKeyIdentifier,other) }, { 0 } }; diff --git a/libsecurity_smime/lib/cmsreclist.c b/libsecurity_smime/lib/cmsreclist.c index 2563db40..9e5c7bf1 100644 --- a/libsecurity_smime/lib/cmsreclist.c +++ b/libsecurity_smime/lib/cmsreclist.c @@ -100,7 +100,7 @@ nss_cms_recipients_traverse(SecCmsRecipientInfoRef *recipientinfos, SecCmsRecipi break; case SecCmsKeyAgreeRecipientIDRKeyID: rle->kind = RLSubjKeyID; - rle->id.subjectKeyID = rek->recipientIdentifier.id.recipientKeyIdentifier.subjectKeyIdentifier; + rle->id.subjectKeyID = &rek->recipientIdentifier.id.recipientKeyIdentifier.subjectKeyIdentifier; break; } recipient_list[rlindex++] = rle; diff --git a/libsecurity_smime/lib/cmstpriv.h b/libsecurity_smime/lib/cmstpriv.h index fede4e52..c5985d1c 100644 --- a/libsecurity_smime/lib/cmstpriv.h +++ b/libsecurity_smime/lib/cmstpriv.h @@ -301,9 +301,9 @@ struct SecCmsOriginatorIdentifierOrKeyStr { typedef struct SecCmsOriginatorIdentifierOrKeyStr SecCmsOriginatorIdentifierOrKey; struct SecCmsRecipientKeyIdentifierStr { - SecAsn1Item * subjectKeyIdentifier; - SecAsn1Item * date; /* optional */ - SecAsn1Item * other; /* optional */ + SecAsn1Item subjectKeyIdentifier; + SecAsn1Item date; /* optional */ + SecAsn1Item other; /* optional */ }; typedef struct SecCmsRecipientKeyIdentifierStr SecCmsRecipientKeyIdentifier; diff --git a/libsecurity_smime/lib/crypto-embedded.c b/libsecurity_smime/lib/crypto-embedded.c index 6cf8af24..da4b7956 100644 --- a/libsecurity_smime/lib/crypto-embedded.c +++ b/libsecurity_smime/lib/crypto-embedded.c @@ -348,8 +348,12 @@ static CFTypeRef CERT_FindBySubjectKeyID (CFTypeRef keychainOrArray, CFTypeRef c { CFTypeRef ident = NULL; CFDictionaryRef query = NULL; - CFDataRef subjectkeyid = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, subjKeyID->Data, subjKeyID->Length, kCFAllocatorNull); + if (!subjKeyID || !subjKeyID->Data || !subjKeyID->Length) { + return NULL; + } + + CFDataRef subjectkeyid = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, subjKeyID->Data, subjKeyID->Length, kCFAllocatorNull); if (keychainOrArray && (CFGetTypeID(keychainOrArray) == CFArrayGetTypeID()) && CFEqual(class, kSecClassCertificate)) { CFIndex c, count = CFArrayGetCount((CFArrayRef)keychainOrArray); diff --git a/libsecurity_smime/lib/smimeutil.c b/libsecurity_smime/lib/smimeutil.c index 3e7f1c04..ae6a5d8f 100644 --- a/libsecurity_smime/lib/smimeutil.c +++ b/libsecurity_smime/lib/smimeutil.c @@ -118,8 +118,8 @@ static const SecAsn1Template smime_encryptionkeypref_template[] = { NSSSMIMEEncryptionKeyPref_IssuerSN }, { SEC_ASN1_POINTER | SEC_ASN1_CONTEXT_SPECIFIC | 1, offsetof(NSSSMIMEEncryptionKeyPreference,id.recipientKeyID), - SecCmsRecipientKeyIdentifierTemplate, - NSSSMIMEEncryptionKeyPref_IssuerSN }, + SEC_ASN1_SUB(SecCmsRecipientKeyIdentifierTemplate), + NSSSMIMEEncryptionKeyPref_RKeyID }, { SEC_ASN1_POINTER | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 2, offsetof(NSSSMIMEEncryptionKeyPreference,id.subjectKeyID), SEC_ASN1_SUB(kSecAsn1OctetStringTemplate), @@ -806,8 +806,10 @@ SecSMIMEGetCertFromEncryptionKeyPreference(SecAsn1Item **rawCerts, SecAsn1Item * cert = CERT_FindCertificateByIssuerAndSN(certs, ekp.id.issuerAndSN); break; case NSSSMIMEEncryptionKeyPref_RKeyID: + cert = CERT_FindCertificateBySubjectKeyID(certs, &ekp.id.recipientKeyID->subjectKeyIdentifier); + break; case NSSSMIMEEncryptionKeyPref_SubjectKeyID: - cert = CERT_FindCertificateBySubjectKeyID(certs, ekp.id.subjectKeyID); + cert = CERT_FindCertificateBySubjectKeyID(certs, ekp.id.subjectKeyID); break; default: PORT_Assert(0); diff --git a/trust/SecTrust.h b/trust/SecTrust.h index 04f5dfa5..e1eada2c 100644 --- a/trust/SecTrust.h +++ b/trust/SecTrust.h @@ -33,6 +33,7 @@ #include #include #include +#include __BEGIN_DECLS @@ -349,7 +350,11 @@ CFAbsoluteTime SecTrustGetVerifyTime(SecTrustRef trust) run loop. Alternatively, you can use the SecTrustEvaluateAsync function. */ OSStatus SecTrustEvaluate(SecTrustRef trust, SecTrustResultType *result) - __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); + API_DEPRECATED_WITH_REPLACEMENT("SecTrustEvaluateWithError", + macos(10.3, API_TO_BE_DEPRECATED), + ios(2.0, API_TO_BE_DEPRECATED), + watchos(1.0, API_TO_BE_DEPRECATED), + tvos(2.0, API_TO_BE_DEPRECATED)); #ifdef __BLOCKS__ /*! -- 2.45.2