1//
2//  si-33-keychain-backup.c
3//  libsecurity_keychain
4//
5//  Created by Wade Benson on 4/16/13.
6//
7//
8
9#include <TargetConditionals.h>
10#include <stdio.h>
11
12#include "keychain_regressions.h"
13#include <Security/SecBase.h>
14#include <Security/SecItem.h>
15#include <Security/SecItemPriv.h>
16#include <libaks.h>
17#include <AssertMacros.h>
18
19
20static CFDataRef create_keybag(keybag_handle_t bag_type, CFDataRef password)
21{
22    keybag_handle_t handle = bad_keybag_handle;
23
24    if (aks_create_bag(NULL, 0, bag_type, &handle) == 0) {
25        void * keybag = NULL;
26        int keybag_size = 0;
27        if (aks_save_bag(handle, &keybag, &keybag_size) == 0) {
28            return CFDataCreate(kCFAllocatorDefault, keybag, keybag_size);
29        }
30    }
31
32    return CFDataCreate(kCFAllocatorDefault, NULL, 0);
33}
34
35/* Test low level keychain migration from device to device interface. */
36static void tests(void)
37{
38    int v_eighty = 80;
39    CFNumberRef eighty = CFNumberCreate(NULL, kCFNumberSInt32Type, &v_eighty);
40    const char *v_data = "test";
41    CFDataRef pwdata = CFDataCreate(NULL, (UInt8 *)v_data, strlen(v_data));
42    CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
43    CFTypeRef result = NULL;
44    CFDictionaryAddValue(query, kSecClass, kSecClassInternetPassword);
45    CFDictionaryAddValue(query, kSecAttrServer, CFSTR("members.spamcop.net"));
46    CFDictionaryAddValue(query, kSecAttrAccount, CFSTR("smith"));
47    CFDictionaryAddValue(query, kSecAttrPort, eighty);
48    CFDictionaryAddValue(query, kSecAttrProtocol, kSecAttrProtocolHTTP);
49    CFDictionaryAddValue(query, kSecAttrAuthenticationType, kSecAttrAuthenticationTypeDefault);
50    CFDictionaryAddValue(query, kSecValueData, pwdata);
51    CFDictionaryAddValue(query, kSecAttrSynchronizable, kCFBooleanTrue);
52
53    CFDataRef keybag = NULL, password = NULL;
54
55    keybag = create_keybag(kAppleKeyStoreAsymmetricBackupBag, password);
56
57    SecItemDelete(query);
58
59    // add syncable item
60    ok_status(SecItemAdd(query, NULL), "add internet password");
61
62    ok_status(SecItemCopyMatching(query, &result), "find item we are about to destroy");
63    if (result) { CFRelease(result); result = NULL; }
64
65    CFDictionaryRef backup = NULL;
66
67    ok_status(_SecKeychainBackupSyncable(keybag, password, NULL, &backup), "export items");
68
69    ok_status(SecItemDelete(query), "delete item we backed up");
70    is_status(SecItemCopyMatching(query, &result), errSecItemNotFound, "find item we are about to destroy");
71    if (result) { CFRelease(result); result = NULL; }
72
73    ok_status(_SecKeychainRestoreSyncable(keybag, password, backup), "import items");
74
75    ok_status(SecItemCopyMatching(query, &result), "find restored item");
76    if (result) { CFRelease(result); result = NULL; }
77
78    ok_status(SecItemDelete(query), "delete restored item");
79
80    if (backup) { CFRelease(backup); }
81}
82
83int si_33_keychain_backup(int argc, char *const *argv)
84{
85	plan_tests(8);
86
87
88	tests();
89
90	return 0;
91}
92