]> git.saurik.com Git - apple/security.git/blob - OSX/sec/SOSCircle/SecureObjectSync/SOSAccountTrustClassic+Identity.m
1851591929b764e5044d6eff2b5303ef01628ca5
[apple/security.git] / OSX / sec / SOSCircle / SecureObjectSync / SOSAccountTrustClassic+Identity.m
1 //
2 // SOSAccountTrustClassicIdentity.m
3 // Security
4 //
5
6
7 #import <Foundation/Foundation.h>
8 #include <AssertMacros.h>
9 #import "Security/SecureObjectSync/SOSAccountTrustClassic.h"
10 #import "Security/SecureObjectSync/SOSAccountTrustClassic+Expansion.h"
11 #import "Security/SecureObjectSync/SOSAccountTrustClassic+Identity.h"
12 #import "Security/SecureObjectSync/SOSAccountTrustClassic+Circle.h"
13
14 #import "Security/SecureObjectSync/SOSViews.h"
15
16 @implementation SOSAccountTrustClassic (Identity)
17
18 -(bool) updateFullPeerInfo:(SOSAccount*)account minimum:(CFSetRef)minimumViews excluded:(CFSetRef)excludedViews
19 {
20 if (self.trustedCircle && self.fullPeerInfo) {
21 if(SOSFullPeerInfoUpdateToCurrent(self.fullPeerInfo, minimumViews, excludedViews)) {
22 [self modifyCircle:account.circle_transport err:NULL action:^(SOSCircleRef circle_to_change) {
23 secnotice("circleChange", "Calling SOSCircleUpdatePeerInfo for gestalt change");
24 return SOSCircleUpdatePeerInfo(circle_to_change, self.peerInfo);
25 }];
26 }
27 }
28
29 return true;
30 }
31
32 -(SOSFullPeerInfoRef) getMyFullPeerInfo
33 {
34 return self.trustedCircle ? self.fullPeerInfo : NULL;
35 }
36
37 -(bool) fullPeerInfoVerify:(SecKeyRef) privKey err:(CFErrorRef *)error
38 {
39 if(!self.fullPeerInfo) return false;
40 SecKeyRef pubKey = SecKeyCreatePublicFromPrivate(privKey);
41 bool retval = SOSPeerInfoApplicationVerify(self.peerInfo, pubKey, error);
42 CFReleaseNull(pubKey);
43 return retval;
44 }
45
46 -(bool) hasFullPeerInfo:(CFErrorRef*) error
47 {
48 bool hasPeer = false;
49 if(![self hasCircle:error]){
50 return hasPeer;
51 }
52 hasPeer = self.fullPeerInfo != NULL;
53
54 if (!hasPeer)
55 SOSCreateErrorWithFormat(kSOSErrorPeerNotFound, NULL, error, NULL, CFSTR("No peer for circle"));
56
57 return hasPeer;
58 }
59
60 -(SOSFullPeerInfoRef) CopyAccountIdentityPeerInfo
61 {
62 return SOSFullPeerInfoCopyFullPeerInfo(self.fullPeerInfo);
63 }
64
65 - (SecKeyRef)randomPermanentFullECKey:(int)keysize name:(NSString *)name error:(CFErrorRef*)cferror
66 {
67 return GeneratePermanentFullECKey(keysize, (__bridge CFStringRef)name, cferror);
68 }
69
70 - (void)ensureOctagonPeerKeys:(SOSKVSCircleStorageTransport*)circleTransport
71 {
72 NSString* octagonKeyName;
73 SecKeyRef publicKey;
74
75 bool changedSelf = false;
76
77 CFErrorRef copyError = NULL;
78 publicKey = SOSFullPeerInfoCopyOctagonSigningKey(self.fullPeerInfo, &copyError);
79 if(copyError) {
80 secerror("circleChange: Error fetching Octagon signing key: %@", copyError);
81 CFReleaseNull(copyError);
82 }
83
84 if (publicKey == NULL) {
85 octagonKeyName = [NSString stringWithFormat:@"Octagon Peer Signing ID for %@", SOSCircleGetName(self.trustedCircle)];
86 CFErrorRef cferror = NULL;
87 SecKeyRef octagonSigningFullKey = [self randomPermanentFullECKey:384 name:octagonKeyName error:&cferror];
88 if(cferror || !octagonSigningFullKey) {
89 secerror("circleChange: Error upgrading Octagon signing key: %@", cferror);
90 } else {
91 SOSFullPeerInfoUpdateOctagonSigningKey(self.fullPeerInfo, octagonSigningFullKey, &cferror);
92 if(cferror) {
93 secerror("circleChange: Error upgrading Octagon signing key: %@", cferror);
94 }
95 changedSelf = true;
96 }
97
98 CFReleaseNull(cferror);
99 CFReleaseNull(octagonSigningFullKey);
100 }
101 CFReleaseNull(publicKey);
102
103 CFReleaseNull(copyError);
104 publicKey = SOSFullPeerInfoCopyOctagonEncryptionKey(self.fullPeerInfo, &copyError);
105 if(copyError) {
106 secerror("circleChange: Error fetching Octagon encryption key: %@", copyError);
107 CFReleaseNull(copyError);
108 }
109
110 if (publicKey == NULL) {
111 octagonKeyName = [NSString stringWithFormat:@"Octagon Peer Encryption ID for %@", SOSCircleGetName(self.trustedCircle)];
112 CFErrorRef cferror = NULL;
113 SecKeyRef octagonEncryptionFullKey = [self randomPermanentFullECKey:384 name:octagonKeyName error:&cferror];
114 if(cferror || !octagonEncryptionFullKey) {
115 secerror("circleChange: Error upgrading Octagon encryption key: %@", cferror);
116 } else {
117
118 SOSFullPeerInfoUpdateOctagonEncryptionKey(self.fullPeerInfo, octagonEncryptionFullKey, &cferror);
119 if(cferror) {
120 secerror("circleChange: Error upgrading Octagon encryption key: %@", cferror);
121 }
122 changedSelf = true;
123 }
124
125 CFReleaseNull(cferror);
126 CFReleaseNull(octagonEncryptionFullKey);
127 }
128 CFReleaseNull(publicKey);
129
130 if(changedSelf) {
131 [self modifyCircle:circleTransport err:NULL action:^bool (SOSCircleRef circle_to_change) {
132 return SOSCircleUpdatePeerInfo(circle_to_change, SOSFullPeerInfoGetPeerInfo(self.fullPeerInfo));
133 }];
134 }
135 }
136
137 -(bool) ensureFullPeerAvailable:(CFDictionaryRef)gestalt deviceID:(CFStringRef)deviceID backupKey:(CFDataRef)backup err:(CFErrorRef *) error
138 {
139 require_action_quiet(self.trustedCircle, fail, SOSCreateErrorWithFormat(kSOSErrorNoCircle, NULL, error, NULL, CFSTR("Don't have circle")));
140
141 if (self.fullPeerInfo == NULL) {
142 NSString* octagonKeyName;
143 CFStringRef keyName = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("ID for %@-%@"), SOSPeerGestaltGetName(gestalt), SOSCircleGetName(self.trustedCircle));
144 SecKeyRef full_key = [self randomPermanentFullECKey:256 name:(__bridge NSString *)keyName error:NULL];
145
146 octagonKeyName = [@"Octagon Peer Signing " stringByAppendingString:(__bridge NSString*)keyName];
147 SecKeyRef octagonSigningFullKey = [self randomPermanentFullECKey:384 name:octagonKeyName error:NULL];
148
149 octagonKeyName = [@"Octagon Peer Encryption " stringByAppendingString:(__bridge NSString*)keyName];
150 SecKeyRef octagonEncryptionFullKey = [self randomPermanentFullECKey:384 name:octagonKeyName error:NULL];
151
152 if (full_key && octagonSigningFullKey && octagonEncryptionFullKey) {
153 CFSetRef initialViews = SOSViewCopyViewSet(kViewSetInitial);
154
155 self.fullPeerInfo = nil;
156 self.fullPeerInfo = SOSFullPeerInfoCreateWithViews(kCFAllocatorDefault, gestalt, backup, initialViews, full_key, octagonSigningFullKey, octagonEncryptionFullKey, error);
157
158 CFDictionaryRef v2dictionaryTestUpdates = [self getValueFromExpansion:kSOSTestV2Settings err:NULL];
159 if(v2dictionaryTestUpdates) SOSFullPeerInfoUpdateV2Dictionary(self.fullPeerInfo, v2dictionaryTestUpdates, NULL);
160 CFReleaseNull(initialViews);
161 CFReleaseNull(full_key);
162
163 CFSetRef pendingDefaultViews = SOSViewCopyViewSet(kViewSetDefault);
164 [self pendEnableViewSet:pendingDefaultViews];
165 CFReleaseNull(pendingDefaultViews);
166
167 [self setValueInExpansion:kSOSUnsyncedViewsKey value:kCFBooleanTrue err:NULL];
168
169 if (!self.fullPeerInfo) {
170 secerror("Can't make FullPeerInfo for %@-%@ (%@) - is AKS ok?", SOSPeerGestaltGetName(gestalt), SOSCircleGetName(self.trustedCircle), error ? (void*)*error : (void*)CFSTR("-"));
171 }
172 else{
173 secnotice("fpi", "alert KeychainSyncingOverIDSProxy the fpi is available");
174 notify_post(kSecServerPeerInfoAvailable);
175 if(deviceID)
176 SOSFullPeerInfoUpdateDeviceID(self.fullPeerInfo, deviceID, error);
177 }
178 }
179 else {
180 secerror("No full_key: %@:", error ? *error : NULL);
181
182 }
183
184 CFReleaseNull(full_key);
185 CFReleaseNull(octagonSigningFullKey);
186 CFReleaseNull(octagonEncryptionFullKey);
187 CFReleaseNull(keyName);
188 }
189
190 fail:
191 return self.fullPeerInfo != NULL;
192 }
193 -(bool) isMyPeerActive:(CFErrorRef*) error
194 {
195 return (self.peerInfo ? SOSCircleHasActivePeer(self.trustedCircle, self.peerInfo, error) : false);
196 }
197
198 -(void) purgeIdentity
199 {
200 if (self.fullPeerInfo) {
201 // Purge private key but don't return error if we can't.
202 CFErrorRef purgeError = NULL;
203 if (!SOSFullPeerInfoPurgePersistentKey(self.fullPeerInfo, &purgeError)) {
204 secwarning("Couldn't purge persistent key for %@ [%@]", self.fullPeerInfo, purgeError);
205 }
206 CFReleaseNull(purgeError);
207
208 self.fullPeerInfo=nil;
209 }
210 }
211 @end