/ RegressionTests / secbackuptest / secbackuptest.m
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