1#include <SecureObjectSync/SOSAccountPriv.h>
2#include <SecureObjectSync/SOSTransport.h>
3#include <SecureObjectSync/SOSTransportKeyParameter.h>
4#include <SecureObjectSync/SOSTransportKeyParameterKVS.h>
5#include <SecureObjectSync/SOSKVSKeys.h>
6#include <SOSCloudKeychainClient.h>
7#include <utilities/SecCFWrappers.h>
8
9static bool SOSTransportKeyParameterKVSPublishCloudParameters(SOSTransportKeyParameterKVSRef transport, CFDataRef newParameters, CFErrorRef *error);
10static bool publishCloudParameters(SOSTransportKeyParameterRef transport, CFDataRef data, CFErrorRef* error);
11static bool SOSTransportKeyParameterKVSUpdateKVS(CFDictionaryRef changes, CFErrorRef *error);
12static void destroy(SOSTransportKeyParameterRef transport);
13
14struct __OpaqueSOSTransportKeyParameterKVS{
15    struct __OpaqueSOSTransportKeyParameter     k;
16};
17
18static bool handleKeyParameterChanges(SOSTransportKeyParameterRef transport, CFDataRef data, CFErrorRef error){
19    SOSAccountRef account = transport->account;
20    return SOSAccountHandleParametersChange(account, data, &error);
21
22}
23
24static bool setToNewAccount(SOSTransportKeyParameterRef transport){
25    SOSAccountRef account = transport->account;
26    SOSAccountSetToNew(account);
27    return true;
28}
29
30SOSTransportKeyParameterKVSRef SOSTransportKeyParameterKVSCreate(SOSAccountRef account, CFErrorRef *error) {
31    SOSTransportKeyParameterKVSRef tkvs = (SOSTransportKeyParameterKVSRef) SOSTransportKeyParameterCreateForSubclass(sizeof(struct __OpaqueSOSTransportKeyParameterKVS) - sizeof(CFRuntimeBase), account, error);
32    if(tkvs){
33        tkvs->k.publishCloudParameters = publishCloudParameters;
34        tkvs->k.handleKeyParameterChanges = handleKeyParameterChanges;
35        tkvs->k.setToNewAccount = setToNewAccount;
36        tkvs->k.destroy = destroy;
37        SOSRegisterTransportKeyParameter((SOSTransportKeyParameterRef)tkvs);
38    }
39    return tkvs;
40}
41
42static void destroy(SOSTransportKeyParameterRef transport){
43    SOSUnregisterTransportKeyParameter(transport);
44}
45
46bool SOSTransportKeyParameterKVSHandleCloudParameterChange(SOSTransportKeyParameterRef transport, CFDataRef data, CFErrorRef* error){
47    SOSTransportKeyParameterKVSRef tkvs = (SOSTransportKeyParameterKVSRef)transport;
48    SOSAccountRef account = tkvs->k.account;
49
50    return SOSAccountHandleParametersChange(account, data, error);
51}
52
53
54bool SOSTransportKeyParameterKVSAppendKeyInterests(SOSTransportKeyParameterKVSRef transport, CFMutableArrayRef alwaysKeys, CFMutableArrayRef afterFirstUnlockKeys, CFMutableArrayRef unlockedKeys, CFErrorRef*error){
55
56    CFArrayAppendValue(alwaysKeys, kSOSKVSKeyParametersKey);
57
58    return true;
59}
60
61static bool publishCloudParameters(SOSTransportKeyParameterRef transport, CFDataRef data, CFErrorRef* error)
62{
63    return SOSTransportKeyParameterKVSPublishCloudParameters((SOSTransportKeyParameterKVSRef)transport, data, error);
64}
65
66static bool SOSTransportKeyParameterKVSUpdateKVS(CFDictionaryRef changes, CFErrorRef *error){
67    CloudKeychainReplyBlock log_error = ^(CFDictionaryRef returnedValues __unused, CFErrorRef error) {
68        if (error) {
69            secerror("Error putting: %@", error);
70            CFReleaseSafe(error);
71        }
72    };
73
74    SOSCloudKeychainPutObjectsInCloud(changes, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), log_error);
75    return true;
76}
77
78static bool SOSTransportKeyParameterKVSPublishCloudParameters(SOSTransportKeyParameterKVSRef transport, CFDataRef newParameters, CFErrorRef *error)
79{
80    CFDictionaryRef changes = CFDictionaryCreateForCFTypes(kCFAllocatorDefault,
81                                                           kSOSKVSKeyParametersKey, newParameters,
82                                                           NULL);
83
84    bool success = SOSTransportKeyParameterKVSUpdateKVS(changes, error);
85
86    CFReleaseNull(changes);
87
88    return success;
89}
90