]> git.saurik.com Git - apple/security.git/blob - keychain/ckks/CKKS.h
Security-58286.251.4.tar.gz
[apple/security.git] / keychain / ckks / CKKS.h
1 /*
2 * Copyright (c) 2016 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 #ifndef CKKS_h
25 #define CKKS_h
26
27 #include <dispatch/dispatch.h>
28 #include <ipc/securityd_client.h>
29 #include <utilities/SecCFWrappers.h>
30 #include <utilities/SecDb.h>
31 #include <xpc/xpc.h>
32
33 #ifdef __OBJC__
34 #import <Foundation/Foundation.h>
35 NS_ASSUME_NONNULL_BEGIN
36 #else
37 CF_ASSUME_NONNULL_BEGIN
38 #endif
39
40 #ifdef __OBJC__
41
42 typedef NS_ENUM(NSUInteger, SecCKKSItemEncryptionVersion) {
43 CKKSItemEncryptionVersionNone = 0, // No encryption present
44 CKKSItemEncryptionVersion1 = 1, // Current version, AES-SIV 512, not all fields authenticated
45 CKKSItemEncryptionVersion2 = 2, // Seed3 version, AES-SIV 512, all fields (including unknown fields) authenticated
46 };
47
48 extern const SecCKKSItemEncryptionVersion currentCKKSItemEncryptionVersion;
49
50 /* Queue Actions */
51 extern NSString* const SecCKKSActionAdd;
52 extern NSString* const SecCKKSActionDelete;
53 extern NSString* const SecCKKSActionModify;
54
55 /* Queue States */
56 @protocol SecCKKSItemState <NSObject>
57 @end
58 typedef NSString<SecCKKSItemState> CKKSItemState;
59 extern CKKSItemState* const SecCKKSStateNew;
60 extern CKKSItemState* const SecCKKSStateUnauthenticated;
61 extern CKKSItemState* const SecCKKSStateInFlight;
62 extern CKKSItemState* const SecCKKSStateReencrypt;
63 extern CKKSItemState* const SecCKKSStateError;
64 extern CKKSItemState* const SecCKKSStateZoneMismatch; // an item has appeared that's in the wrong zone
65 extern CKKSItemState* const SecCKKSStateDeleted; // meta-state: please delete this item!
66
67 /* Processed States */
68 @protocol SecCKKSProcessedState <NSObject>
69 @end
70 typedef NSString<SecCKKSProcessedState> CKKSProcessedState;
71 extern CKKSProcessedState* const SecCKKSProcessedStateLocal;
72 extern CKKSProcessedState* const SecCKKSProcessedStateRemote;
73
74 /* Key Classes */
75 @protocol SecCKKSKeyClass <NSObject>
76 @end
77 typedef NSString<SecCKKSKeyClass> CKKSKeyClass;
78 extern CKKSKeyClass* const SecCKKSKeyClassTLK;
79 extern CKKSKeyClass* const SecCKKSKeyClassA;
80 extern CKKSKeyClass* const SecCKKSKeyClassC;
81
82 /* Useful CloudKit configuration */
83 extern NSString* SecCKKSContainerName;
84 extern bool SecCKKSContainerUsePCS;
85 extern NSString* const SecCKKSSubscriptionID;
86 extern NSString* const SecCKKSAPSNamedPort;
87
88 /* Item CKRecords */
89 extern NSString* const SecCKRecordItemType;
90 extern NSString* const SecCKRecordHostOSVersionKey;
91 extern NSString* const SecCKRecordEncryptionVersionKey;
92 extern NSString* const SecCKRecordParentKeyRefKey;
93 extern NSString* const SecCKRecordDataKey;
94 extern NSString* const SecCKRecordWrappedKeyKey;
95 extern NSString* const SecCKRecordGenerationCountKey;
96 extern NSString* const SecCKRecordPCSServiceIdentifier;
97 extern NSString* const SecCKRecordPCSPublicKey;
98 extern NSString* const SecCKRecordPCSPublicIdentity;
99 extern NSString* const SecCKRecordServerWasCurrent;
100
101 /* Intermediate Key CKRecord Keys */
102 extern NSString* const SecCKRecordIntermediateKeyType;
103 extern NSString* const SecCKRecordKeyClassKey;
104 //extern NSString* const SecCKRecordWrappedKeyKey;
105 //extern NSString* const SecCKRecordParentKeyRefKey;
106
107 /* TLK Share CKRecord Keys */
108 // These are a bit special; they can't use the record ID as information without parsing.
109 extern NSString* const SecCKRecordTLKShareType;
110 extern NSString* const SecCKRecordSenderPeerID;
111 extern NSString* const SecCKRecordReceiverPeerID;
112 extern NSString* const SecCKRecordReceiverPublicEncryptionKey;
113 extern NSString* const SecCKRecordCurve;
114 extern NSString* const SecCKRecordEpoch;
115 extern NSString* const SecCKRecordPoisoned;
116 extern NSString* const SecCKRecordSignature;
117 extern NSString* const SecCKRecordVersion;
118 //extern NSString* const SecCKRecordParentKeyRefKey; // reference to the key contained by this record
119 //extern NSString* const SecCKRecordWrappedKeyKey; // key material
120
121 /* Current Key CKRecord Keys */
122 extern NSString* const SecCKRecordCurrentKeyType;
123 // The key class will be the record name.
124 //extern NSString* const SecCKRecordParentKeyRefKey; <-- represent the current key for this key class
125
126 /* Current Item CKRecord Keys */
127 extern NSString* const SecCKRecordCurrentItemType;
128 extern NSString* const SecCKRecordItemRefKey;
129
130
131 /* Device State CKRecord Keys */
132 extern NSString* const SecCKRecordDeviceStateType;
133 extern NSString* const SecCKRecordCirclePeerID;
134 extern NSString* const SecCKRecordCircleStatus;
135 extern NSString* const SecCKRecordKeyState;
136 extern NSString* const SecCKRecordCurrentTLK;
137 extern NSString* const SecCKRecordCurrentClassA;
138 extern NSString* const SecCKRecordCurrentClassC;
139 extern NSString* const SecCKSRecordLastUnlockTime;
140 extern NSString* const SecCKSRecordOSVersionKey; // Similar to SecCKRecordHostOSVersionKey, but better named
141
142 /* Manifest master CKRecord Keys */
143 extern NSString* const SecCKRecordManifestType;
144 extern NSString* const SecCKRecordManifestDigestValueKey;
145 extern NSString* const SecCKRecordManifestGenerationCountKey;
146 extern NSString* const SecCKRecordManifestLeafRecordIDsKey;
147 extern NSString* const SecCKRecordManifestPeerManifestRecordIDsKey;
148 extern NSString* const SecCKRecordManifestCurrentItemsKey;
149 extern NSString* const SecCKRecordManifestSignaturesKey;
150 extern NSString* const SecCKRecordManifestSignerIDKey;
151 extern NSString* const SecCKRecordManifestSchemaKey;
152
153 /* Manifest leaf CKRecord Keys */
154 extern NSString* const SecCKRecordManifestLeafType;
155 extern NSString* const SecCKRecordManifestLeafDERKey;
156 extern NSString* const SecCKRecordManifestLeafDigestKey;
157
158 /* Zone Key Hierarchy States */
159 @protocol SecCKKSZoneKeyState <NSObject>
160 @end
161 typedef NSString<SecCKKSZoneKeyState> CKKSZoneKeyState;
162
163 // CKKS is currently logged out
164 extern CKKSZoneKeyState* const SecCKKSZoneKeyStateLoggedOut;
165
166 // Class has just been created.
167 extern CKKSZoneKeyState* const SecCKKSZoneKeyStateInitializing;
168 // CKKSZone has just informed us that its setup is done (and completed successfully).
169 extern CKKSZoneKeyState* const SecCKKSZoneKeyStateInitialized;
170 // CKKSZone has informed us that zone setup did not work. Try again soon!
171 extern CKKSZoneKeyState* const SecCKKSZoneKeyStateZoneCreationFailed;
172 // Everything is ready and waiting for input.
173 extern CKKSZoneKeyState* const SecCKKSZoneKeyStateReady;
174 // We're presumably ready, but we'd like to do one or two more checks after we unlock.
175 extern CKKSZoneKeyState* const SecCKKSZoneKeyStateReadyPendingUnlock;
176
177 // We're currently refetching the zone
178 extern CKKSZoneKeyState* const SecCKKSZoneKeyStateFetch;
179 // A Fetch has just been completed which includes some new keys to process
180 extern CKKSZoneKeyState* const SecCKKSZoneKeyStateFetchComplete;
181 // We'd really like a full refetch.
182 extern CKKSZoneKeyState* const SecCKKSZoneKeyStateNeedFullRefetch;
183 // We've received a wrapped TLK, but we don't have its contents yet. Wait until they arrive.
184 extern CKKSZoneKeyState* const SecCKKSZoneKeyStateWaitForTLK;
185 // We've received a wrapped TLK, but we can't process it until the keybag unlocks. Wait until then.
186 extern CKKSZoneKeyState* const SecCKKSZoneKeyStateWaitForUnlock;
187 // Things are unhealthy, but we're not sure entirely why.
188 extern CKKSZoneKeyState* const SecCKKSZoneKeyStateUnhealthy;
189 // Something has gone horribly wrong with the current key pointers.
190 extern CKKSZoneKeyState* const SecCKKSZoneKeyStateBadCurrentPointers;
191 // Something has gone wrong creating new TLKs.
192 extern CKKSZoneKeyState* const SecCKKSZoneKeyStateNewTLKsFailed;
193 // Something isn't quite right with the TLK shares.
194 extern CKKSZoneKeyState* const SecCKKSZoneKeyStateHealTLKShares;
195 // Something has gone wrong fixing TLK shares.
196 extern CKKSZoneKeyState* const SecCKKSZoneKeyStateHealTLKSharesFailed;
197 // The key hierarchy state machine needs to wait for the fixup operation to complete
198 extern CKKSZoneKeyState* const SecCKKSZoneKeyStateWaitForFixupOperation;
199 // The key hierarchy state machine is responding to a key state reprocess request
200 extern CKKSZoneKeyState* const SecCKKSZoneKeyStateProcess;
201
202 // CKKS is resetting the remote zone, due to key hierarchy reasons. Will not proceed until the local reset occurs.
203 extern CKKSZoneKeyState* const SecCKKSZoneKeyStateResettingZone;
204 // CKKS is resetting the local data, likely to do a cloudkit reset or a rpc.
205 extern CKKSZoneKeyState* const SecCKKSZoneKeyStateResettingLocalData;
206
207 // Fatal error. Will not proceed unless fixed from outside class.
208 extern CKKSZoneKeyState* const SecCKKSZoneKeyStateError;
209 // This CKKS instance has been cancelled.
210 extern CKKSZoneKeyState* const SecCKKSZoneKeyStateCancelled;
211
212 // If you absolutely need to numberify one of the above constants, here's your maps.
213 NSDictionary<CKKSZoneKeyState*, NSNumber*>* CKKSZoneKeyStateMap(void);
214 NSDictionary<NSNumber*, CKKSZoneKeyState*>* CKKSZoneKeyStateInverseMap(void);
215 NSNumber* CKKSZoneKeyToNumber(CKKSZoneKeyState* state);
216 CKKSZoneKeyState* CKKSZoneKeyRecover(NSNumber* stateNumber);
217
218 // Use this to determine if CKKS believes the current state is "transient": that is, should resolve itself with further local processing
219 // or 'nontransient': further local processing won't progress. Either we're ready, or waiting for the user to unlock, or a remote device to do something.
220 bool CKKSKeyStateTransient(CKKSZoneKeyState* state);
221
222 /* Hide Item Length */
223 extern const NSUInteger SecCKKSItemPaddingBlockSize;
224
225 /* Aggd Keys */
226 extern NSString* const SecCKKSAggdPropagationDelay;
227 extern NSString* const SecCKKSAggdPrimaryKeyConflict;
228 extern NSString* const SecCKKSAggdViewKeyCount;
229 extern NSString* const SecCKKSAggdItemReencryption;
230
231 extern NSString* const SecCKKSUserDefaultsSuite;
232
233 extern NSString* const CKKSErrorDomain;
234 extern NSString* const CKKSServerExtensionErrorDomain;
235
236 /* Queue limits: these should likely be configurable via plist */
237 #define SecCKKSOutgoingQueueItemsAtOnce 100
238 #define SecCKKSIncomingQueueItemsAtOnce 50
239
240 // Utility functions
241 NSString* SecCKKSHostOSVersion(void);
242
243 #endif // OBJ-C
244
245 /* C functions to interact with CKKS */
246 void SecCKKSInitialize(SecDbRef db);
247 void SecCKKSNotifyBlock(SecDbConnectionRef dbconn, SecDbTransactionPhase phase, SecDbTransactionSource source, CFArrayRef changes);
248
249 // Called by XPC approximately every 3 days
250 void SecCKKS24hrNotification(void);
251
252 // Register this callback to receive a call when the item with this UUID next successfully (or unsuccessfully) exits the outgoing queue.
253 void CKKSRegisterSyncStatusCallback(CFStringRef cfuuid, SecBoolCFErrorCallback callback);
254
255 // Tells CKKS that the local keychain was reset, and that it should respond accordingly
256 void SecCKKSPerformLocalResync(void);
257
258 // Returns true if CloudKit keychain syncing should occur
259 bool SecCKKSIsEnabled(void);
260
261 bool SecCKKSEnable(void);
262 bool SecCKKSDisable(void);
263
264 bool SecCKKSResetSyncing(void);
265
266 bool SecCKKSSyncManifests(void);
267 bool SecCKKSEnableSyncManifests(void);
268 bool SecCKKSSetSyncManifests(bool value);
269
270 bool SecCKKSEnforceManifests(void);
271 bool SecCKKSEnableEnforceManifests(void);
272 bool SecCKKSSetEnforceManifests(bool value);
273
274 bool SecCKKSReduceRateLimiting(void);
275 bool SecCKKSSetReduceRateLimiting(bool value);
276
277 // Testing support
278 bool SecCKKSTestsEnabled(void);
279 bool SecCKKSTestsEnable(void);
280 bool SecCKKSTestsDisable(void);
281
282 void SecCKKSTestResetFlags(void);
283 bool SecCKKSTestDisableAutomaticUUID(void);
284 void SecCKKSTestSetDisableAutomaticUUID(bool set);
285
286 bool SecCKKSTestDisableSOS(void);
287 void SecCKKSTestSetDisableSOS(bool set);
288
289 bool SecCKKSTestDisableKeyNotifications(void);
290 void SecCKKSTestSetDisableKeyNotifications(bool set);
291
292 // TODO: handle errors better
293 typedef CF_ENUM(CFIndex, CKKSErrorCode) {
294 CKKSNotInitialized = 9,
295 CKKSNotLoggedIn = 10,
296 CKKSNoSuchView = 11,
297
298 CKKSRemoteItemChangePending = 12,
299 CKKSLocalItemChangePending = 13,
300 CKKSItemChanged = 14,
301 CKKSNoUUIDOnItem = 15,
302 CKKSItemCreationFailure = 16,
303 CKKSInvalidKeyClass = 17,
304 CKKSKeyNotSelfWrapped = 18,
305 CKKSNoTrustedPeer = 19,
306 CKKSDataMismatch = 20,
307 CKKSProtobufFailure = 21,
308 CKKSNoSuchRecord = 22,
309 CKKSMissingTLKShare = 23,
310 CKKSNoPeersAvailable = 24,
311
312 CKKSSplitKeyHierarchy = 32,
313 CKKSOrphanedKey = 33,
314 CKKSInvalidTLK = 34,
315 CKKSNoTrustedTLKShares = 35,
316 CKKSKeyUnknownFormat = 36,
317 CKKSNoSigningKey = 37,
318 CKKSNoEncryptionKey = 38,
319
320 CKKSNotHSA2 = 40,
321 CKKSiCloudGreyMode = 41,
322
323 CKKSNoFetchesRequested = 50,
324 };
325
326 typedef CF_ENUM(CFIndex, CKKSResultDescriptionErrorCode) {
327 CKKSResultDescriptionNone = 0,
328 CKKSResultDescriptionPendingKeyReady = 1,
329 CKKSResultDescriptionPendingSuccessfulFetch = 2,
330 CKKSResultDescriptionPendingAccountLoggedIn = 3,
331 CKKSResultDescriptionPendingUnlock = 4,
332 CKKSResultDescriptionPendingBottledPeerModifyRecords = 5,
333 CKKSResultDescriptionPendingBottledPeerFetchRecords = 6,
334
335 CKKSResultDescriptionPendingZoneChangeFetchScheduling = 1000,
336 CKKSResultDescriptionPendingViewChangedScheduling = 1001,
337 CKKSResultDescriptionPendingZoneInitializeScheduling = 1002,
338 CKKSResultDescriptionPendingOutgoingQueueScheduling = 1003,
339 CKKSResultDescriptionPendingKeyHierachyPokeScheduling = 1004,
340 };
341
342 // These errors are returned by the CKKS server extension.
343 // Commented out codes here indicate that we don't currently handle them on the client side.
344 typedef CF_ENUM(CFIndex, CKKSServerExtensionErrorCode) {
345 // Generic Errors
346 //CKKSServerMissingField = 1,
347 //CKKSServerMissingRecord = 2,
348 //CKKSServerUnexpectedFieldType = 3,
349 //CKKSServerUnexpectedRecordType = 4,
350 //CKKSServerUnepxectedRecordID = 5,
351
352 // Chain errors:
353 //CKKSServerMissingCurrentKeyPointer = 6,
354 //CKKSServerMissingCurrentKey = 7,
355 //CKKSServerUnexpectedSyncKeyClassInChain = 8,
356 CKKSServerUnexpectedSyncKeyInChain = 9,
357
358 // Item/Currentitem record errors:
359 //CKKSServerKeyrollingNotAllowed = 10,
360 //CKKSServerInvalidPublicIdentity = 11,
361 //CKKSServerPublicKeyMismatch = 12,
362 //CKKSServerServiceNumberMismatch = 13,
363 //CKKSServerUnknownServiceNumber = 14,
364 //CKKSServerEncverLessThanMinVal = 15,
365 //CKKSServerCannotModifyWasCurrent = 16,
366 //CKKSServerInvalidCurrentItem = 17,
367 };
368
369 #define SecTranslateError(nserrorptr, cferror) \
370 if(nserrorptr) { \
371 *nserrorptr = (__bridge_transfer NSError*)cferror; \
372 } else { \
373 CFReleaseNull(cferror); \
374 }
375
376 // Very similar to the secerror, secnotice, and secinfo macros in debugging.h, but add zoneNames
377 #define ckkserrorwithzonename(scope, zoneName, format, ...) \
378 { \
379 os_log(secLogObjForScope("SecError"), scope "-%@: " format, (zoneName ? zoneName : @"unknown"), ##__VA_ARGS__); \
380 }
381 #define ckksnoticewithzonename(scope, zoneName, format, ...) \
382 { \
383 os_log(secLogObjForCFScope((__bridge CFStringRef)[@(scope "-") stringByAppendingString:(zoneName ? zoneName : @"unknown")]), \
384 format, \
385 ##__VA_ARGS__); \
386 }
387 #define ckksinfowithzonename(scope, zoneName, format, ...) \
388 { \
389 os_log_debug(secLogObjForCFScope((__bridge CFStringRef)[@(scope "-") stringByAppendingString:(zoneName ? zoneName : @"unknown")]), \
390 format, \
391 ##__VA_ARGS__); \
392 }
393
394 #define ckkserror(scope, zoneNameHaver, format, ...) \
395 { \
396 NSString* znh = zoneNameHaver.zoneName; \
397 ckkserrorwithzonename(scope, znh, format, ##__VA_ARGS__) \
398 }
399 #define ckksnotice(scope, zoneNameHaver, format, ...) \
400 { \
401 NSString* znh = zoneNameHaver.zoneName; \
402 ckksnoticewithzonename(scope, znh, format, ##__VA_ARGS__) \
403 }
404 #define ckksinfo(scope, zoneNameHaver, format, ...) \
405 { \
406 NSString* znh = zoneNameHaver.zoneName; \
407 ckksinfowithzonename(scope, znh, format, ##__VA_ARGS__) \
408 }
409
410 #undef ckksdebug
411 #if !defined(NDEBUG)
412 #define ckksdebugwithzonename(scope, zoneName, format, ...) \
413 { \
414 os_log_debug(secLogObjForCFScope((__bridge CFStringRef)[@(scope "-") stringByAppendingString:(zoneName ? zoneName : @"unknown")]), \
415 format, \
416 ##__VA_ARGS__); \
417 }
418 #define ckksdebug(scope, zoneNameHaver, format, ...) \
419 { \
420 NSString* znh = zoneNameHaver.zoneName; \
421 ckksdebugwithzonename(scope, znh, format, ##__VA_ARGS__) \
422 }
423 #else
424 #define ckksdebug(scope, ...) /* nothing */
425 #endif
426
427 #ifdef __OBJC__
428 NS_ASSUME_NONNULL_END
429 #else
430 CF_ASSUME_NONNULL_END
431 #endif
432
433 #endif /* CKKS_h */
434