CKKSKeychainBackedKey.h
1 /* 2 * Copyright (c) 2018 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 #if OCTAGON 25 26 #import <Foundation/Foundation.h> 27 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" 32 33 NS_ASSUME_NONNULL_BEGIN 34 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. 40 41 @interface CKKSKeychainBackedKey : NSObject <NSCopying, NSSecureCoding> 42 @property NSString* uuid; 43 @property NSString* parentKeyUUID; 44 @property CKKSKeyClass* keyclass; 45 @property CKRecordZoneID* zoneID; 46 47 // Actual key material 48 @property CKKSWrappedAESSIVKey* wrappedkey; 49 @property (nullable) CKKSAESSIVKey* aessivkey; 50 51 - (instancetype)init NS_UNAVAILABLE; 52 - (instancetype _Nullable)initSelfWrappedWithAESKey:(CKKSAESSIVKey*)aeskey 53 uuid:(NSString*)uuid 54 keyclass:(CKKSKeyClass*)keyclass 55 zoneID:(CKRecordZoneID*)zoneID; 56 57 - (instancetype _Nullable)initWrappedBy:(CKKSKeychainBackedKey*)wrappingKey 58 AESKey:(CKKSAESSIVKey*)aessivkey 59 uuid:(NSString*)uuid 60 keyclass:(CKKSKeyClass*)keyclass 61 zoneID:(CKRecordZoneID*)zoneID; 62 63 - (instancetype)initWithWrappedAESKey:(CKKSWrappedAESSIVKey* _Nullable)wrappedaeskey 64 uuid:(NSString*)uuid 65 parentKeyUUID:(NSString*)parentKeyUUID 66 keyclass:(CKKSKeyClass*)keyclass 67 zoneID:(CKRecordZoneID*)zoneID; 68 69 // Creates new random keys, in the parent's zone 70 + (instancetype _Nullable)randomKeyWrappedByParent:(CKKSKeychainBackedKey*)parentKey 71 error:(NSError* __autoreleasing*)error; 72 73 + (instancetype _Nullable)randomKeyWrappedByParent:(CKKSKeychainBackedKey*)parentKey 74 keyclass:(CKKSKeyClass*)keyclass 75 error:(NSError* __autoreleasing*)error; 76 77 // Creates a new random key that wraps itself 78 + (instancetype _Nullable)randomKeyWrappedBySelf:(CKRecordZoneID*)zoneID 79 error:(NSError* __autoreleasing*)error; 80 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 85 86 - (BOOL)loadKeyMaterialFromKeychain:(NSError* __autoreleasing*)error; 87 - (BOOL)deleteKeyMaterialFromKeychain:(NSError* __autoreleasing*)error; 88 89 // Class methods to help tests 90 + (NSDictionary* _Nullable)setKeyMaterialInKeychain:(NSDictionary*)query 91 error:(NSError* __autoreleasing*)error; 92 93 + (NSDictionary* _Nullable)queryKeyMaterialInKeychain:(NSDictionary*)query 94 error:(NSError* __autoreleasing*)error; 95 96 + (instancetype _Nullable)keyFromKeychain:(NSString*)uuid 97 parentKeyUUID:(NSString*)parentKeyUUID 98 keyclass:(CKKSKeyClass*)keyclass 99 zoneID:(CKRecordZoneID*)zoneID 100 error:(NSError* __autoreleasing*)error; 101 102 /* Returns true if we believe this key wraps itself. */ 103 - (bool)wrapsSelf; 104 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; 107 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; 112 113 - (CKKSWrappedAESSIVKey* _Nullable)wrapAESKey:(CKKSAESSIVKey*)keyToWrap 114 error:(NSError* __autoreleasing*)error; 115 116 - (CKKSAESSIVKey* _Nullable)unwrapAESKey:(CKKSWrappedAESSIVKey*)keyToUnwrap 117 error:(NSError* __autoreleasing*)error; 118 119 - (bool)wrapUnder:(CKKSKeychainBackedKey*)wrappingKey 120 error:(NSError* __autoreleasing*)error; 121 122 - (bool)unwrapSelfWithAESKey:(CKKSAESSIVKey*)unwrappingKey 123 error:(NSError* __autoreleasing*)error; 124 125 - (NSData* _Nullable)encryptData:(NSData*)plaintext 126 authenticatedData:(NSDictionary<NSString*, NSData*>* _Nullable)ad 127 error:(NSError* __autoreleasing*)error; 128 129 - (NSData* _Nullable)decryptData:(NSData*)ciphertext 130 authenticatedData:(NSDictionary<NSString*, NSData*>* _Nullable)ad 131 error:(NSError* __autoreleasing*)error; 132 133 - (NSData* _Nullable)serializeAsProtobuf:(NSError* __autoreleasing*)error; 134 135 + (CKKSKeychainBackedKey* _Nullable)loadFromProtobuf:(NSData*)data 136 error:(NSError* __autoreleasing*)error; 137 @end 138 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; 145 146 - (instancetype)initWithTLK:(CKKSKeychainBackedKey*)tlk 147 classA:(CKKSKeychainBackedKey*)classA 148 classC:(CKKSKeychainBackedKey*)classC 149 newUpload:(BOOL)newUpload; 150 @end 151 152 153 NS_ASSUME_NONNULL_END 154 155 #endif