1/*
2 * Copyright (c) 2013-2014 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 * keychain_backup.c
24 */
25
26#include <TargetConditionals.h>
27#if TARGET_OS_EMBEDDED
28
29#include "Securitycommands.h"
30
31#include <AssertMacros.h>
32#include <Security/SecItemPriv.h>
33
34#include <utilities/SecCFWrappers.h>
35
36#include <SecurityTool/readline.h>
37#include <SecurityTool/tool_errors.h>
38
39
40static int
41do_keychain_import(const char *backupPath, const char *keybagPath, const char *passwordString)
42{
43    CFDataRef backup=NULL;
44    CFDataRef keybag=NULL;
45    CFDataRef password=NULL;
46    bool ok=false;
47
48    if(passwordString) {
49        require(password = CFDataCreate(NULL, (UInt8 *)passwordString, strlen(passwordString)), out);
50    }
51    require(keybag=copyFileContents(keybagPath), out);
52    require(backup=copyFileContents(backupPath), out);
53
54    ok=_SecKeychainRestoreBackup(backup, keybag, password);
55
56out:
57    CFReleaseSafe(backup);
58    CFReleaseSafe(keybag);
59    CFReleaseSafe(password);
60
61    return ok?0:1;
62}
63
64static int
65do_keychain_export(const char *backupPath, const char *keybagPath, const char *passwordString)
66{
67    CFDataRef backup=NULL;
68    CFDataRef keybag=NULL;
69    CFDataRef password=NULL;
70    bool ok=false;
71
72    if(passwordString) {
73        require(password = CFDataCreate(NULL, (UInt8 *)passwordString, strlen(passwordString)), out);
74    }
75    require(keybag=copyFileContents(keybagPath), out);
76    require(backup=_SecKeychainCopyBackup(keybag, password), out);
77
78    ok=writeFileContents(backupPath, backup);
79
80out:
81    CFReleaseSafe(backup);
82    CFReleaseSafe(keybag);
83    CFReleaseSafe(password);
84
85    return ok?0:1;
86}
87
88
89int
90keychain_import(int argc, char * const *argv)
91{
92    int ch;
93    int verbose=0;
94    const char *keybag=NULL;
95    const char *password=NULL;
96
97    while ((ch = getopt(argc, argv, "vk:p:")) != -1)
98    {
99        switch (ch)
100        {
101            case 'v':
102                verbose++;
103                break;
104            case 'k':
105                keybag=optarg;
106                break;
107            case 'p':
108                password=optarg;
109                break;
110             default:
111                return 2; /* Trigger usage message. */
112        }
113    }
114
115    argc -= optind;
116    argv += optind;
117
118    if(keybag==NULL) {
119        sec_error("-k is required\n");
120        return 2;
121    }
122
123    if (argc != 1) {
124        sec_error("<backup> is required\n");
125        return 2; /* Trigger usage message. */
126    }
127
128    return do_keychain_import(argv[0], keybag, password);
129}
130
131int
132keychain_export(int argc, char * const *argv)
133{
134    int ch;
135    int verbose=0;
136    const char *keybag=NULL;
137    const char *password=NULL;
138
139    while ((ch = getopt(argc, argv, "vk:p:")) != -1)
140    {
141        switch (ch)
142        {
143            case 'v':
144                verbose++;
145                break;
146            case 'k':
147                keybag=optarg;
148                break;
149            case 'p':
150                password=optarg;
151                break;
152            default:
153                return 2; /* Trigger usage message. */
154        }
155    }
156
157    argc -= optind;
158    argv += optind;
159
160    if(keybag==NULL) {
161        sec_error("-k is required\n");
162        return 2;
163    }
164
165    if (argc != 1) {
166        sec_error("<backup> is required\n");
167        return 2; /* Trigger usage message. */
168    }
169
170    return do_keychain_export(argv[0], keybag, password);
171}
172
173#endif /* TARGET_OS_EMBEDDED */
174