]> git.saurik.com Git - apple/security.git/blob - keychain/ot/OTEscrowKeys.m
Security-58286.70.7.tar.gz
[apple/security.git] / keychain / ot / OTEscrowKeys.m
1 /*
2 * Copyright (c) 2017 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 #if OCTAGON
24
25 #import "OTEscrowKeys.h"
26
27 #import <Security/SecItemPriv.h>
28 #include <Security/SecKey.h>
29 #include <Security/SecKeyPriv.h>
30 #import <Foundation/Foundation.h>
31 #import <utilities/debugging.h>
32 #import <utilities/SecCFWrappers.h>
33
34 #import <SecurityFoundation/SFEncryptionOperation.h>
35 #import <SecurityFoundation/SFSigningOperation.h>
36 #import <SecurityFoundation/SFDigestOperation.h>
37 #import <SecurityFoundation/SFKey.h>
38 #import <SecurityFoundation/SFKey_Private.h>
39
40 #import "keychain/ot/OTDefines.h"
41
42 #import <corecrypto/cchkdf.h>
43 #import <corecrypto/ccsha2.h>
44 #import <corecrypto/ccec.h>
45
46 #import <CommonCrypto/CommonRandomSPI.h>
47 #import <Security/SecCFAllocator.h>
48 #import <Foundation/NSKeyedArchiver_Private.h>
49
50 static uint8_t escrowedSigningPrivKey[] = {'E', 's', 'c', 'r', 'o', 'w', ' ', 'S', 'i', 'g', 'n', 'i', 'n', 'g', ' ', 'P', 'r', 'i', 'v', 'a', 't', 'e', ' ', 'K', 'e', 'y'};
51 static uint8_t escrowedEncryptionPrivKey[] = { 'E', 's', 'c', 'r', 'o', 'w', ' ','E', 'n', 'c', 'r', 'y', 'p', 't', 'i', 'o', 'n', ' ', 'P', 'r', 'v', 'a', 't', 'e', ' ', 'K', 'e', 'y' };
52 static uint8_t escrowedSymmetric[] = {'E', 's', 'c', 'r', 'o', 'w', ' ', 'S', 'y', 'm', 'm', 'e', 't', 'r', 'i','c',' ', 'K', 'e', 'y' };
53
54 #define OT_ESCROW_SIGNING_HKDF_SIZE 56
55 #define OT_ESCROW_ENCRYPTION_HKDF_SIZE 56
56 #define OT_ESCROW_SYMMETRIC_HKDF_SIZE 32
57
58 @interface OTEscrowKeys ()
59 @property (nonatomic, strong) SFECKeyPair* encryptionKey;
60 @property (nonatomic, strong) SFECKeyPair* signingKey;
61 @property (nonatomic, strong) SFAESKey* symmetricKey;
62 @property (nonatomic, strong) NSData* secret;
63 @property (nonatomic, strong) NSString* dsid;
64 @end
65
66 @implementation OTEscrowKeys
67
68 - (nullable instancetype) initWithSecret:(NSData*)secret
69 dsid:(NSString*)dsid
70 error:(NSError* __autoreleasing *)error
71 {
72 self = [super init];
73 if (self) {
74 NSError* localError = nil;
75
76 if([secret length] == 0){
77 if(error){
78 *error = [NSError errorWithDomain:octagonErrorDomain code:OTErrorEmptySecret userInfo:@{NSLocalizedDescriptionKey: @"entropy/secret is nil"}];
79 }
80 return nil;
81 }
82 _secret = [secret copy];
83
84 if([dsid length] == 0){
85 if(error){
86 *error = [NSError errorWithDomain:octagonErrorDomain code:OTErrorEmptyDSID userInfo:@{NSLocalizedDescriptionKey: @"dsid is nil"}];
87 }
88 return nil;
89 }
90 _dsid = [dsid copy];
91
92 NSData *data = [OTEscrowKeys generateEscrowKey:kOTEscrowKeySigning masterSecret:secret dsid:self.dsid error:&localError];
93 if (!data) {
94 if(error){
95 *error = localError;
96 }
97 return nil;
98 }
99 _signingKey = [[SFECKeyPair alloc] initWithSecKey:[OTEscrowKeys createSecKey:data]];
100 if(!_signingKey){
101 if(error){
102 *error = [NSError errorWithDomain:octagonErrorDomain code:OTErrorKeyGeneration userInfo:@{NSLocalizedDescriptionKey: @"failed to create EC signing key"}];
103 }
104 return nil;
105 }
106 data = [OTEscrowKeys generateEscrowKey:kOTEscrowKeyEncryption masterSecret:secret dsid:self.dsid error:&localError];
107 if (!data) {
108 if(error){
109 *error = localError;
110 }
111 return nil;
112 }
113 _encryptionKey = [[SFECKeyPair alloc] initWithSecKey:[OTEscrowKeys createSecKey:data]];
114 if(!_encryptionKey){
115 if(error){
116 *error = [NSError errorWithDomain:octagonErrorDomain code:OTErrorKeyGeneration userInfo:@{NSLocalizedDescriptionKey: @"failed to create EC encryption key"}];
117 }
118 return nil;
119 }
120 data = [OTEscrowKeys generateEscrowKey:kOTEscrowKeySymmetric masterSecret:secret dsid:self.dsid error:&localError];
121 if (!data) {
122 if(error){
123 *error = localError;
124 }
125 return nil;
126 }
127 _symmetricKey = [[SFAESKey alloc] initWithData:data specifier:[[SFAESKeySpecifier alloc] initWithBitSize:SFAESKeyBitSize256] error:&localError];
128 if (!_symmetricKey) {
129 if(error){
130 *error = localError;
131 }
132 return nil;
133 }
134
135 BOOL result = [OTEscrowKeys storeEscrowedSigningKeyPair:[_signingKey keyData] error:&localError];
136 if(!result || localError){
137 secerror("octagon: could not store escrowed signing SPKI in keychain: %@", localError);
138 if(error){
139 *error = localError;
140 }
141 return nil;
142 }
143 result = [OTEscrowKeys storeEscrowedEncryptionKeyPair:[_encryptionKey keyData] error:error];
144 if(!result || localError){
145 secerror("octagon: could not store escrowed signing SPKI in keychain: %@", localError);
146 if(error){
147 *error = localError;
148 }
149 return nil;
150 }
151 result = [OTEscrowKeys storeEscrowedSymmetricKey:[_symmetricKey keyData] error:error];
152 if(!result || localError){
153 secerror("octagon: could not store escrowed signing SPKI in keychain: %@", localError);
154 if(error){
155 *error = localError;
156 }
157 return nil;
158 }
159 }
160 return self;
161 }
162
163 + (NSData* _Nullable) generateEscrowKey:(escrowKeyType)keyType
164 masterSecret:(NSData*)masterSecret
165 dsid:(NSString *)dsid
166 error:(NSError**)error
167 {
168 NSUInteger keyLength = 0;
169 const void *info = nil;
170 size_t infoLength = 0;
171 NSMutableData* derivedKey = NULL;
172
173 switch(keyType)
174 {
175 case kOTEscrowKeySymmetric:
176 keyLength = OT_ESCROW_SYMMETRIC_HKDF_SIZE;
177 info = escrowedSymmetric;
178 infoLength = sizeof(escrowedSymmetric);
179 break;
180 case kOTEscrowKeyEncryption:
181 keyLength = OT_ESCROW_ENCRYPTION_HKDF_SIZE;
182 info = escrowedEncryptionPrivKey;
183 infoLength = sizeof(escrowedEncryptionPrivKey);
184 break;
185 case kOTEscrowKeySigning:
186 keyLength = OT_ESCROW_SIGNING_HKDF_SIZE;
187 info = escrowedSigningPrivKey;
188 infoLength = sizeof(escrowedSigningPrivKey);
189 break;
190 default:
191 break;
192 }
193
194 ccec_const_cp_t cp = ccec_cp_384();
195 int status = 0;
196
197 ccec_full_ctx_decl_cp(cp, fullKey);
198
199 derivedKey = [NSMutableData dataWithLength:keyLength];
200 status = cchkdf(ccsha384_di(),
201 [masterSecret length], [masterSecret bytes],
202 strlen([dsid UTF8String]),[dsid UTF8String],
203 infoLength, info,
204 keyLength, [derivedKey mutableBytes]);
205
206
207 if (status != 0) {
208 if(error){
209 *error = [NSError errorWithDomain:octagonErrorDomain code:OTErrorKeyGeneration userInfo:nil];
210 }
211 secerror("octagon: could not generate seed for signing keys");
212 return nil;
213 }
214 if(keyType == kOTEscrowKeySymmetric){
215 return derivedKey;
216 }
217 else if(keyType == kOTEscrowKeyEncryption || keyType == kOTEscrowKeySigning){
218
219 status = ccec_generate_key_deterministic(cp,
220 [derivedKey length], [derivedKey mutableBytes],
221 ccDRBGGetRngState(),
222 CCEC_GENKEY_DETERMINISTIC_FIPS,
223 fullKey);
224 if(status != 0){
225 if(error){
226 *error = [NSError errorWithDomain:octagonErrorDomain code:OTErrorKeyGeneration userInfo:nil];
227 }
228 secerror("octagon: could not generate signing keys");
229 return nil;
230 }
231
232 size_t space = ccec_x963_export_size(true, ccec_ctx_pub(fullKey));
233 NSMutableData* key = [[NSMutableData alloc]initWithLength:space];
234 ccec_x963_export(true, [key mutableBytes], fullKey);
235 derivedKey = key;
236 }
237 return derivedKey;
238 }
239
240 + (SecKeyRef) createSecKey:(NSData*)keyData
241 {
242 NSDictionary *keyAttributes = @{
243 (__bridge id)kSecAttrKeyClass : (__bridge id)kSecAttrKeyClassPrivate,
244 (__bridge id)kSecAttrKeyType : (__bridge id)kSecAttrKeyTypeEC,
245 };
246
247 SecKeyRef key = SecKeyCreateWithData((__bridge CFDataRef)keyData, (__bridge CFDictionaryRef)keyAttributes, NULL);
248 return key;
249 }
250
251 + (BOOL) setKeyMaterialInKeychain:(NSDictionary*)query error:(NSError* __autoreleasing *)error
252 {
253 BOOL result = NO;
254
255 CFTypeRef results = NULL;
256 OSStatus status = SecItemAdd((__bridge CFDictionaryRef)query, &results);
257
258 NSError* localerror = nil;
259
260 if(status == errSecDuplicateItem || status == errSecSuccess) {
261 result = YES;
262 } else {
263 localerror = [NSError errorWithDomain:@"securityd"
264 code:status
265 userInfo:nil];
266 }
267 if(status != errSecSuccess) {
268 CFReleaseNull(results);
269
270 if(error) {
271 *error = localerror;
272 }
273 }
274
275 return result;
276 }
277
278 +(NSString*) hashIt:(NSData*)keyData
279 {
280 const struct ccdigest_info *di = ccsha384_di();
281 NSMutableData* result = [[NSMutableData alloc] initWithLength:ccsha384_di()->output_size];
282
283 ccdigest(di, [keyData length], [keyData bytes], [result mutableBytes]);
284
285 NSString* hash = [result base64EncodedStringWithOptions:0];
286 return hash;
287 }
288
289 + (BOOL)storeEscrowedEncryptionKeyPair:(NSData*)keyData error:(NSError**)error
290 {
291 NSDictionary* query = @{
292 (id)kSecClass : (id)kSecClassInternetPassword,
293 (id)kSecAttrAccessible: (id)kSecAttrAccessibleWhenUnlocked,
294 (id)kSecAttrNoLegacy : @YES,
295 (id)kSecAttrAccessGroup: @"com.apple.security.ckks",
296 (id)kSecAttrSynchronizable : (id)kCFBooleanFalse,
297 (id)kSecAttrServer : [self hashIt:keyData],
298 (id)kSecAttrLabel : @"Escrowed Encryption Key",
299 (id)kSecValueData : keyData,
300 };
301 return [OTEscrowKeys setKeyMaterialInKeychain:query error:error];
302 }
303
304 + (BOOL)storeEscrowedSigningKeyPair:(NSData*)keyData error:(NSError**)error
305 {
306 NSDictionary* query = @{
307 (id)kSecClass : (id)kSecClassInternetPassword,
308 (id)kSecAttrAccessible: (id)kSecAttrAccessibleWhenUnlocked,
309 (id)kSecAttrNoLegacy : @YES,
310 (id)kSecAttrAccessGroup: @"com.apple.security.ckks",
311 (id)kSecAttrSynchronizable : (id)kCFBooleanFalse,
312 (id)kSecAttrLabel : @"Escrowed Signing Key",
313 (id)kSecAttrServer : [self hashIt:keyData],
314 (id)kSecValueData : keyData,
315 };
316 return [OTEscrowKeys setKeyMaterialInKeychain:query error:error];
317 }
318
319 + (BOOL)storeEscrowedSymmetricKey:(NSData*)keyData error:(NSError**)error
320 {
321 NSDictionary* query = @{
322 (id)kSecClass : (id)kSecClassInternetPassword,
323 (id)kSecAttrAccessible: (id)kSecAttrAccessibleWhenUnlocked,
324 (id)kSecAttrNoLegacy : @YES,
325 (id)kSecAttrAccessGroup: @"com.apple.security.ckks",
326 (id)kSecAttrSynchronizable : (id)kCFBooleanFalse,
327 (id)kSecAttrLabel : @"Escrowed Symmetric Key",
328 (id)kSecAttrServer : [self hashIt:keyData],
329 (id)kSecValueData : keyData,
330 };
331 return [OTEscrowKeys setKeyMaterialInKeychain:query error:error];
332 }
333
334 @end
335 #endif