2 * Copyright (c) 2017 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
24 #include <AssertMacros.h>
25 #import <Foundation/Foundation.h>
26 #include <Security/SecBase.h>
27 #import "AsymKeybagBackup.h"
28 #import <Security/SecItemPriv.h>
34 #include <utilities/debugging.h>
35 #include <utilities/SecCFWrappers.h>
36 #include "sec/ipc/securityd_client.h"
39 #import "SecBackupKeybagEntry.h"
45 static bool writeKeybagPublicKey(CFDataRef keybag, CFDataRef identifier, CFErrorRef *error) {
47 NSData* publickeyHash = (__bridge NSData *)(identifier);
48 NSData* musr = [[NSData alloc] init];
49 NSError *localError = NULL;
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);
57 static bool deleteKeybagViaPublicKeyHash(CFDataRef publickeyHash, CFStringRef agrp, CFDataRef musr, CFErrorRef *error) {
60 NSError *localError = NULL;
62 SecBackupKeybagEntry *kbe = [[SecBackupKeybagEntry alloc] initWithPublicKey: keybag publickeyHash: (__bridge NSData*)publickeyHash user: (__bridge NSData *)(musr)];
63 ok = [kbe deleteFromDatabase: &localError];
65 CFErrorPropagate((__bridge CFErrorRef)(localError), error);
69 static bool deleteAllKeybags(CFErrorRef *error) {
70 NSError *localError = NULL;
72 bool ok = [SecBackupKeybagEntry deleteAll: &localError];
74 CFErrorPropagate((__bridge CFErrorRef)(localError), error);
81 bool _SecServerBackupKeybagAdd(SecurityClient *client, CFDataRef passcode, CFDataRef *identifier, CFDataRef *pathinfo, CFErrorRef *error) {
85 CFURLRef upathinfo = NULL;
86 CFDataRef keybagData = NULL;
89 CFDataRef tidentifier = NULL;
91 secerror("_SecServerBackupKeybagAdd: passlen: %ld", CFDataGetLength(passcode) );
93 require_action(passcode && CFDataGetLength(passcode), xit, ok = SecError(errSecParam, error, CFSTR("passcode is required")));
94 keybag_handle_t handle = bad_keybag_handle;
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));
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);
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));
109 tidentifier = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)uuidstr, sizeof(uuidstr));
110 uuid_unparse_lower(uuid, uuidstr);
112 *identifier = CFRetainSafe(tidentifier);
114 require_action(writeKeybagPublicKey(keybagData, tidentifier, error), xit, ok = SecError(errSecParam, error, CFSTR("passcode is required")));
119 CFReleaseNull(tidentifier);
120 CFReleaseNull(upathinfo);
121 CFReleaseNull(keybagData);
122 #endif /* USE_KEYSTORE */
127 bool _SecServerBackupKeybagDelete(CFDictionaryRef attributes, bool deleteAll, CFErrorRef *error) {
131 // Look for matching publicKeyHash
134 deleteAllKeybags(error);
136 CFDataRef publickeyHash = (CFDataRef)CFDictionaryGetValue(attributes, kSecAttrPublicKeyHash);
137 CFStringRef agrp = (CFStringRef)CFDictionaryGetValue(attributes, kSecAttrAccessGroup);
138 CFDataRef musr = (CFDataRef)CFDictionaryGetValue(attributes, kSecAttrMultiUser);
140 require_action(publickeyHash, xit, ok = SecError(errSecParam, error, CFSTR("publickeyHash is required")));
141 ok = deleteKeybagViaPublicKeyHash(publickeyHash, agrp, musr, error);
144 #endif /* USE_KEYSTORE */