2 * Copyright (c) 2016 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
27 #include <dispatch/dispatch.h>
28 #include "ipc/securityd_client.h"
29 #include "utilities/SecCFWrappers.h"
30 #include "utilities/SecDb.h"
34 #import <Foundation/Foundation.h>
35 #import "keychain/ot/OctagonStateMachine.h"
38 CF_ASSUME_NONNULL_BEGIN
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
48 extern const SecCKKSItemEncryptionVersion currentCKKSItemEncryptionVersion
;
51 extern NSString
* const SecCKKSActionAdd
;
52 extern NSString
* const SecCKKSActionDelete
;
53 extern NSString
* const SecCKKSActionModify
;
56 @protocol SecCKKSItemState
<NSObject
>
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 SecCKKSStateDeleted
; // meta-state: please delete this item!
65 extern CKKSItemState
* const SecCKKSStateMismatchedView
; // This item was for a different view at processing time. Held pending a policy refresh.
67 /* Processed States */
68 @protocol SecCKKSProcessedState
<NSObject
>
70 typedef NSString
<SecCKKSProcessedState
> CKKSProcessedState
;
71 extern CKKSProcessedState
* const SecCKKSProcessedStateLocal
;
72 extern CKKSProcessedState
* const SecCKKSProcessedStateRemote
;
75 @protocol SecCKKSKeyClass
<NSObject
>
77 typedef NSString
<SecCKKSKeyClass
> CKKSKeyClass
;
78 extern CKKSKeyClass
* const SecCKKSKeyClassTLK
;
79 extern CKKSKeyClass
* const SecCKKSKeyClassA
;
80 extern CKKSKeyClass
* const SecCKKSKeyClassC
;
82 /* Useful CloudKit configuration */
83 extern NSString
* SecCKKSContainerName
;
84 extern bool SecCKKSContainerUsePCS
;
85 extern NSString
* const SecCKKSSubscriptionID
;
86 extern NSString
* const SecCKKSAPSNamedPort
;
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
;
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;
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
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
126 /* Current Item CKRecord Keys */
127 extern NSString
* const SecCKRecordCurrentItemType
;
128 extern NSString
* const SecCKRecordItemRefKey
;
131 /* Device State CKRecord Keys */
132 extern NSString
* const SecCKRecordDeviceStateType
;
133 extern NSString
* const SecCKRecordCirclePeerID
;
134 extern NSString
* const SecCKRecordOctagonPeerID
;
135 extern NSString
* const SecCKRecordOctagonStatus
;
136 extern NSString
* const SecCKRecordCircleStatus
;
137 extern NSString
* const SecCKRecordKeyState
;
138 extern NSString
* const SecCKRecordCurrentTLK
;
139 extern NSString
* const SecCKRecordCurrentClassA
;
140 extern NSString
* const SecCKRecordCurrentClassC
;
141 extern NSString
* const SecCKSRecordLastUnlockTime
;
142 extern NSString
* const SecCKSRecordOSVersionKey
; // Similar to SecCKRecordHostOSVersionKey, but better named
144 /* Manifest master CKRecord Keys */
145 extern NSString
* const SecCKRecordManifestType
;
146 extern NSString
* const SecCKRecordManifestDigestValueKey
;
147 extern NSString
* const SecCKRecordManifestGenerationCountKey
;
148 extern NSString
* const SecCKRecordManifestLeafRecordIDsKey
;
149 extern NSString
* const SecCKRecordManifestPeerManifestRecordIDsKey
;
150 extern NSString
* const SecCKRecordManifestCurrentItemsKey
;
151 extern NSString
* const SecCKRecordManifestSignaturesKey
;
152 extern NSString
* const SecCKRecordManifestSignerIDKey
;
153 extern NSString
* const SecCKRecordManifestSchemaKey
;
155 /* Manifest leaf CKRecord Keys */
156 extern NSString
* const SecCKRecordManifestLeafType
;
157 extern NSString
* const SecCKRecordManifestLeafDERKey
;
158 extern NSString
* const SecCKRecordManifestLeafDigestKey
;
160 /* Zone Key Hierarchy States */
162 typedef OctagonState CKKSZoneKeyState
;
164 // This is here to allow for building with Octagon off
165 @protocol SecCKKSZoneKeyState
<NSObject
>
167 typedef NSString
<SecCKKSZoneKeyState
> CKKSZoneKeyState
;
170 extern CKKSZoneKeyState
* const SecCKKSZoneKeyStateWaitForCloudKitAccountStatus
;
172 // CKKS is currently logged out
173 extern CKKSZoneKeyState
* const SecCKKSZoneKeyStateLoggedOut
;
175 // Class has just been created.
176 extern CKKSZoneKeyState
* const SecCKKSZoneKeyStateInitializing
;
177 // CKKSZone has just informed us that its setup is done (and completed successfully).
178 extern CKKSZoneKeyState
* const SecCKKSZoneKeyStateInitialized
;
179 // CKKSZone has informed us that zone setup did not work. Try again soon!
180 extern CKKSZoneKeyState
* const SecCKKSZoneKeyStateZoneCreationFailed
;
182 // Everything is likely ready. Double-check.
183 extern CKKSZoneKeyState
* const SecCKKSZoneKeyStateBecomeReady
;
184 // Everything is ready and waiting for input.
185 extern CKKSZoneKeyState
* const SecCKKSZoneKeyStateReady
;
187 // We're presumably ready, but we'd like to do one or two more checks after we unlock.
188 extern CKKSZoneKeyState
* const SecCKKSZoneKeyStateReadyPendingUnlock
;
190 // A key hierarchy fetch will now begin
191 extern CKKSZoneKeyState
* const SecCKKSZoneKeyStateBeginFetch
;
193 // We're currently refetching the zone
194 extern CKKSZoneKeyState
* const SecCKKSZoneKeyStateFetch
;
195 // A Fetch has just been completed which includes some new keys to process
196 extern CKKSZoneKeyState
* const SecCKKSZoneKeyStateFetchComplete
;
197 // We'd really like a full refetch.
198 extern CKKSZoneKeyState
* const SecCKKSZoneKeyStateNeedFullRefetch
;
200 // The TLK doesn't appear to be present. Determine what to to next!
201 extern CKKSZoneKeyState
* const SecCKKSZoneKeyStateTLKMissing
;
203 // We've received a wrapped TLK, but we don't have its contents yet. Wait until they arrive.
204 extern CKKSZoneKeyState
* const SecCKKSZoneKeyStateWaitForTLK
;
206 // No keys exist for this zone yet, and we're waiting to make some. Please call the "make TLKs" API.
207 extern CKKSZoneKeyState
* const SecCKKSZoneKeyStateWaitForTLKCreation
;
208 // No keys exist for this zone yet, but we've made some. Octagon should upload them.
209 extern CKKSZoneKeyState
* const SecCKKSZoneKeyStateWaitForTLKUpload
;
211 // We've received a wrapped TLK, but we can't process it until the keybag unlocks. Wait until then.
212 extern CKKSZoneKeyState
* const SecCKKSZoneKeyStateWaitForUnlock
;
213 // Some operation has noticed that trust is lost. Will enter WaitForTrust.
214 extern CKKSZoneKeyState
* const SecCKKSZoneKeyStateLoseTrust
;
215 // We've done some CK ops, but are waiting for the trust system to tell us to continue
216 extern CKKSZoneKeyState
* const SecCKKSZoneKeyStateWaitForTrust
;
218 // Things are unhealthy, but we're not sure entirely why.
219 extern CKKSZoneKeyState
* const SecCKKSZoneKeyStateUnhealthy
;
220 // Something has gone horribly wrong with the current key pointers.
221 extern CKKSZoneKeyState
* const SecCKKSZoneKeyStateBadCurrentPointers
;
222 // Something has gone wrong creating new TLKs.
223 extern CKKSZoneKeyState
* const SecCKKSZoneKeyStateNewTLKsFailed
;
224 // Something isn't quite right with the TLK shares.
225 extern CKKSZoneKeyState
* const SecCKKSZoneKeyStateHealTLKShares
;
226 // Something has gone wrong fixing TLK shares.
227 extern CKKSZoneKeyState
* const SecCKKSZoneKeyStateHealTLKSharesFailed
;
228 // The key hierarchy state machine needs to wait for the fixup operation to complete
229 extern CKKSZoneKeyState
* const SecCKKSZoneKeyStateWaitForFixupOperation
;
230 // The key hierarchy state machine is responding to a key state reprocess request
231 extern CKKSZoneKeyState
* const SecCKKSZoneKeyStateProcess
;
233 // CKKS is resetting the remote zone, due to key hierarchy reasons. Will not proceed until the local reset occurs.
234 extern CKKSZoneKeyState
* const SecCKKSZoneKeyStateResettingZone
;
235 // CKKS is resetting the local data, likely to do a cloudkit reset or a rpc.
236 extern CKKSZoneKeyState
* const SecCKKSZoneKeyStateResettingLocalData
;
238 // Fatal error. Will not proceed unless fixed from outside class.
239 extern CKKSZoneKeyState
* const SecCKKSZoneKeyStateError
;
241 // If you absolutely need to numberify one of the above constants, here's your maps.
242 NSDictionary
<CKKSZoneKeyState
*, NSNumber
*>* CKKSZoneKeyStateMap(void);
243 NSDictionary
<NSNumber
*, CKKSZoneKeyState
*>* CKKSZoneKeyStateInverseMap(void);
244 NSNumber
* CKKSZoneKeyToNumber(CKKSZoneKeyState
* state
);
245 CKKSZoneKeyState
* CKKSZoneKeyRecover(NSNumber
* stateNumber
);
247 // Use this to determine if CKKS believes the current state is "transient": that is, should resolve itself with further local processing
248 // 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.
249 NSSet
<CKKSZoneKeyState
*>* CKKSKeyStateNonTransientStates(void);
251 /* Hide Item Length */
252 extern const NSUInteger SecCKKSItemPaddingBlockSize
;
255 extern NSString
* const SecCKKSAggdPropagationDelay
;
256 extern NSString
* const SecCKKSAggdPrimaryKeyConflict
;
257 extern NSString
* const SecCKKSAggdViewKeyCount
;
258 extern NSString
* const SecCKKSAggdItemReencryption
;
260 extern NSString
* const SecCKKSUserDefaultsSuite
;
262 extern NSString
* const CKKSErrorDomain
;
263 extern NSString
* const CKKSServerExtensionErrorDomain
;
265 /* Queue limits: these should likely be configurable via plist */
266 #define SecCKKSOutgoingQueueItemsAtOnce 100
267 #define SecCKKSIncomingQueueItemsAtOnce 50
270 NSString
* SecCKKSHostOSVersion(void);
274 /* C functions to interact with CKKS */
275 void SecCKKSInitialize(SecDbRef db
);
276 void SecCKKSNotifyBlock(SecDbConnectionRef dbconn
, SecDbTransactionPhase phase
, SecDbTransactionSource source
, CFArrayRef changes
);
278 // Called by XPC approximately every 3 days
279 void SecCKKS24hrNotification(void);
281 // Register this callback to receive a call when the item with this UUID next successfully (or unsuccessfully) exits the outgoing queue.
282 void CKKSRegisterSyncStatusCallback(CFStringRef cfuuid
, SecBoolCFErrorCallback callback
);
284 // Tells CKKS that the local keychain was reset, and that it should respond accordingly
285 void SecCKKSPerformLocalResync(void);
287 // Returns true if CloudKit keychain syncing should occur
288 bool SecCKKSIsEnabled(void);
290 bool SecCKKSEnable(void);
291 bool SecCKKSDisable(void);
293 bool SecCKKSResetSyncing(void);
295 bool SecCKKSSyncManifests(void);
296 bool SecCKKSEnableSyncManifests(void);
297 bool SecCKKSSetSyncManifests(bool value
);
299 bool SecCKKSEnforceManifests(void);
300 bool SecCKKSEnableEnforceManifests(void);
301 bool SecCKKSSetEnforceManifests(bool value
);
303 bool SecCKKSReduceRateLimiting(void);
304 bool SecCKKSSetReduceRateLimiting(bool value
);
307 bool SecCKKSTestsEnabled(void);
308 bool SecCKKSTestsEnable(void);
309 bool SecCKKSTestsDisable(void);
311 void SecCKKSTestResetFlags(void);
312 bool SecCKKSTestDisableAutomaticUUID(void);
313 void SecCKKSTestSetDisableAutomaticUUID(bool set
);
315 bool SecCKKSTestDisableSOS(void);
316 void SecCKKSTestSetDisableSOS(bool set
);
318 bool SecCKKSTestDisableKeyNotifications(void);
319 void SecCKKSTestSetDisableKeyNotifications(bool set
);
321 bool SecCKKSTestSkipScan(void);
322 bool SecCKKSSetTestSkipScan(bool value
);
324 // TODO: handle errors better
325 typedef CF_ENUM(CFIndex
, CKKSErrorCode
) {
326 CKKSNotInitialized
= 9,
327 CKKSNotLoggedIn
= 10,
330 CKKSRemoteItemChangePending
= 12,
331 CKKSLocalItemChangePending
= 13,
332 CKKSItemChanged
= 14,
333 CKKSNoUUIDOnItem
= 15,
334 CKKSItemCreationFailure
= 16,
335 CKKSInvalidKeyClass
= 17,
336 CKKSKeyNotSelfWrapped
= 18,
337 CKKSNoTrustedPeer
= 19,
338 CKKSDataMismatch
= 20,
339 CKKSProtobufFailure
= 21,
340 CKKSNoSuchRecord
= 22,
341 CKKSMissingTLKShare
= 23,
342 CKKSNoPeersAvailable
= 24,
344 CKKSSplitKeyHierarchy
= 32,
345 CKKSOrphanedKey
= 33,
347 CKKSNoTrustedTLKShares
= 35,
348 CKKSKeyUnknownFormat
= 36,
349 CKKSNoSigningKey
= 37,
350 CKKSNoEncryptionKey
= 38,
353 CKKSiCloudGreyMode
= 41,
355 CKKSNoFetchesRequested
= 50,
359 CKKSLackingTrust
= 52,
360 CKKSKeysMissing
= 53,
362 CKKSCircularKeyReference
= 54,
364 CKKSErrorViewIsPaused
= 55,
365 CKKSErrorPolicyNotLoaded
= 56,
367 CKKSErrorUnexpectedNil
= 57,
370 typedef CF_ENUM(CFIndex
, CKKSResultDescriptionErrorCode
) {
371 CKKSResultDescriptionNone
= 0,
372 CKKSResultDescriptionPendingKeyReady
= 1,
373 CKKSResultDescriptionPendingSuccessfulFetch
= 2,
374 CKKSResultDescriptionPendingAccountLoggedIn
= 3,
375 CKKSResultDescriptionPendingUnlock
= 4,
376 CKKSResultDescriptionPendingBottledPeerModifyRecords
= 5,
377 CKKSResultDescriptionPendingBottledPeerFetchRecords
= 6,
379 CKKSResultDescriptionPendingZoneChangeFetchScheduling
= 1000,
380 CKKSResultDescriptionPendingViewChangedScheduling
= 1001,
381 CKKSResultDescriptionPendingZoneInitializeScheduling
= 1002, // No longer used
382 CKKSResultDescriptionPendingOutgoingQueueScheduling
= 1003,
383 CKKSResultDescriptionPendingKeyHierachyPokeScheduling
= 1004,
384 CKKSResultDescriptionPendingCloudKitRetryAfter
= 1005,
385 CKKSResultDescriptionPendingFlag
= 1006,
388 // These errors are returned by the CKKS server extension.
389 // Commented out codes here indicate that we don't currently handle them on the client side.
390 typedef CF_ENUM(CFIndex
, CKKSServerExtensionErrorCode
) {
392 //CKKSServerMissingField = 1,
393 CKKSServerMissingRecord
= 2,
394 //CKKSServerUnexpectedFieldType = 3,
395 //CKKSServerUnexpectedRecordType = 4,
396 //CKKSServerUnepxectedRecordID = 5,
399 //CKKSServerMissingCurrentKeyPointer = 6,
400 //CKKSServerMissingCurrentKey = 7,
401 //CKKSServerUnexpectedSyncKeyClassInChain = 8,
402 CKKSServerUnexpectedSyncKeyInChain
= 9,
404 // Item/Currentitem record errors:
405 //CKKSServerKeyrollingNotAllowed = 10,
406 //CKKSServerInvalidPublicIdentity = 11,
407 //CKKSServerPublicKeyMismatch = 12,
408 //CKKSServerServiceNumberMismatch = 13,
409 //CKKSServerUnknownServiceNumber = 14,
410 //CKKSServerEncverLessThanMinVal = 15,
411 //CKKSServerCannotModifyWasCurrent = 16,
412 //CKKSServerInvalidCurrentItem = 17,
417 #define SecTranslateError(nserrorptr, cferror) \
419 *nserrorptr = (__bridge_transfer NSError*)cferror; \
421 CFReleaseNull(cferror); \
424 extern os_log_t
CKKSLogObject(NSString
* scope
, NSString
* _Nullable zoneName
);
426 // Very similar to the secerror, secnotice, and secinfo macros in debugging.h, but add zoneNames
427 #define ckkserrorwithzonename(scope, zoneName, format, ...) \
429 os_log_with_type(CKKSLogObject(@scope, zoneName), \
435 #define ckkserror(scope, zoneNameBearer, format, ...) \
436 ckkserrorwithzonename(scope, zoneNameBearer.zoneName, format, ##__VA_ARGS__)
438 #define ckkserror_global(scope, format, ...) \
439 ckkserrorwithzonename(scope, nil, format, ##__VA_ARGS__)
441 #define ckksnotice(scope, zoneNameBearer, format, ...) \
442 os_log(CKKSLogObject(@scope, zoneNameBearer.zoneName), format, ##__VA_ARGS__)
444 #define ckksnotice_global(scope, format, ...) \
445 os_log(CKKSLogObject(@scope, nil), format, ##__VA_ARGS__)
447 #define ckksinfo(scope, zoneNameBearer, format, ...) \
448 os_log_debug(CKKSLogObject(@scope, zoneNameBearer.zoneName), format, ##__VA_ARGS__)
450 #define ckksinfo_global(scope, format, ...) \
451 os_log_debug(CKKSLogObject(@scope, nil), format, ##__VA_ARGS__)
455 CF_ASSUME_NONNULL_END