]> git.saurik.com Git - apple/security.git/blob - OSX/sec/securityd/AsymKeybagBackup.m
Security-58286.41.2.tar.gz
[apple/security.git] / OSX / sec / securityd / AsymKeybagBackup.m
1 /*
2 * Copyright (c) 2017 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
24 #include <AssertMacros.h>
25 #import <Foundation/Foundation.h>
26 #include <Security/SecBase.h>
27 #import "AsymKeybagBackup.h"
28 #import <Security/SecItemPriv.h>
29
30 #if USE_KEYSTORE
31 #include <libaks.h>
32 #endif
33
34 #include <utilities/debugging.h>
35 #include <utilities/SecCFWrappers.h>
36 #include "sec/ipc/securityd_client.h"
37
38 #if OCTAGON
39 #import "SecBackupKeybagEntry.h"
40 #endif
41
42 #if OCTAGON
43 #if USE_KEYSTORE
44
45 static bool writeKeybagPublicKey(CFDataRef keybag, CFDataRef identifier, CFErrorRef *error) {
46 bool ok = true;
47 NSData* publickeyHash = (__bridge NSData *)(identifier);
48 NSData* musr = [[NSData alloc] init];
49 NSError *localError = NULL;
50
51 SecBackupKeybagEntry *kbe = [[SecBackupKeybagEntry alloc] initWithPublicKey: (__bridge NSData*)keybag publickeyHash: (NSData*) publickeyHash user: musr];
52 ok = [kbe saveToDatabase: &localError];
53 CFErrorPropagate((__bridge CFErrorRef)(localError), error);
54 return ok;
55 }
56
57 static bool deleteKeybagViaPublicKeyHash(CFDataRef publickeyHash, CFStringRef agrp, CFDataRef musr, CFErrorRef *error) {
58 bool ok = true;
59 NSData* keybag = nil;
60 NSError *localError = NULL;
61
62 SecBackupKeybagEntry *kbe = [[SecBackupKeybagEntry alloc] initWithPublicKey: keybag publickeyHash: (__bridge NSData*)publickeyHash user: (__bridge NSData *)(musr)];
63 ok = [kbe deleteFromDatabase: &localError];
64
65 CFErrorPropagate((__bridge CFErrorRef)(localError), error);
66 return ok;
67 }
68
69 static bool deleteAllKeybags(CFErrorRef *error) {
70 NSError *localError = NULL;
71
72 bool ok = [SecBackupKeybagEntry deleteAll: &localError];
73
74 CFErrorPropagate((__bridge CFErrorRef)(localError), error);
75 return ok;
76 }
77
78 #endif
79 #endif
80
81 bool _SecServerBackupKeybagAdd(SecurityClient *client, CFDataRef passcode, CFDataRef *identifier, CFDataRef *pathinfo, CFErrorRef *error) {
82 bool ok = true;
83 #if OCTAGON
84 #if USE_KEYSTORE
85 CFURLRef upathinfo = NULL;
86 CFDataRef keybagData = NULL;
87 uuid_t uuid;
88 char uuidstr[37];
89 CFDataRef tidentifier = NULL;
90
91 secerror("_SecServerBackupKeybagAdd: passlen: %ld", CFDataGetLength(passcode) );
92
93 require_action(passcode && CFDataGetLength(passcode), xit, ok = SecError(errSecParam, error, CFSTR("passcode is required")));
94 keybag_handle_t handle = bad_keybag_handle;
95
96 kern_return_t kr = aks_create_bag(CFDataGetBytePtr(passcode), (int)CFDataGetLength(passcode), kAppleKeyStoreAsymmetricBackupBag, &handle);
97 require_action(kr == kIOReturnSuccess, xit, ok = SecError(errSecParam, error, CFSTR("could not create keybag: %d"), kr));
98
99 void *keybag = NULL;
100 int keybag_size = 0;
101 kr = aks_save_bag(handle, &keybag, &keybag_size);
102 require_action(kr == kIOReturnSuccess, xit, ok = SecError(errSecParam, error, CFSTR("could not save keybag: %d"), kr));
103 keybagData = CFDataCreate(kCFAllocatorDefault, keybag, keybag_size);
104
105 // For now, use uuid as key in db; will use publicKey hash later
106 kr = aks_get_bag_uuid(handle, uuid);
107 require_action(kr == kIOReturnSuccess, xit, ok = SecError(errSecParam, error, CFSTR("could not get keybag uuid: %d"), kr));
108
109 tidentifier = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)uuidstr, sizeof(uuidstr));
110 uuid_unparse_lower(uuid, uuidstr);
111 if (identifier)
112 *identifier = CFRetainSafe(tidentifier);
113
114 require_action(writeKeybagPublicKey(keybagData, tidentifier, error), xit, ok = SecError(errSecParam, error, CFSTR("passcode is required")));
115
116 if (pathinfo)
117 *pathinfo = NULL;
118 xit:
119 CFReleaseNull(tidentifier);
120 CFReleaseNull(upathinfo);
121 CFReleaseNull(keybagData);
122 #endif /* USE_KEYSTORE */
123 #endif
124 return ok;
125 }
126
127 bool _SecServerBackupKeybagDelete(CFDictionaryRef attributes, bool deleteAll, CFErrorRef *error) {
128 bool ok = true;
129 #if OCTAGON
130 #if USE_KEYSTORE
131 // Look for matching publicKeyHash
132
133 if (deleteAll) {
134 deleteAllKeybags(error);
135 } else {
136 CFDataRef publickeyHash = (CFDataRef)CFDictionaryGetValue(attributes, kSecAttrPublicKeyHash);
137 CFStringRef agrp = (CFStringRef)CFDictionaryGetValue(attributes, kSecAttrAccessGroup);
138 CFDataRef musr = (CFDataRef)CFDictionaryGetValue(attributes, kSecAttrMultiUser);
139
140 require_action(publickeyHash, xit, ok = SecError(errSecParam, error, CFSTR("publickeyHash is required")));
141 ok = deleteKeybagViaPublicKeyHash(publickeyHash, agrp, musr, error);
142 }
143 xit:
144 #endif /* USE_KEYSTORE */
145 #endif /* OCTAGON */
146 return ok;
147 }