]> git.saurik.com Git - apple/security.git/commitdiff
Security-58286.220.15.tar.gz macos-10141 v58286.220.15
authorApple <opensource@apple.com>
Thu, 6 Dec 2018 05:21:02 +0000 (05:21 +0000)
committerApple <opensource@apple.com>
Thu, 6 Dec 2018 05:21:02 +0000 (05:21 +0000)
42 files changed:
Analytics/SFAnalytics.h
Analytics/SFAnalytics.m
CircleJoinRequested/CircleJoinRequested.m
OSX/lib/en.lproj/authorization.dfr.prompts-BBBAA77A32-C4EBFEA440.strings
OSX/lib/en.lproj/authorization.prompts.strings
OSX/libsecurity_codesigning/lib/SecRequirement.cpp
OSX/libsecurity_codesigning/lib/codedirectory.cpp
OSX/libsecurity_codesigning/lib/policydb.cpp
OSX/libsecurity_codesigning/lib/resources.cpp
OSX/libsecurity_smime/lib/cmsasn1.c
OSX/libsecurity_smime/lib/cmsreclist.c
OSX/libsecurity_smime/lib/cmstpriv.h
OSX/libsecurity_smime/lib/smimeutil.c
OSX/libsecurity_utilities/lib/mach++.cpp
OSX/libsecurity_utilities/lib/mach++.h
OSX/libsecurity_utilities/lib/machserver.cpp
OSX/sec/SOSCircle/SecureObjectSync/SOSAccountRecovery.m
OSX/sec/SOSCircle/SecureObjectSync/SOSEnsureBackup.m
OSX/sec/Security/Regressions/secitem/si-66-smime.c
OSX/sec/Security/Regressions/secitem/si-66-smime/smime_attr_emails.h
OSX/sec/Security/SecAccessControl.c
OSX/sec/Security/SecExports.exp-in
OSX/sec/Security/SecItemConstants.c
OSX/sec/SharedWebCredential/swcagent.m
OSX/sec/securityd/OTATrustUtilities.h
OSX/sec/securityd/OTATrustUtilities.m
OSX/sec/securityd/SOSCloudCircleServer.m
OSX/sec/securityd/SecPinningDb.h
OSX/sec/securityd/SecPinningDb.m
OSX/sec/securityd/SecRevocationNetworking.m
OSX/sec/securityd/SecRevocationServer.c
OSX/shared_regressions/si-44-seckey-aks.m
keychain/KeychainDataclassOwner/KeychainDataclassOwner.m
keychain/SecItemPriv.h
keychain/ckks/CKKSKeychainView.m
keychain/ckks/CKKSViewManager.m
libsecurity_smime/lib/cmsasn1.c
libsecurity_smime/lib/cmsreclist.c
libsecurity_smime/lib/cmstpriv.h
libsecurity_smime/lib/crypto-embedded.c
libsecurity_smime/lib/smimeutil.c
trust/SecTrust.h

index 130aec0fa52c0756558dcec691c2642f44cb8ea6..9a135bd2e38c8aaa41c06d51eb46abeee5e051f1 100644 (file)
@@ -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;
index 28e674cb9e5ebbcebe78f222aa7eb5510b3f0662..5f2d531a9a446004ea174456c89e03b3f91170cc 100644 (file)
@@ -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];
index 4f6ed2e243334332dccab3efce0bdc64f53e016e..1cbf8ad12508239e7e8931d59eecd27aaea70122 100644 (file)
@@ -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){
index 6ef3830777a22c9fcc44d9d72627165a595e5c91..7cb67dfb5395036dbd98ef5dbd415b1b9767d928 100644 (file)
 
 "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.";
 
index 0253a7c5a4c17f2c4de15d5943b197e169525d70..932855d9d0592e7e9f8b88a102adfc43ba4a332a 100644 (file)
 
 "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.";
 
index 1ed75082fccd829343c266d8a7dae58ad5b0490b..7c44fcf6f535025c7a2946b8366d6e3a933c123f 100644 (file)
@@ -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<CFNumberRef> keys_vector(count, NULL);
+       vector<SecRequirementRef> 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<Requirements::Type>(keys[n]), req->clone());
+               const Requirement *req = SecRequirement::required(reqs_vector[n])->requirement();
+               maker.add(cfNumber<Requirements::Type>(keys_vector[n]), req->clone());
        }
        Requirements *reqset = maker.make();                                    // malloc'ed
        CodeSigning::Required(requirementSet) = makeCFDataMalloc(*reqset);      // takes ownership of reqs
