1//
2//  AccountCloudParameters.c
3//  sec
4//
5
6#include "SOSAccountPriv.h"
7#include <SecureObjectSync/SOSTransportKeyParameter.h>
8//
9// Cloud Paramters encode/decode
10//
11
12static size_t der_sizeof_cloud_parameters(SecKeyRef publicKey, CFDataRef paramters, CFErrorRef* error)
13{
14    size_t public_key_size = der_sizeof_public_bytes(publicKey, error);
15    size_t parameters_size = der_sizeof_data_or_null(paramters, error);
16
17    return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, public_key_size + parameters_size);
18}
19
20static uint8_t* der_encode_cloud_parameters(SecKeyRef publicKey, CFDataRef paramters, CFErrorRef* error,
21                                            const uint8_t* der, uint8_t* der_end)
22{
23    uint8_t* original_der_end = der_end;
24
25    return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, original_der_end, der,
26                                       der_encode_public_bytes(publicKey, error, der,
27                                                               der_encode_data_or_null(paramters, error, der, der_end)));
28}
29
30static const uint8_t* der_decode_cloud_parameters(CFAllocatorRef allocator,
31                                                  CFIndex algorithmID, SecKeyRef* publicKey,
32                                                  CFDataRef *parameters,
33                                                  CFErrorRef* error,
34                                                  const uint8_t* der, const uint8_t* der_end)
35{
36    const uint8_t *sequence_end;
37    der = ccder_decode_sequence_tl(&sequence_end, der, der_end);
38    der = der_decode_public_bytes(allocator, algorithmID, publicKey, error, der, sequence_end);
39    der = der_decode_data_or_null(allocator, parameters, error, der, sequence_end);
40
41    return der;
42}
43
44
45bool SOSAccountPublishCloudParameters(SOSAccountRef account, CFErrorRef* error){
46    bool success = false;
47    CFIndex cloud_der_len = der_sizeof_cloud_parameters(
48                                                        account->user_public,
49                                                        account->user_key_parameters,
50                                                        error);
51    CFMutableDataRef cloudParameters =
52    CFDataCreateMutableWithScratch(kCFAllocatorDefault, cloud_der_len);
53
54    if (der_encode_cloud_parameters(account->user_public, account->user_key_parameters, error,
55                                    CFDataGetMutableBytePtr(cloudParameters),
56                                    CFDataGetMutablePastEndPtr(cloudParameters)) != NULL) {
57
58        CFErrorRef changeError = NULL;
59        if (SOSTrasnportKeyParameterPublishCloudParameters(account->key_transport, cloudParameters, error)) {
60            success = true;
61        } else {
62            SOSCreateErrorWithFormat(kSOSErrorSendFailure, changeError, error, NULL,
63                                     CFSTR("update parameters key failed [%@]"), cloudParameters);
64        }
65        CFReleaseSafe(changeError);
66    } else {
67        SOSCreateError(kSOSErrorEncodeFailure, CFSTR("Encoding parameters failed"), NULL, error);
68    }
69
70    CFReleaseNull(cloudParameters);
71
72    return success;
73}
74
75bool SOSAccountRetrieveCloudParameters(SOSAccountRef account, SecKeyRef *newKey,
76                                       CFDataRef derparms,
77                                       CFDataRef *newParameters, CFErrorRef* error) {
78    const uint8_t *parse_end = der_decode_cloud_parameters(kCFAllocatorDefault, kSecECDSAAlgorithmID,
79                                                           newKey, newParameters, error,
80                                                           CFDataGetBytePtr(derparms), CFDataGetPastEndPtr(derparms));
81
82    if (parse_end == CFDataGetPastEndPtr(derparms)) return true;
83    return false;
84}
85
86