]> git.saurik.com Git - apple/security.git/blob - keychain/ot/OTUploadNewCKKSTLKsOperation.m
Security-59754.80.3.tar.gz
[apple/security.git] / keychain / ot / OTUploadNewCKKSTLKsOperation.m
1
2 #if OCTAGON
3
4 #import "utilities/debugging.h"
5
6 #import <CloudKit/CloudKit_Private.h>
7
8 #import "keychain/ot/OTUploadNewCKKSTLKsOperation.h"
9 #import "keychain/ot/OTCuttlefishAccountStateHolder.h"
10 #import "keychain/ot/OTFetchCKKSKeysOperation.h"
11 #import "keychain/ot/OTStates.h"
12 #import "keychain/ckks/CKKSCurrentKeyPointer.h"
13 #import "keychain/ckks/CKKSKeychainView.h"
14 #import "keychain/ckks/CKKSNearFutureScheduler.h"
15 #import "keychain/ckks/CloudKitCategories.h"
16
17 #import "keychain/TrustedPeersHelper/TrustedPeersHelperProtocol.h"
18 #import "keychain/ot/ObjCImprovements.h"
19
20 @interface OTUploadNewCKKSTLKsOperation ()
21 @property OTOperationDependencies* deps;
22
23 @property OctagonState* ckksConflictState;
24 @property OctagonState* peerMissingState;
25
26 @property NSOperation* finishedOp;
27 @end
28
29 @implementation OTUploadNewCKKSTLKsOperation
30 @synthesize intendedState = _intendedState;
31
32 - (instancetype)initWithDependencies:(OTOperationDependencies*)dependencies
33 intendedState:(OctagonState*)intendedState
34 ckksConflictState:(OctagonState*)ckksConflictState
35 peerMissingState:(OctagonState*)peerMissingState
36 errorState:(OctagonState*)errorState
37 {
38 if((self = [super init])) {
39 _deps = dependencies;
40
41 _intendedState = intendedState;
42 _ckksConflictState = ckksConflictState;
43 _peerMissingState = peerMissingState;
44 _nextState = errorState;
45 }
46 return self;
47 }
48
49 - (void)groupStart
50 {
51 secnotice("octagon", "Beginning an operation to upload any pending CKKS tlks");
52
53 WEAKIFY(self);
54
55 NSMutableSet<CKKSKeychainView*>* viewsToUpload = [NSMutableSet set];
56
57 // One (or more) of our sub-CKKSes believes it needs to upload new TLKs.
58 CKKSViewManager* viewManager = self.deps.viewManager;
59 for(CKKSKeychainView* view in viewManager.currentViews) {
60 if([view requiresTLKUpload]) {
61 secnotice("octagon-ckks", "CKKS view %@ needs TLK uploads!", view);
62 [viewsToUpload addObject: view];
63 }
64 }
65
66 if(viewsToUpload.count == 0) {
67 // Nothing to do; return to ready
68 secnotice("octagon-ckks", "No CKKS views need uploads");
69 self.nextState = self.intendedState;
70 return;
71 }
72
73 self.finishedOp = [NSBlockOperation blockOperationWithBlock:^{
74 STRONGIFY(self);
75 secnotice("octagon", "Finishing an update TLKs operation with %@", self.error ?: @"no error");
76 }];
77 [self dependOnBeforeGroupFinished:self.finishedOp];
78
79 OTFetchCKKSKeysOperation* fetchKeysOp = [[OTFetchCKKSKeysOperation alloc] initWithViews:viewsToUpload];
80 [self runBeforeGroupFinished:fetchKeysOp];
81
82 CKKSResultOperation* proceedWithKeys = [CKKSResultOperation named:@"upload-tlks-with-keys"
83 withBlock:^{
84 STRONGIFY(self);
85 [self proceedWithKeys:fetchKeysOp.viewKeySets
86 pendingTLKShares:fetchKeysOp.tlkShares
87 viewsToUpload:viewsToUpload];
88 }];
89
90 [proceedWithKeys addDependency:fetchKeysOp];
91 [self runBeforeGroupFinished:proceedWithKeys];
92 }
93
94 - (void)proceedWithKeys:(NSArray<CKKSKeychainBackedKeySet*>*)viewKeySets
95 pendingTLKShares:(NSArray<CKKSTLKShare*>*)pendingTLKShares
96 viewsToUpload:(NSSet<CKKSKeychainView*>*)viewsToUpload
97 {
98 WEAKIFY(self);
99
100 secnotice("octagon-ckks", "Beginning tlk upload with keys: %@", viewKeySets);
101 [self.deps.cuttlefishXPCWrapper updateTLKsWithContainer:self.deps.containerName
102 context:self.deps.contextID
103 ckksKeys:viewKeySets
104 tlkShares:pendingTLKShares
105 reply:^(NSArray<CKRecord*>* _Nullable keyHierarchyRecords, NSError * _Nullable error) {
106 STRONGIFY(self);
107
108 if(error) {
109 if ([error isCuttlefishError:CuttlefishErrorKeyHierarchyAlreadyExists]) {
110 secnotice("octagon-ckks", "A CKKS key hierarchy is out of date; moving to '%@'", self.ckksConflictState);
111 self.nextState = self.ckksConflictState;
112 } else if ([error isCuttlefishError:CuttlefishErrorUpdateTrustPeerNotFound]) {
113 secnotice("octagon-ckks", "Cuttlefish reports we no longer exist.");
114 self.nextState = self.peerMissingState;
115 self.error = error;
116
117 } else {
118 secerror("octagon: Error calling tlk upload: %@", error);
119 self.error = error;
120 }
121 } else {
122 // Tell CKKS about our shiny new records!
123 for(CKKSKeychainView* view in viewsToUpload) {
124 secnotice("octagon-ckks", "Providing records to %@", view);
125 [view receiveTLKUploadRecords: keyHierarchyRecords];
126 }
127
128 self.nextState = self.intendedState;
129 }
130 [self runBeforeGroupFinished:self.finishedOp];
131 }];
132 }
133
134 @end
135
136 #endif // OCTAGON