index 5218ef4b1cf75b6ebeb782c23f4e68f64ffc670d..4d3c1c80015884dcc02a2837b9ade80189e8310b 100644 (file)
@@ -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<CodeDirectory> hasher(this);
-       Hashing::Byte digest[hasher->digestLength()];
-       generateHash(hasher, data, length, digest);
-       return memcmp(digest, getSlot(slot, preEncrypt), hasher->digestLength()) == 0;
+       vector<Hashing::Byte> 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<CodeDirectory> hasher(this);
-       Hashing::Byte digest[hasher->digestLength()];
-       generateHash(hasher, fd, digest, length);
-       return memcmp(digest, getSlot(slot, preEncrypt), hasher->digestLength()) == 0;
+       vector<Hashing::Byte> 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<CodeDirectory> hash(this);
-       Hashing::Byte digest[hash->digestLength()];
+       vector<Hashing::Byte> 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());
 }
index 0be1a6cf114310a2a4f76fc236a9f9a4f9717e49..9e330e17c558eb55f221d3b270f2124161d5216f 100644 (file)
@@ -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<CFStringRef> keys_vector(count, NULL);
+                       vector<CFDictionaryRef> 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<CFNumberRef>("version")) {
                                        int version = cfNumber<int>(versionRef);
index 25ddade7c61798bda60707492b63fc6a445658b8..2c8a43effdfda74639d892d61db617a459b7a4cb 100644 (file)
@@ -286,9 +286,10 @@ CFDataRef ResourceBuilder::hashFile(const char *path, CodeDirectory::HashAlgorit
        fd.fcntl(F_NOCACHE, true);              // turn off page caching (one-pass)
        RefPointer<DynamicHash> hasher(CodeDirectory::hashFor(type));
        hashFileData(fd, hasher.get());
-       Hashing::Byte digest[hasher->digestLength()];
-       hasher->finish(digest);
-       return CFDataCreate(NULL, digest, sizeof(digest));
+       vector<Hashing::Byte> 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<Hashing::Byte> digest_vector(length);
+               hasher->finish(digest_vector.data());
+               CFDictionaryAddValue(resultRef, CFTempString(hashName(type)), CFTempData(digest_vector.data(), length));
        });
        return result.yield();
 }
index 7a70f886a48bdc7c346b3b661a7d93243bffea7d..bbb53f57ceefb1ca4109c9e706e2191004649189 100644 (file)
@@ -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 }
 };
index cfadee8c708a21d360ec82bc9b97d070ae8261cb..ecf3179eaff5c0c0f133d8c847f12e145472b554 100644 (file)
@@ -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;
index 5d0f5617dbaff95e9048d3fffbf88c4eb0e502d7..4c78e6e44ee8462e433f356c5a1b63cd32c685f1 100644 (file)
@@ -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;
 
index 61bd6f0568b920bd00c9769750ce4662eaab22e4..569c7f65b7b1a5bb5f6b929619017583756b064f 100644 (file)
@@ -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);
index c8271d949c85b089bb0f0c2dde25ca00c1889313..ab6bb98201d7c11ba8869c080688fd4bad6fd643 100644 (file)
@@ -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.
index b2fe942523814dacf274f757157357c4b94231ca..dba14c3786629220ea476120aa977dc38ba9c4df 100644 (file)
@@ -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; }
index 8f825ba2ae1265944bc65c91d6e60240827c06c9..29ffa83a3c97936646451b291667abb3192e464b 100644 (file)
@@ -40,6 +40,8 @@
 # include <sys/time.h>
 #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
index b93c6b5e4ecf787644d79559ae88997b8a6386fd..e9757938f08676a3102fa82843f264ec53ee7ed0 100644 (file)
@@ -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);
index be8a73fceffd1630166f922c22532f73d84c5e1c..e9389196c8a3ec3e1a1bd1bf7d0ff5211bbc1d50 100644 (file)
@@ -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));
index 8fc837e5e9b2c2d8be117b2ce2e2acaa0fcc9c38..0ad24d90bb7bc728ab371d1624f9066649915f0a 100644 (file)
@@ -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();
index 8a77186fede2a45f30dbaa9178419b4353105c81..7dfe2bb55d73b33114b29be9fe583080c466ac84 100644 (file)
@@ -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
+};
index 8dab3c4992b39d6cb614c50fd08fd57d4aef7751..ed8671b448940c1230e511ed148682b018c08353 100644 (file)
@@ -251,7 +251,8 @@ bool SecAccessControlSetProtection(SecAccessControlRef access_control, CFTypeRef
                                                kSecAttrAccessibleWhenUnlocked, kSecAttrAccessibleAlwaysThisDeviceOnlyPrivate,
                                                kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly,
                                                kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
-                                               kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly),
+                                               kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly,
+                                               kSecAttrAccessibleUntilReboot),
                          CFSTR("SecAccessControl: invalid protection"));
     }
 
index 20fa2fd8684d890a4bc69adb4b516396a4479fa4..d9f013ecf5ce19698dfd72817e0de83f91b713cf 100644 (file)
@@ -1260,6 +1260,7 @@ _kSecAttrAccessibleWhenUnlocked
 _kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
 _kSecAttrAccessibleAlwaysThisDeviceOnly
 _kSecAttrAccessibleAlwaysThisDeviceOnlyPrivate
