secbackuptest.m
1 // 2 // Copyright 2015 - 2016 Apple. All rights reserved. 3 // 4 5 /* 6 * This is to fool os services to not provide the Keychain manager 7 * interface tht doens't work since we don't have unified headers 8 * between iOS and OS X. rdar://23405418/ 9 */ 10 #define __KEYCHAINCORE__ 1 11 12 #include <Foundation/Foundation.h> 13 #include <Security/Security.h> 14 15 #include <TargetConditionals.h> 16 17 #include <Security/SecItemPriv.h> 18 #include <sys/stat.h> 19 #include <err.h> 20 21 #if TARGET_OS_SIMULATOR || TARGET_OS_BRIDGE 22 int 23 main(void) 24 { 25 return 0; 26 } 27 #else 28 29 #include <libaks.h> 30 31 static NSData *keybag = NULL; 32 static NSString *keybaguuid = NULL; 33 34 static void 35 BagMe(void) 36 { 37 keybag_handle_t handle; 38 kern_return_t result; 39 char uuidstr[37]; 40 uuid_t uuid; 41 void *data = NULL; 42 int length; 43 44 result = aks_create_bag("foo", 3, kAppleKeyStoreAsymmetricBackupBag, &handle); 45 if (result) 46 errx(1, "aks_create_bag: %08x", result); 47 48 result = aks_save_bag(handle, &data, &length); 49 if (result) 50 errx(1, "aks_save_bag"); 51 52 result = aks_get_bag_uuid(handle, uuid); 53 if (result) 54 errx(1, "aks_get_bag_uuid"); 55 56 uuid_unparse_lower(uuid, uuidstr); 57 58 keybaguuid = [NSString stringWithUTF8String:uuidstr]; 59 keybag = [NSData dataWithBytes:data length:length]; 60 } 61 62 int main (int argc, const char * argv[]) 63 { 64 @autoreleasepool { 65 NSData *password = NULL; 66 CFErrorRef error = NULL; 67 NSString *uuid = NULL; 68 69 BagMe(); 70 password = [NSData dataWithBytes:"foo" length:3]; 71 72 NSData *backup = CFBridgingRelease(_SecKeychainCopyBackup((__bridge CFDataRef)keybag, (__bridge CFDataRef)password)); 73 if (backup == NULL) { 74 errx(1, "backup failed"); 75 } 76 77 char path[] = "/tmp/secbackuptestXXXXXXX"; 78 int fd = mkstemp(path); 79 80 bool status = _SecKeychainWriteBackupToFileDescriptor((__bridge CFDataRef)keybag, (__bridge CFDataRef)password, fd, &error); 81 if (!status) { 82 NSLog(@"backup failed: %@", error); 83 errx(1, "failed backup 2"); 84 } 85 86 uuid = CFBridgingRelease(_SecKeychainCopyKeybagUUIDFromFileDescriptor(fd, &error)); 87 if (uuid == NULL) { 88 NSLog(@"getting uuid failed failed: %@", error); 89 errx(1, "failed getting uuid"); 90 } 91 92 if (![uuid isEqual:keybaguuid]) { 93 NSLog(@"getting uuid failed failed: %@ vs %@", uuid, keybaguuid); 94 errx(1, "failed compare uuid"); 95 } 96 97 struct stat sb; 98 fstat(fd, &sb); 99 100 if (sb.st_size != (off_t)[backup length]) 101 warn("backup different "); 102 103 if (abs((int)(sb.st_size - (off_t)[backup length])) > 1000) 104 errx(1, "backup different enough to fail"); 105 106 status = _SecKeychainRestoreBackupFromFileDescriptor(fd, (__bridge CFDataRef)keybag, (__bridge CFDataRef)password, &error); 107 if (!status) { 108 NSLog(@"restore failed: %@", error); 109 errx(1, "restore failed"); 110 } 111 112 close(fd); 113 unlink(path); 114 115 NSData *backup2 = CFBridgingRelease(_SecKeychainCopyBackup((__bridge CFDataRef)keybag, (__bridge CFDataRef)password)); 116 if (backup2 == NULL) { 117 errx(1, "backup 3 failed"); 118 } 119 120 if (abs((int)(sb.st_size - (off_t)[backup2 length])) > 1000) 121 errx(1, "backup different enough to fail (mem vs backup2): %d vs %d", (int)sb.st_size, (int)[backup2 length]); 122 if (abs((int)([backup length] - [backup2 length])) > 1000) 123 errx(1, "backup different enough to fail (backup1 vs backup2: %d vs %d", (int)[backup length], (int)[backup2 length]); 124 125 return 0; 126 } 127 } 128 129 #endif /* TARGET_OS_SIMULATOR */ 130