2 * Copyright (c) 2014 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@
25 // Test save and restore of SOSEngine states
27 #include "keychain/SecureObjectSync/Regressions/SOSTestDevice.h"
28 #include "keychain/SecureObjectSync/Regressions/SOSTestDataSource.h"
29 #include "secd_regressions.h"
30 #include "SecdTestKeychainUtilities.h"
32 #include "keychain/SecureObjectSync/SOSEngine.h"
33 #include "keychain/SecureObjectSync/SOSPeer.h"
34 #include <Security/SecBase64.h>
35 #include <Security/SecItem.h>
36 #include <Security/SecItemPriv.h>
37 #include <corecrypto/ccsha2.h>
38 #include "keychain/securityd/SecItemServer.h"
39 #include "keychain/securityd/SecItemDataSource.h"
40 #include <utilities/SecCFWrappers.h>
41 #include <utilities/SecIOFormat.h>
42 #include <utilities/SecFileLocations.h>
43 #include "SOSAccountTesting.h"
45 #include <AssertMacros.h>
49 static int kTestTestCount = 8;
52 Attributes for a v0 engine-state genp item
54 MANGO-iPhone:~ mobile$ security item class=genp,acct=engine-state
56 agrp : com.apple.security.sos
57 cdat : 2016-04-18 20:40:33 +0000
58 mdat : 2016-04-18 20:40:33 +0000
61 svce : SOSDataSource-ak
66 #include "secd-71-engine-save-sample1.h"
68 static bool verifyV2EngineState(SOSDataSourceRef ds, CFStringRef myPeerID) {
70 CFErrorRef error = NULL;
71 SOSTransactionRef txn = NULL;
72 CFDataRef basicEngineState = NULL;
73 CFDictionaryRef engineState = NULL;
76 CFDataRef basicEngineState = SOSDataSourceCopyStateWithKey(ds, kSOSEngineStatev2, kSecAttrAccessibleAlwaysPrivate, txn, &error);
77 skip("Failed to get V2 engine state", 2, basicEngineState);
78 ok(basicEngineState, "SOSDataSourceCopyStateWithKey:kSOSEngineStatev2");
79 engineState = derStateToDictionaryCopy(basicEngineState, &error);
80 skip("Failed to DER decode V2 engine state", 1, basicEngineState);
81 CFStringRef engID = (CFStringRef)asString(CFDictionaryGetValue(engineState, CFSTR("id")), &error);
82 ok(CFEqualSafe(myPeerID, engID),"Check myPeerID");
86 CFReleaseSafe(basicEngineState);
87 CFReleaseSafe(engineState);
92 static bool verifyV2PeerStates(SOSDataSourceRef ds, CFStringRef myPeerID, CFArrayRef peers) {
94 __block CFErrorRef error = NULL;
95 SOSTransactionRef txn = NULL;
96 CFDictionaryRef peerStateDict = NULL;
97 CFDataRef data = NULL;
98 __block CFIndex peerCount = CFArrayGetCount(peers) - 1; // drop myPeerID
101 data = SOSDataSourceCopyStateWithKey(ds, kSOSEnginePeerStates, kSOSEngineProtectionDomainClassD, txn, &error);
102 skip("Failed to get V2 peerStates", 3, data);
104 peerStateDict = derStateToDictionaryCopy(data, &error);
105 skip("Failed to DER decode V2 peerStates", 2, peerStateDict);
106 ok(peerStateDict, "SOSDataSourceCopyStateWithKey:kSOSEnginePeerStates");
108 // Check that each peer passed in exists in peerStateDict
109 CFArrayForEach(peers, ^(const void *key) {
110 CFStringRef peerID = (CFStringRef)asString(key, &error);
111 if (!CFEqualSafe(myPeerID, peerID)) {
112 if (CFDictionaryContainsKey(peerStateDict, peerID))
116 ok(peerCount==0,"Peers exist in peer list (%ld)", (CFArrayGetCount(peers) - 1 - peerCount));
120 CFReleaseSafe(peerStateDict);
122 CFReleaseSafe(error);
126 static bool checkV2EngineStates(SOSTestDeviceRef td, CFStringRef myPeerID, CFArrayRef peers) {
128 CFErrorRef error = NULL;
129 SOSTransactionRef txn = NULL;
130 CFDictionaryRef manifestCache = NULL;
131 CFDataRef data = NULL;
132 // CFMutableDictionaryRef codersDict = NULL; // SOSEngineLoadCoders
134 rx &= verifyV2EngineState(td->ds, myPeerID);
136 data = SOSDataSourceCopyStateWithKey(td->ds, kSOSEngineManifestCache, kSOSEngineProtectionDomainClassD, txn, &error);
137 manifestCache = derStateToDictionaryCopy(data, &error);
140 rx &= verifyV2PeerStates(td->ds, myPeerID, peers);
142 CFReleaseSafe(manifestCache);
146 static void testSaveRestore(void) {
147 CFMutableArrayRef deviceIDs = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
148 CFArrayAppendValue(deviceIDs, CFSTR("lemon"));
149 CFArrayAppendValue(deviceIDs, CFSTR("lime"));
150 CFArrayAppendValue(deviceIDs, CFSTR("orange"));
153 CFErrorRef error = NULL;
154 __block int devIdx = 0;
155 CFMutableDictionaryRef testDevices = SOSTestDeviceListCreate(false, version, deviceIDs, ^(SOSDataSourceRef ds) {
156 // This block is called before SOSEngineLoad
158 // Test migration of v0 to v2 engine state
159 CFDataRef engineStateData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, es_mango_bin, es_mango_bin_len, kCFAllocatorNull);
160 SOSTestDeviceAddV0EngineStateWithData(ds, engineStateData);
161 CFReleaseSafe(engineStateData);
166 CFStringRef sourceID = (CFStringRef)CFArrayGetValueAtIndex(deviceIDs, 0);
167 SOSTestDeviceRef source = (SOSTestDeviceRef)CFDictionaryGetValue(testDevices, sourceID);
169 ok(SOSTestDeviceEngineSave(source, &error),"SOSTestDeviceEngineSave: %@",error);
171 bx = SOSTestDeviceEngineLoad(source, &error);
172 ok(bx,"SOSTestEngineLoad: %@",error);
174 bx = checkV2EngineStates(source, sourceID, deviceIDs);
175 ok(bx,"getV2EngineStates: %@",error);
177 bx = SOSTestDeviceEngineSave(source, &error);
178 ok(bx,"SOSTestDeviceEngineSave v2: %@",error);
180 SOSTestDeviceDestroyEngine(testDevices);
181 CFReleaseSafe(deviceIDs);
182 CFReleaseSafe(testDevices);
183 CFReleaseSafe(error);
187 int secd_71_engine_save(int argc, char *const *argv)
190 plan_tests(kTestTestCount);