+_kSecAttrAccessibleUntilReboot
 _kSecAttrAccessibleWhenUnlockedThisDeviceOnly
 _kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly
 _kSecAttrAccount
@@ -1394,6 +1395,7 @@ _kSecAttrAccessibleAlways
 _kSecAttrAccessibleAlwaysPrivate
 _kSecAttrAccessibleAlwaysThisDeviceOnly
 _kSecAttrAccessibleAlwaysThisDeviceOnlyPrivate
+_kSecAttrAccessibleUntilReboot
 _kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly
 _kSecAttrAccessibleWhenUnlocked
 _kSecAttrAccessibleWhenUnlockedThisDeviceOnly
index 0c1822a8d78badadd50565b0a892f21303fa6b8b..3231cbc307bd25ad1400f0ea8daa06f1e5862aca 100644 (file)
@@ -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 ");
index 862b8376eb7c55a07ce6c3bddde16704c7f7c617..a93776671ef3bf98f4bbadd4e5ff1cea77309331 100644 (file)
@@ -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);
index 71ccc3b64b32e1d30cff8b6368bf005000e4ba88..74f33fe5455df090b54eb1b5a9e17681d3d38dee 100644 (file)
@@ -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
index 6431ac00a18d49d5d9f43d8c8b83f83b990acc55..4582e3dab4a3970d051b20b1e441e52bf0eef23f 100644 (file)
 #import <securityd/SecTrustLoggingServer.h>
 #endif
 
+#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
+#import <MobileKeyBag/MobileKeyBag.h>
+#endif
+
 #if TARGET_OS_OSX
 #import <MobileAsset/MobileAsset.h>
 #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 */
 /* <rdar://problem/30879827> 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;
 }
index d90097fbdb54343a8b34c095b874a4e6e6025886..d0ce64254a7816d72d7480eef95da5ca98aad506 100644 (file)
@@ -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;
 }
index e8e198fcd91ccc0a1ff7f2ddb06f961719206dcd..fc5a21d6fe3787cf79c039d92b2e002024e584f6 100644 (file)
@@ -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);
index 78df478018c1bae061854788ad3465f0504be947..a93bae984dea0b77b7e771a0242db069af966bb9 100644 (file)
@@ -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
 
index 9b1673b9fc9ee6714ea1b6ecca30b3a39014dbb1..09eec204a15c9bb14fa8fdaf717d2b208a5bcdf6 100644 (file)
@@ -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 */
index c23ea89e5afb14d4c0678a191a6ca003fdd691d3..512dd6fd1f44cd47e24db5d0d3861682e30e67ed 100644 (file)
@@ -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);
index 6ba2ecf9e1d77aa858d764d1ffa69452a6f55020..a6568eea6279815aecbe6879ce6071640f40898a 100644 (file)
@@ -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;
     }
 }
index af2ef1dd1a6f9f421095da6a545052936593bf3b..ff923758643517a6c7fb331d863e136617690aa1 100644 (file)
@@ -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);
index 9e4f9d776f3b5063a1834233388aa85dd61ae535..0476998d28b8701d7c2c7ceea91298287831bc96 100644 (file)
@@ -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 */
 
index d603cf4a12eaf64c46fcaf0ae0096089b73e9160..4a958f083669a97e8e65cfa78610bdad9b5a00e7 100644 (file)
                        [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);
                     }
                         // 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);
                     }
index f3dea6670d09cc7c6d597c101e989113c8f877a4..e5a091263bfa30031e28446b55967fc37f2ab36b 100644 (file)
@@ -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;
index 91448a7ea23433858970dbee3619ed50389a485b..eadf40ec5b62a7632ade05ed6f73e2eb2b33373d 100644 (file)
@@ -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 }
 };
index 2563db402a0035557a5a11aecb33924d7ab951a3..9e5c7bf1c5a1a3a0d09dcd3cad7e3abd1444321a 100644 (file)
@@ -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;
index fede4e5207bc99f69a169af0347a527c1aa01af0..c5985d1c498808e06284e18059e8dcad054af267 100644 (file)
@@ -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;
 
index 6cf8af24ff04f6c1eb0462125427b15ba3300f8d..da4b7956b896367475d1b00765e7c9a39cc537c2 100644 (file)
@@ -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);
index 3e7f1c04cd83270e8f5e2c7e7196ad678bcb0bf7..ae6a5d8f957a7212608e9a42a2426f0c6946cf23 100644 (file)
@@ -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);
index 04f5dfa528413f8992f9104ac3680ca7d765ab36..e1eada2c1b2196bd2e815ed0edd4aca8c57dfdf6 100644 (file)
@@ -33,6 +33,7 @@
 #include <Security/SecBase.h>
 #include <CoreFoundation/CoreFoundation.h>
 #include <AvailabilityMacros.h>
+#include <Availability.h>
 
 __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__
 /*!