2 * Copyright (c) 2018 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@
26 #import <Foundation/Foundation.h>
28 #import "keychain/ckks/CKKS.h"
29 #import "keychain/ckks/CKKSRecordHolder.h"
30 #import "keychain/ckks/CKKSSIV.h"
31 #import "keychain/ckks/proto/generated_source/CKKSSerializedKey.h"
33 NS_ASSUME_NONNULL_BEGIN
35 // Important note: while this class does conform to NSSecureCoding,
36 // for safety reasons encoding a CKKSKeychainBackedKey will ~not~
37 // encode the aessivkey. If you want your receiver to have access
38 // to the original key material, they must successfully call
39 // loadKeyMaterialFromKeychain.
41 @interface CKKSKeychainBackedKey
: NSObject
<NSCopying
, NSSecureCoding
>
42 @property NSString
* uuid
;
43 @property NSString
* parentKeyUUID
;
44 @property CKKSKeyClass
* keyclass
;
45 @property CKRecordZoneID
* zoneID
;
47 // Actual key material
48 @property CKKSWrappedAESSIVKey
* wrappedkey
;
49 @
property (nullable
) CKKSAESSIVKey
* aessivkey
;
51 - (instancetype
)init NS_UNAVAILABLE
;
52 - (instancetype _Nullable
)initSelfWrappedWithAESKey
:(CKKSAESSIVKey
*)aeskey
54 keyclass
:(CKKSKeyClass
*)keyclass
55 zoneID
:(CKRecordZoneID
*)zoneID
;
57 - (instancetype _Nullable
)initWrappedBy
:(CKKSKeychainBackedKey
*)wrappingKey
58 AESKey
:(CKKSAESSIVKey
*)aessivkey
60 keyclass
:(CKKSKeyClass
*)keyclass
61 zoneID
:(CKRecordZoneID
*)zoneID
;
63 - (instancetype
)initWithWrappedAESKey
:(CKKSWrappedAESSIVKey
* _Nullable
)wrappedaeskey
65 parentKeyUUID
:(NSString
*)parentKeyUUID
66 keyclass
:(CKKSKeyClass
*)keyclass
67 zoneID
:(CKRecordZoneID
*)zoneID
;
69 // Creates new random keys, in the parent's zone
70 + (instancetype _Nullable
)randomKeyWrappedByParent
:(CKKSKeychainBackedKey
*)parentKey
71 error
:(NSError
* __autoreleasing
*)error
;
73 + (instancetype _Nullable
)randomKeyWrappedByParent
:(CKKSKeychainBackedKey
*)parentKey
74 keyclass
:(CKKSKeyClass
*)keyclass
75 error
:(NSError
* __autoreleasing
*)error
;
77 // Creates a new random key that wraps itself
78 + (instancetype _Nullable
)randomKeyWrappedBySelf
:(CKRecordZoneID
*)zoneID
79 error
:(NSError
* __autoreleasing
*)error
;
81 /* Helper functions for persisting key material in the keychain */
82 - (BOOL
)saveKeyMaterialToKeychain
:(NSError
* __autoreleasing
*)error
;
83 - (BOOL
)saveKeyMaterialToKeychain
:(bool)stashTLK
84 error
:(NSError
* __autoreleasing
*)error
; // call this to not stash a non-syncable TLK, if that's what you want
86 - (BOOL
)loadKeyMaterialFromKeychain
:(NSError
* __autoreleasing
*)error
;
87 - (BOOL
)deleteKeyMaterialFromKeychain
:(NSError
* __autoreleasing
*)error
;
89 // Class methods to help tests
90 + (NSDictionary
* _Nullable
)setKeyMaterialInKeychain
:(NSDictionary
*)query
91 error
:(NSError
* __autoreleasing
*)error
;
93 + (NSDictionary
* _Nullable
)queryKeyMaterialInKeychain
:(NSDictionary
*)query
94 error
:(NSError
* __autoreleasing
*)error
;
96 + (instancetype _Nullable
)keyFromKeychain
:(NSString
*)uuid
97 parentKeyUUID
:(NSString
*)parentKeyUUID
98 keyclass
:(CKKSKeyClass
*)keyclass
99 zoneID
:(CKRecordZoneID
*)zoneID
100 error
:(NSError
* __autoreleasing
*)error
;
102 /* Returns true if we believe this key wraps itself. */
105 // Attempts checks if the AES key is already loaded, or attempts to load it from the keychain. Returns nil if it fails.
106 - (CKKSAESSIVKey
* _Nullable
)ensureKeyLoaded
:(NSError
* __autoreleasing
*)error
;
108 // On a self-wrapped key, determine if this AES-SIV key is the self-wrapped key.
109 // If it is, save the key as this CKKSKey's unwrapped key.
110 - (bool)trySelfWrappedKeyCandidate
:(CKKSAESSIVKey
*)candidate
111 error
:(NSError
* __autoreleasing
*)error
;
113 - (CKKSWrappedAESSIVKey
* _Nullable
)wrapAESKey
:(CKKSAESSIVKey
*)keyToWrap
114 error
:(NSError
* __autoreleasing
*)error
;
116 - (CKKSAESSIVKey
* _Nullable
)unwrapAESKey
:(CKKSWrappedAESSIVKey
*)keyToUnwrap
117 error
:(NSError
* __autoreleasing
*)error
;
119 - (bool)wrapUnder
:(CKKSKeychainBackedKey
*)wrappingKey
120 error
:(NSError
* __autoreleasing
*)error
;
122 - (bool)unwrapSelfWithAESKey
:(CKKSAESSIVKey
*)unwrappingKey
123 error
:(NSError
* __autoreleasing
*)error
;
125 - (NSData
* _Nullable
)encryptData
:(NSData
*)plaintext
126 authenticatedData
:(NSDictionary
<NSString
*, NSData
*>* _Nullable
)ad
127 error
:(NSError
* __autoreleasing
*)error
;
129 - (NSData
* _Nullable
)decryptData
:(NSData
*)ciphertext
130 authenticatedData
:(NSDictionary
<NSString
*, NSData
*>* _Nullable
)ad
131 error
:(NSError
* __autoreleasing
*)error
;
133 - (NSData
* _Nullable
)serializeAsProtobuf
:(NSError
* __autoreleasing
*)error
;
135 + (CKKSKeychainBackedKey
* _Nullable
)loadFromProtobuf
:(NSData
*)data
136 error
:(NSError
* __autoreleasing
*)error
;
139 // Useful when sending keys across interface boundaries
140 @interface CKKSKeychainBackedKeySet
: NSObject
<NSSecureCoding
>
141 @property CKKSKeychainBackedKey
* tlk
;
142 @property CKKSKeychainBackedKey
* classA
;
143 @property CKKSKeychainBackedKey
* classC
;
144 @property BOOL newUpload
;
146 - (instancetype
)initWithTLK
:(CKKSKeychainBackedKey
*)tlk
147 classA
:(CKKSKeychainBackedKey
*)classA
148 classC
:(CKKSKeychainBackedKey
*)classC
149 newUpload
:(BOOL
)newUpload
;
153 NS_ASSUME_NONNULL_END