]> git.saurik.com Git - apple/security.git/blob - keychain/SecureObjectSync/SOSCircleDer.c
Security-59754.41.1.tar.gz
[apple/security.git] / keychain / SecureObjectSync / SOSCircleDer.c
1 //
2 // SOSCircleDer.c
3 // sec
4 //
5 // Created by Richard Murphy on 1/22/15.
6 //
7 //
8
9 #include <stdio.h>
10 #include <AssertMacros.h>
11 #include <CoreFoundation/CoreFoundation.h>
12 #include <CoreFoundation/CoreFoundation.h>
13 #include <CoreFoundation/CFArray.h>
14 #include <Security/SecureObjectSync/SOSCloudCircle.h>
15 #include <Security/SecureObjectSync/SOSCloudCircleInternal.h>
16 #include "keychain/SecureObjectSync/SOSCircle.h"
17 #include "keychain/SecureObjectSync/SOSCirclePriv.h"
18 #include <utilities/SecCFRelease.h>
19 #include <utilities/SecCFWrappers.h>
20 #include <utilities/debugging.h>
21 #include "keychain/SecureObjectSync/SOSInternal.h"
22 #include "keychain/SecureObjectSync/SOSPeer.h"
23 #include "keychain/SecureObjectSync/SOSPeerInfoInternal.h"
24 #include "keychain/SecureObjectSync/SOSPeerInfoCollections.h"
25 #include <Security/SecFramework.h>
26
27 #include <utilities/der_plist.h>
28 #include <utilities/der_plist_internal.h>
29 #include <corecrypto/ccder.h>
30 #include <stdlib.h>
31
32 #include "SOSCircleDer.h"
33
34 SOSCircleRef SOSCircleCreateFromDER(CFAllocatorRef allocator, CFErrorRef* error,
35 const uint8_t** der_p, const uint8_t *der_end) {
36 SOSCircleRef cir = CFTypeAllocate(SOSCircle, struct __OpaqueSOSCircle, allocator);
37
38 const uint8_t *sequence_end;
39
40 cir->name = NULL;
41 cir->generation = NULL;
42 cir->peers = NULL;
43 cir->applicants = NULL;
44 cir->rejected_applicants = NULL;
45 cir->signatures = NULL;
46
47 *der_p = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, *der_p, der_end);
48 require_action_quiet(sequence_end != NULL, fail,
49 SOSCreateError(kSOSErrorBadFormat, CFSTR("Bad Circle DER"), (error != NULL) ? *error : NULL, error));
50
51 // Version first.
52 uint64_t version = 0;
53 *der_p = ccder_decode_uint64(&version, *der_p, der_end);
54
55 require_action_quiet(version == kOnlyCompatibleVersion, fail,
56 SOSCreateError(kSOSErrorIncompatibleCircle, CFSTR("Bad Circle Version"), NULL, error));
57
58 *der_p = der_decode_string(allocator, &cir->name, error, *der_p, sequence_end);
59 cir->generation = SOSGenCountCreateFromDER(kCFAllocatorDefault, error, der_p, sequence_end);
60
61 cir->peers = SOSPeerInfoSetCreateFromArrayDER(allocator, &kSOSPeerSetCallbacks, error, der_p, sequence_end);
62 cir->applicants = SOSPeerInfoSetCreateFromArrayDER(allocator, &kSOSPeerSetCallbacks, error, der_p, sequence_end);
63 cir->rejected_applicants = SOSPeerInfoSetCreateFromArrayDER(allocator, &kSOSPeerSetCallbacks, error, der_p, sequence_end);
64
65 CFDictionaryRef tmp = NULL;
66 *der_p = der_decode_dictionary(allocator, &tmp, error, *der_p, sequence_end);
67 cir->signatures = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, tmp);
68 CFReleaseNull(tmp);
69
70 require_action_quiet(*der_p == sequence_end, fail,
71 SOSCreateError(kSOSErrorBadFormat, CFSTR("Bad Circle DER"), (error != NULL) ? *error : NULL, error));
72
73 return cir;
74
75 fail:
76 CFReleaseNull(cir);
77 return NULL;
78 }
79
80 SOSCircleRef SOSCircleCreateFromData(CFAllocatorRef allocator, CFDataRef circleData, CFErrorRef *error)
81 {
82 size_t size = CFDataGetLength(circleData);
83 const uint8_t *der = CFDataGetBytePtr(circleData);
84 SOSCircleRef inflated = SOSCircleCreateFromDER(allocator, error, &der, der + size);
85 return inflated;
86 }
87
88 size_t SOSCircleGetDEREncodedSize(SOSCircleRef cir, CFErrorRef *error) {
89 SOSCircleAssertStable(cir);
90 size_t total_payload = 0;
91
92 require_quiet(accumulate_size(&total_payload, ccder_sizeof_uint64(kOnlyCompatibleVersion)), fail);
93 require_quiet(accumulate_size(&total_payload, der_sizeof_string(cir->name, error)), fail);
94 require_quiet(accumulate_size(&total_payload, SOSGenCountGetDEREncodedSize(cir->generation, error)), fail);
95 require_quiet(accumulate_size(&total_payload, SOSPeerInfoSetGetDEREncodedArraySize(cir->peers, error)), fail);
96 require_quiet(accumulate_size(&total_payload, SOSPeerInfoSetGetDEREncodedArraySize(cir->applicants, error)), fail);
97 require_quiet(accumulate_size(&total_payload, SOSPeerInfoSetGetDEREncodedArraySize(cir->rejected_applicants, error)), fail);
98 require_quiet(accumulate_size(&total_payload, der_sizeof_dictionary((CFDictionaryRef) cir->signatures, error)), fail);
99
100 return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, total_payload);
101
102 fail:
103 SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("don't know how to encode"), NULL, error);
104 return 0;
105 }
106
107 uint8_t* SOSCircleEncodeToDER(SOSCircleRef cir, CFErrorRef* error, const uint8_t* der, uint8_t* der_end) {
108 SOSCircleAssertStable(cir);
109
110 return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der,
111 ccder_encode_uint64(kOnlyCompatibleVersion, der,
112 der_encode_string(cir->name, error, der,
113 SOSGenCountEncodeToDER(cir->generation, error, der,
114 SOSPeerInfoSetEncodeToArrayDER(cir->peers, error, der,
115 SOSPeerInfoSetEncodeToArrayDER(cir->applicants, error, der,
116 SOSPeerInfoSetEncodeToArrayDER(cir->rejected_applicants, error, der,
117 der_encode_dictionary((CFDictionaryRef) cir->signatures, error, der, der_end))))))));
118 }
119
120 CFDataRef SOSCircleCreateIncompatibleCircleDER(CFErrorRef* error)
121 {
122 size_t total_payload = 0;
123 size_t encoded_size = 0;
124 uint8_t* der = 0;
125 uint8_t* der_end = 0;
126 CFMutableDataRef result = NULL;
127
128 require_quiet(accumulate_size(&total_payload, ccder_sizeof_uint64(kAlwaysIncompatibleVersion)), fail);
129
130 encoded_size = ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, total_payload);
131
132 result = CFDataCreateMutableWithScratch(kCFAllocatorDefault, encoded_size);
133
134 der = CFDataGetMutableBytePtr(result);
135 der_end = der + CFDataGetLength(result);
136
137 der_end = ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der,
138 ccder_encode_uint64(kAlwaysIncompatibleVersion, der, der_end));
139
140 fail:
141 if (der == NULL || der != der_end)
142 CFReleaseNull(result);
143
144 return result;
145 }
146
147
148 CFDataRef SOSCircleCopyEncodedData(SOSCircleRef circle, CFAllocatorRef allocator, CFErrorRef *error)
149 {
150 return CFDataCreateWithDER(kCFAllocatorDefault, SOSCircleGetDEREncodedSize(circle, error), ^uint8_t*(size_t size, uint8_t *buffer) {
151 return SOSCircleEncodeToDER(circle, error, buffer, (uint8_t *) buffer + size);
152 });
153 }
154
155 //
156 // Encodes data or a zero length data
157 //
158 size_t der_sizeof_data_or_null(CFDataRef data, CFErrorRef* error)
159 {
160 if (data) {
161 return der_sizeof_data(data, error);
162 } else {
163 return der_sizeof_null(kCFNull, error);
164 }
165 }
166
167 uint8_t* der_encode_data_or_null(CFDataRef data, CFErrorRef* error, const uint8_t* der, uint8_t* der_end)
168 {
169 if (data) {
170 return der_encode_data(data, error, der, der_end);
171 } else {
172 return der_encode_null(kCFNull, error, der, der_end);
173 }
174 }
175
176
177 const uint8_t* der_decode_data_or_null(CFAllocatorRef allocator, CFDataRef* data,
178 CFErrorRef* error,
179 const uint8_t* der, const uint8_t* der_end)
180 {
181 CFTypeRef value = NULL;
182 der = der_decode_plist(allocator, &value, error, der, der_end);
183 if (value && CFGetTypeID(value) != CFDataGetTypeID()) {
184 CFReleaseNull(value);
185 }
186 if (data) {
187 *data = value;
188 }
189 return der;
190 }
191