2 * Copyright (c) 2020 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@
24 #import <Foundation/Foundation.h>
25 #import "OTEscrowTranslation.h"
27 #import <SoftLinking/SoftLinking.h>
28 #import <CloudServices/SecureBackup.h>
29 #import <CloudServices/SecureBackupConstants.h>
30 #import "keychain/ot/categories/OctagonEscrowRecoverer.h"
31 #import <OctagonTrust/OTEscrowRecordMetadata.h>
32 #import <OctagonTrust/OTEscrowRecordMetadataClientMetadata.h>
33 #import <Security/OTConstants.h>
34 #import "keychain/ot/OTClique+Private.h"
35 #import <utilities/debugging.h>
37 SOFT_LINK_OPTIONAL_FRAMEWORK(PrivateFrameworks, CloudServices);
39 #pragma clang diagnostic push
40 #pragma clang diagnostic ignored "-Wstrict-prototypes"
42 SOFT_LINK_CLASS(CloudServices, SecureBackup);
43 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupErrorDomain, NSErrorDomain);
45 /* Escrow Authentication Information used for SRP*/
46 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupAuthenticationAppleID, NSString*);
47 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupAuthenticationPassword, NSString*);
48 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupAuthenticationiCloudEnvironment, NSString*);
49 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupAuthenticationAuthToken, NSString*);
50 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupAuthenticationEscrowProxyURL, NSString*);
51 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupIDMSRecoveryKey, NSString*);
52 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupFMiPRecoveryKey, NSString*);
53 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupFMiPUUIDKey, NSString*);
54 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupAuthenticationDSID, NSString*);
56 /* CDP recovery information */
57 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupUseCachedPassphraseKey, NSString*);
58 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupPassphraseKey, NSString*);
59 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupRecoveryKeyKey, NSString*);
60 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupContainsiCDPDataKey, NSString*);
61 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupSilentRecoveryAttemptKey, NSString*);
64 /* Escrow Record Fields set by SecureBackup*/
65 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupIsEnabledKey, NSString*);
66 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupUsesRecoveryKeyKey, NSString*);
67 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupLastBackupTimestampKey, NSString*);
68 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupLastBackupDateKey, NSString*);
69 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupEscrowTrustStatusKey, NSString*);
70 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupRecordStatusKey, NSString*);
71 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupRecordIDKey, NSString*);
72 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupPeerInfoDataKey, NSString*);
73 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupPeerInfoSerialNumberKey, NSString*);
74 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupPeerInfoOSVersionKey, NSString*);
75 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupAlliCDPRecordsKey, NSString*);
76 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupRecordLabelKey, NSString*);
77 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupEscrowedSPKIKey, NSString*);
78 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupBottleIDKey, NSString*);
79 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupSerialNumberKey, NSString*);
80 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupBuildVersionKey, NSString*);
82 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupUsesRandomPassphraseKey, NSString*);
83 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupUsesComplexPassphraseKey, NSString*);
84 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupUsesNumericPassphraseKey, NSString*);
85 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupNumericPassphraseLengthKey, NSString*);
87 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupRecoveryRequiresVerificationTokenKey, NSString*);
88 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupAccountIsHighSecurityKey, NSString*);
89 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupSMSTargetInfoKey, NSString*);
90 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupMetadataKey, NSString*);
91 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupUsesMultipleiCSCKey, NSString*);
92 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupClientMetadataKey, NSString*);
93 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupBottleValidityKey, NSString*);
94 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupEscrowDateKey, NSString*);
95 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupRemainingAttemptsKey, NSString*);
96 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupCoolOffEndKey, NSString*);
97 SOFT_LINK_CONSTANT(CloudServices, kSecureBackupRecoveryStatusKey, NSString*);
99 #pragma clang diagnostic pop
101 static NSString * const kCliqueSecureBackupTimestampKey = @"com.apple.securebackup.timestamp";
102 static NSString * const kCliqueEscrowServiceRecordMetadataKey = @"metadata";
103 static NSString * const kCliqueSecureBackupEncodedMetadataKey = @"encodedMetadata";
104 static NSString * const kCliqueSecureBackupKeybagDigestKey = @"BackupKeybagDigest";
105 static NSString * const kCliqueSecureBackupMetadataTimestampKey = @"SecureBackupMetadataTimestamp";
106 static NSString * const kCliqueSecureBackupDeviceColor = @"device_color";
107 static NSString * const kCliqueSecureBackupDeviceEnclosureColor = @"device_enclosure_color";
108 static NSString * const kCliqueSecureBackupDeviceMID = @"device_mid";
109 static NSString * const kCliqueSecureBackupDeviceModel = @"device_model";
110 static NSString * const kCliqueSecureBackupDeviceModelClass = @"device_model_class";
111 static NSString * const kCliqueSecureBackupDeviceModelVersion = @"device_model_version";
112 static NSString * const kCliqueSecureBackupDeviceName = @"device_name";
113 static NSString * const kCliqueSecureBackupDevicePlatform = @"device_platform";
114 static NSString * const kCliqueSecureBackupSilentAttemptAllowed = @"silentAttemptAllowed";
116 @implementation OTEscrowTranslation
118 //dictionary to escrow auth
119 + (OTEscrowAuthenticationInformation*) dictionaryToEscrowAuthenticationInfo:(NSDictionary*)dictionary
121 if ([OTClique isCloudServicesAvailable] == NO) {
125 OTEscrowAuthenticationInformation* escrowAuthInfo = [[OTEscrowAuthenticationInformation alloc] init];
126 escrowAuthInfo.authenticationAppleid = dictionary[getkSecureBackupAuthenticationAppleID()];
127 escrowAuthInfo.authenticationAuthToken = dictionary[getkSecureBackupAuthenticationAuthToken()];
128 escrowAuthInfo.authenticationDsid = dictionary[getkSecureBackupAuthenticationDSID()];
129 escrowAuthInfo.authenticationEscrowproxyUrl = dictionary[getkSecureBackupAuthenticationEscrowProxyURL()];
130 escrowAuthInfo.authenticationIcloudEnvironment = dictionary[getkSecureBackupAuthenticationiCloudEnvironment()];
131 escrowAuthInfo.authenticationPassword = dictionary[getkSecureBackupAuthenticationPassword()];
132 escrowAuthInfo.fmipUuid = dictionary[getkSecureBackupFMiPUUIDKey()];
133 escrowAuthInfo.fmipRecovery = [dictionary[getkSecureBackupFMiPRecoveryKey()] boolValue];
134 escrowAuthInfo.idmsRecovery = [dictionary[getkSecureBackupIDMSRecoveryKey()] boolValue];
136 return escrowAuthInfo;
139 //escrow auth to dictionary
140 + (NSDictionary*) escrowAuthenticationInfoToDictionary:(OTEscrowAuthenticationInformation*)escrowAuthInfo
142 if ([OTClique isCloudServicesAvailable] == NO) {
146 NSMutableDictionary* dictionary = [NSMutableDictionary dictionary];
147 if(![escrowAuthInfo.authenticationAppleid isEqualToString:@""]){
148 dictionary[getkSecureBackupAuthenticationAppleID()] = escrowAuthInfo.authenticationAppleid;
150 if(![escrowAuthInfo.authenticationAuthToken isEqualToString:@""]){
151 dictionary[getkSecureBackupAuthenticationAuthToken()] = escrowAuthInfo.authenticationAuthToken;
153 if(![escrowAuthInfo.authenticationDsid isEqualToString:@""]){
154 dictionary[getkSecureBackupAuthenticationDSID()] = escrowAuthInfo.authenticationDsid;
156 if(![escrowAuthInfo.authenticationEscrowproxyUrl isEqualToString:@""]){
157 dictionary[getkSecureBackupAuthenticationEscrowProxyURL()] = escrowAuthInfo.authenticationEscrowproxyUrl;
159 if(![escrowAuthInfo.authenticationIcloudEnvironment isEqualToString:@""]){
160 dictionary[getkSecureBackupAuthenticationiCloudEnvironment()] = escrowAuthInfo.authenticationIcloudEnvironment;
162 if(![escrowAuthInfo.authenticationPassword isEqualToString:@""]){
163 dictionary[getkSecureBackupAuthenticationPassword()] = escrowAuthInfo.authenticationPassword;
165 if(![escrowAuthInfo.fmipUuid isEqualToString:@""]){
166 dictionary[getkSecureBackupFMiPUUIDKey()] = escrowAuthInfo.fmipUuid;
168 dictionary[getkSecureBackupFMiPRecoveryKey()] = escrowAuthInfo.fmipRecovery ? @YES : @NO;
169 dictionary[getkSecureBackupIDMSRecoveryKey()] = escrowAuthInfo.idmsRecovery ? @YES : @NO;
174 + (OTCDPRecoveryInformation*)dictionaryToCDPRecoveryInformation:(NSDictionary*)dictionary
176 if ([OTClique isCloudServicesAvailable] == NO) {
180 OTCDPRecoveryInformation* info = [[OTCDPRecoveryInformation alloc] init];
181 info.recoverySecret = dictionary[getkSecureBackupPassphraseKey()];
182 info.useCachedSecret = [dictionary[getkSecureBackupUseCachedPassphraseKey()] boolValue];
183 info.recoveryKey = dictionary[getkSecureBackupRecoveryKeyKey()];
184 info.usePreviouslyCachedRecoveryKey = [dictionary[getkSecureBackupUsesRecoveryKeyKey()] boolValue];
185 info.silentRecoveryAttempt = [dictionary[@"SecureBackupSilentRecoveryAttempt"] boolValue];
186 info.containsIcdpData =[dictionary[getkSecureBackupContainsiCDPDataKey()] boolValue];
187 info.usesMultipleIcsc = [dictionary[getkSecureBackupUsesMultipleiCSCKey()] boolValue];
191 + (NSDictionary*)cdpRecoveryInformationToDictionary:(OTCDPRecoveryInformation*)info
193 if ([OTClique isCloudServicesAvailable] == NO) {
197 NSMutableDictionary* dictionary = [NSMutableDictionary dictionary];
198 dictionary[getkSecureBackupPassphraseKey()] = info.recoverySecret;
199 dictionary[getkSecureBackupUseCachedPassphraseKey()] = info.useCachedSecret ? @YES : @NO;
200 dictionary[getkSecureBackupRecoveryKeyKey()] = info.recoveryKey;
201 dictionary[getkSecureBackupUsesRecoveryKeyKey()] = info.usePreviouslyCachedRecoveryKey ? @YES : @NO;
202 dictionary[@"SecureBackupSilentRecoveryAttempt"] = info.silentRecoveryAttempt ? @YES : @NO;
203 dictionary[getkSecureBackupContainsiCDPDataKey()] = info.containsIcdpData ? @YES : @NO;
204 dictionary[getkSecureBackupUsesMultipleiCSCKey()] = info.usesMultipleIcsc ? @YES : @NO;
209 + (NSDate *)_dateWithSecureBackupDateString:(NSString *)dateString
211 NSDateFormatter *dateFormatter = [NSDateFormatter new];
212 dateFormatter.dateFormat = @"dd-MM-yyyy HH:mm:ss";
213 NSDate *ret = [dateFormatter dateFromString:dateString];
218 // New date format is GMT
219 dateFormatter.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];
220 dateFormatter.dateFormat = @"yyyy-MM-dd HH:mm:ss";
221 return [dateFormatter dateFromString:dateString];
224 + (NSString*)_stringWithSecureBackupDate:(NSDate*) date
226 NSDateFormatter *dateFormatter = [NSDateFormatter new];
227 dateFormatter.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];
228 dateFormatter.dateFormat = @"yyyy-MM-dd HH:mm:ss";
229 return [dateFormatter stringFromDate: date];
232 + (OTEscrowRecordMetadata *) dictionaryToMetadata:(NSDictionary*)dictionary
234 if ([OTClique isCloudServicesAvailable] == NO) {
238 OTEscrowRecordMetadata *metadata = [[OTEscrowRecordMetadata alloc] init];
240 metadata.backupKeybagDigest = dictionary[kCliqueSecureBackupKeybagDigestKey];
241 metadata.secureBackupUsesMultipleIcscs = [dictionary[getkSecureBackupUsesMultipleiCSCKey()] boolValue];
242 metadata.bottleId = dictionary[getkSecureBackupBottleIDKey()];
243 metadata.bottleValidity = dictionary[@"bottleValid"];
244 NSDate* secureBackupTimestamp = [OTEscrowTranslation _dateWithSecureBackupDateString: dictionary[kCliqueSecureBackupTimestampKey]];
246 metadata.secureBackupTimestamp = [secureBackupTimestamp timeIntervalSince1970];
247 metadata.escrowedSpki = dictionary[getkSecureBackupEscrowedSPKIKey()];
248 metadata.peerInfo = dictionary[getkSecureBackupPeerInfoDataKey()];
249 metadata.serial = dictionary[getkSecureBackupSerialNumberKey()];
251 NSDictionary* escrowInformationMetadataClientMetadata = dictionary[getkSecureBackupClientMetadataKey()];
252 metadata.clientMetadata = [[OTEscrowRecordMetadataClientMetadata alloc] init];
253 NSNumber *platform = escrowInformationMetadataClientMetadata[kCliqueSecureBackupDevicePlatform];
254 metadata.clientMetadata.devicePlatform = [platform longLongValue];
256 NSDate* secureBackupMetadataTimestamp = [OTEscrowTranslation _dateWithSecureBackupDateString: escrowInformationMetadataClientMetadata[kCliqueSecureBackupMetadataTimestampKey]];
257 metadata.clientMetadata.secureBackupMetadataTimestamp = [secureBackupMetadataTimestamp timeIntervalSince1970];
259 NSNumber *passphraseLength = escrowInformationMetadataClientMetadata[getkSecureBackupNumericPassphraseLengthKey()];
260 metadata.clientMetadata.secureBackupNumericPassphraseLength = [passphraseLength longLongValue];
261 metadata.clientMetadata.secureBackupUsesComplexPassphrase = [escrowInformationMetadataClientMetadata[getkSecureBackupUsesComplexPassphraseKey()] boolValue];
262 metadata.clientMetadata.secureBackupUsesNumericPassphrase = [escrowInformationMetadataClientMetadata[getkSecureBackupUsesNumericPassphraseKey()] boolValue];
263 metadata.clientMetadata.deviceColor = escrowInformationMetadataClientMetadata[kCliqueSecureBackupDeviceColor];
264 metadata.clientMetadata.deviceEnclosureColor = escrowInformationMetadataClientMetadata[kCliqueSecureBackupDeviceEnclosureColor];
265 metadata.clientMetadata.deviceMid = escrowInformationMetadataClientMetadata[kCliqueSecureBackupDeviceMID];
266 metadata.clientMetadata.deviceModel = escrowInformationMetadataClientMetadata[kCliqueSecureBackupDeviceModel];
267 metadata.clientMetadata.deviceModelClass = escrowInformationMetadataClientMetadata[kCliqueSecureBackupDeviceModelClass];
268 metadata.clientMetadata.deviceModelVersion = escrowInformationMetadataClientMetadata[kCliqueSecureBackupDeviceModelVersion];
269 metadata.clientMetadata.deviceName = escrowInformationMetadataClientMetadata[kCliqueSecureBackupDeviceName];
274 //dictionary to escrow record
275 + (OTEscrowRecord*) dictionaryToEscrowRecord:(NSDictionary*)dictionary
277 if ([OTClique isCloudServicesAvailable] == NO) {
281 OTEscrowRecord* record = [[OTEscrowRecord alloc] init];
282 NSDate* creationDate = dictionary[getkSecureBackupEscrowDateKey()];
283 record.creationDate = [creationDate timeIntervalSince1970];
284 NSDictionary* escrowInformationMetadata = dictionary[kCliqueEscrowServiceRecordMetadataKey];
285 record.escrowInformationMetadata = [OTEscrowTranslation dictionaryToMetadata:escrowInformationMetadata];
287 NSNumber *remainingAttempts = dictionary[getkSecureBackupRemainingAttemptsKey()];
289 record.remainingAttempts = [remainingAttempts longLongValue];
290 record.label = dictionary[getkSecureBackupRecordLabelKey()];
291 record.recordStatus = [dictionary[getkSecureBackupRecordStatusKey()] isEqualToString:@"valid"] ? OTEscrowRecord_RecordStatus_RECORD_STATUS_VALID : OTEscrowRecord_RecordStatus_RECORD_STATUS_INVALID;
292 record.silentAttemptAllowed = [dictionary[kCliqueSecureBackupSilentAttemptAllowed] boolValue];
293 record.recordId = dictionary[getkSecureBackupRecordIDKey()];
294 record.serialNumber = dictionary[getkSecureBackupPeerInfoSerialNumberKey()];
295 if(dictionary[getkSecureBackupCoolOffEndKey()]) {
296 record.coolOffEnd = [dictionary[getkSecureBackupCoolOffEndKey()] longLongValue];
298 record.recoveryStatus = [dictionary[getkSecureBackupRecoveryStatusKey()] intValue];
302 + (NSDictionary *) metadataToDictionary:(OTEscrowRecordMetadata*)metadata
304 if ([OTClique isCloudServicesAvailable] == NO) {
308 NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
309 dictionary[getkSecureBackupClientMetadataKey()] = [NSMutableDictionary dictionary];
311 dictionary[kCliqueSecureBackupKeybagDigestKey] = metadata.backupKeybagDigest;
312 dictionary[getkSecureBackupUsesMultipleiCSCKey()] = [[NSNumber alloc]initWithUnsignedLongLong:metadata.secureBackupUsesMultipleIcscs];
313 dictionary[getkSecureBackupBottleIDKey()] = metadata.bottleId;
314 dictionary[@"bottleValid"] = metadata.bottleValidity;
315 dictionary[kCliqueSecureBackupTimestampKey] = [OTEscrowTranslation _stringWithSecureBackupDate: [NSDate dateWithTimeIntervalSince1970: metadata.secureBackupTimestamp]];
316 dictionary[getkSecureBackupEscrowedSPKIKey()] = metadata.escrowedSpki;
317 dictionary[getkSecureBackupPeerInfoDataKey()] = metadata.peerInfo;
318 dictionary[getkSecureBackupSerialNumberKey()] = metadata.serial;
319 dictionary[getkSecureBackupClientMetadataKey()][kCliqueSecureBackupDevicePlatform] = [[NSNumber alloc]initWithUnsignedLongLong: metadata.clientMetadata.devicePlatform];
320 dictionary[getkSecureBackupClientMetadataKey()][kCliqueSecureBackupMetadataTimestampKey] = [OTEscrowTranslation _stringWithSecureBackupDate: [NSDate dateWithTimeIntervalSince1970: metadata.clientMetadata.secureBackupMetadataTimestamp]];
321 dictionary[getkSecureBackupClientMetadataKey()][getkSecureBackupNumericPassphraseLengthKey()] = [[NSNumber alloc]initWithUnsignedLongLong: metadata.clientMetadata.secureBackupNumericPassphraseLength];
322 dictionary[getkSecureBackupClientMetadataKey()][getkSecureBackupUsesComplexPassphraseKey()] = [[NSNumber alloc]initWithUnsignedLongLong: metadata.clientMetadata.secureBackupUsesComplexPassphrase];
323 dictionary[getkSecureBackupClientMetadataKey()][getkSecureBackupUsesNumericPassphraseKey()] = [[NSNumber alloc]initWithUnsignedLongLong: metadata.clientMetadata.secureBackupUsesNumericPassphrase];
324 dictionary[getkSecureBackupClientMetadataKey()][kCliqueSecureBackupDeviceColor] = metadata.clientMetadata.deviceColor;
325 dictionary[getkSecureBackupClientMetadataKey()][kCliqueSecureBackupDeviceEnclosureColor] = metadata.clientMetadata.deviceEnclosureColor;
326 dictionary[getkSecureBackupClientMetadataKey()][kCliqueSecureBackupDeviceMID] = metadata.clientMetadata.deviceMid;
327 dictionary[getkSecureBackupClientMetadataKey()][kCliqueSecureBackupDeviceModel] = metadata.clientMetadata.deviceModel;
328 dictionary[getkSecureBackupClientMetadataKey()][kCliqueSecureBackupDeviceModelClass] = metadata.clientMetadata.deviceModelClass;
329 dictionary[getkSecureBackupClientMetadataKey()][kCliqueSecureBackupDeviceModelVersion] = metadata.clientMetadata.deviceModelVersion;
330 dictionary[getkSecureBackupClientMetadataKey()][kCliqueSecureBackupDeviceName] = metadata.clientMetadata.deviceName;
335 //escrow record to dictionary
336 + (NSDictionary*) escrowRecordToDictionary:(OTEscrowRecord*)escrowRecord
338 if ([OTClique isCloudServicesAvailable] == NO) {
342 NSMutableDictionary* dictionary = [NSMutableDictionary dictionary];
343 dictionary[getkSecureBackupEscrowDateKey()] = [NSDate dateWithTimeIntervalSince1970: escrowRecord.creationDate];
345 dictionary[kCliqueEscrowServiceRecordMetadataKey] = [OTEscrowTranslation metadataToDictionary: escrowRecord.escrowInformationMetadata];
347 dictionary[getkSecureBackupRemainingAttemptsKey()] = [[NSNumber alloc]initWithUnsignedLongLong:escrowRecord.remainingAttempts];
348 dictionary[getkSecureBackupRecordLabelKey()] = escrowRecord.label;
349 dictionary[getkSecureBackupRecordStatusKey()] = escrowRecord.recordStatus == OTEscrowRecord_RecordStatus_RECORD_STATUS_VALID ? @"valid" : @"invalid";
350 dictionary[kCliqueSecureBackupSilentAttemptAllowed] = [[NSNumber alloc] initWithUnsignedLongLong: escrowRecord.silentAttemptAllowed];
351 dictionary[getkSecureBackupRecordIDKey()] = escrowRecord.recordId;
352 dictionary[getkSecureBackupPeerInfoSerialNumberKey()] = escrowRecord.serialNumber;
353 dictionary[getkSecureBackupCoolOffEndKey()] = @(escrowRecord.coolOffEnd);
354 dictionary[getkSecureBackupRecoveryStatusKey()] = @(escrowRecord.recoveryStatus);
359 + (OTICDPRecordContext*)dictionaryToCDPRecordContext:(NSDictionary*)dictionary
361 if ([OTClique isCloudServicesAvailable] == NO) {
365 OTICDPRecordContext* context = [[OTICDPRecordContext alloc] init];
366 context.authInfo = [OTEscrowTranslation dictionaryToEscrowAuthenticationInfo:dictionary];
367 context.cdpInfo = [OTEscrowTranslation dictionaryToCDPRecoveryInformation:dictionary];
372 + (NSDictionary*)CDPRecordContextToDictionary:(OTICDPRecordContext*)context
374 if ([OTClique isCloudServicesAvailable] == NO) {
378 NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
380 [dictionary addEntriesFromDictionary:[OTEscrowTranslation escrowAuthenticationInfoToDictionary:context.authInfo]];
381 [dictionary addEntriesFromDictionary:[OTEscrowTranslation cdpRecoveryInformationToDictionary:context.cdpInfo]];
386 + (BOOL)supportedRestorePath:(OTICDPRecordContext *)cdpContext
388 return (cdpContext.authInfo.idmsRecovery == false
389 && (cdpContext.authInfo.fmipUuid == nil || [cdpContext.authInfo.fmipUuid isEqualToString:@""])
390 && cdpContext.authInfo.fmipRecovery == false
391 && (cdpContext.cdpInfo.recoveryKey == nil || [cdpContext.cdpInfo.recoveryKey isEqualToString:@""])
392 && cdpContext.cdpInfo.usePreviouslyCachedRecoveryKey == false);