]>
Commit | Line | Data |
---|---|---|
5c19dc3a A |
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 <Security/SecureObjectSync/SOSCircle.h> | |
17 | #include <Security/SecureObjectSync/SOSCirclePriv.h> | |
18 | #include <utilities/SecCFRelease.h> | |
19 | #include <utilities/SecCFWrappers.h> | |
20 | #include <utilities/debugging.h> | |
21 | #include <Security/SecureObjectSync/SOSInternal.h> | |
22 | #include <Security/SecureObjectSync/SOSPeer.h> | |
23 | #include <Security/SecureObjectSync/SOSPeerInfoInternal.h> | |
24 | #include <Security/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 | #include <assert.h> | |
32 | ||
33 | #include "SOSCircleDer.h" | |
34 | ||
35 | static const uint8_t* der_decode_mutable_dictionary(CFAllocatorRef allocator, CFOptionFlags mutability, | |
36 | CFMutableDictionaryRef* dictionary, CFErrorRef *error, | |
37 | const uint8_t* der, const uint8_t *der_end) | |
38 | { | |
39 | CFDictionaryRef theDict; | |
40 | const uint8_t* result = der_decode_dictionary(allocator, mutability, &theDict, error, der, der_end); | |
41 | ||
42 | if (result != NULL) | |
43 | *dictionary = (CFMutableDictionaryRef)theDict; | |
44 | ||
45 | return result; | |
46 | } | |
47 | ||
48 | ||
49 | SOSCircleRef SOSCircleCreateFromDER(CFAllocatorRef allocator, CFErrorRef* error, | |
50 | const uint8_t** der_p, const uint8_t *der_end) { | |
51 | SOSCircleRef cir = CFTypeAllocate(SOSCircle, struct __OpaqueSOSCircle, allocator); | |
52 | ||
53 | const uint8_t *sequence_end; | |
54 | ||
55 | cir->name = NULL; | |
56 | cir->generation = NULL; | |
57 | cir->peers = NULL; | |
58 | cir->applicants = NULL; | |
59 | cir->rejected_applicants = NULL; | |
60 | cir->signatures = NULL; | |
61 | ||
62 | *der_p = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, *der_p, der_end); | |
63 | require_action_quiet(sequence_end != NULL, fail, | |
64 | SOSCreateError(kSOSErrorBadFormat, CFSTR("Bad Circle DER"), (error != NULL) ? *error : NULL, error)); | |
65 | ||
66 | // Version first. | |
67 | uint64_t version = 0; | |
68 | *der_p = ccder_decode_uint64(&version, *der_p, der_end); | |
69 | ||
70 | require_action_quiet(version == kOnlyCompatibleVersion, fail, | |
71 | SOSCreateError(kSOSErrorIncompatibleCircle, CFSTR("Bad Circle Version"), NULL, error)); | |
72 | ||
73 | *der_p = der_decode_string(allocator, 0, &cir->name, error, *der_p, sequence_end); | |
74 | *der_p = der_decode_number(allocator, 0, &cir->generation, error, *der_p, sequence_end); | |
75 | ||
76 | cir->peers = SOSPeerInfoSetCreateFromArrayDER(allocator, &kSOSPeerSetCallbacks, error, der_p, sequence_end); | |
77 | cir->applicants = SOSPeerInfoSetCreateFromArrayDER(allocator, &kSOSPeerSetCallbacks, error, der_p, sequence_end); | |
78 | cir->rejected_applicants = SOSPeerInfoSetCreateFromArrayDER(allocator, &kSOSPeerSetCallbacks, error, der_p, sequence_end); | |
79 | ||
80 | *der_p = der_decode_mutable_dictionary(allocator, kCFPropertyListMutableContainersAndLeaves, | |
81 | &cir->signatures, error, *der_p, sequence_end); | |
82 | ||
83 | require_action_quiet(*der_p == sequence_end, fail, | |
84 | SOSCreateError(kSOSErrorBadFormat, CFSTR("Bad Circle DER"), (error != NULL) ? *error : NULL, error)); | |
85 | ||
86 | return cir; | |
87 | ||
88 | fail: | |
89 | CFReleaseNull(cir); | |
90 | return NULL; | |
91 | } | |
92 | ||
93 | SOSCircleRef SOSCircleCreateFromData(CFAllocatorRef allocator, CFDataRef circleData, CFErrorRef *error) | |
94 | { | |
95 | size_t size = CFDataGetLength(circleData); | |
96 | const uint8_t *der = CFDataGetBytePtr(circleData); | |
97 | SOSCircleRef inflated = SOSCircleCreateFromDER(allocator, error, &der, der + size); | |
98 | return inflated; | |
99 | } | |
100 | ||
101 | size_t SOSCircleGetDEREncodedSize(SOSCircleRef cir, CFErrorRef *error) { | |
102 | SOSCircleAssertStable(cir); | |
103 | size_t total_payload = 0; | |
104 | ||
105 | require_quiet(accumulate_size(&total_payload, ccder_sizeof_uint64(kOnlyCompatibleVersion)), fail); | |
106 | require_quiet(accumulate_size(&total_payload, der_sizeof_string(cir->name, error)), fail); | |
107 | require_quiet(accumulate_size(&total_payload, der_sizeof_number(cir->generation, error)), fail); | |
108 | require_quiet(accumulate_size(&total_payload, SOSPeerInfoSetGetDEREncodedArraySize(cir->peers, error)), fail); | |
109 | require_quiet(accumulate_size(&total_payload, SOSPeerInfoSetGetDEREncodedArraySize(cir->applicants, error)), fail); | |
110 | require_quiet(accumulate_size(&total_payload, SOSPeerInfoSetGetDEREncodedArraySize(cir->rejected_applicants, error)), fail); | |
111 | require_quiet(accumulate_size(&total_payload, der_sizeof_dictionary((CFDictionaryRef) cir->signatures, error)), fail); | |
112 | ||
113 | return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, total_payload); | |
114 | ||
115 | fail: | |
116 | SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("don't know how to encode"), NULL, error); | |
117 | return 0; | |
118 | } | |
119 | ||
120 | uint8_t* SOSCircleEncodeToDER(SOSCircleRef cir, CFErrorRef* error, const uint8_t* der, uint8_t* der_end) { | |
121 | SOSCircleAssertStable(cir); | |
122 | ||
123 | return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, | |
124 | ccder_encode_uint64(kOnlyCompatibleVersion, der, | |
125 | der_encode_string(cir->name, error, der, | |
126 | der_encode_number(cir->generation, error, der, | |
127 | SOSPeerInfoSetEncodeToArrayDER(cir->peers, error, der, | |
128 | SOSPeerInfoSetEncodeToArrayDER(cir->applicants, error, der, | |
129 | SOSPeerInfoSetEncodeToArrayDER(cir->rejected_applicants, error, der, | |
130 | der_encode_dictionary((CFDictionaryRef) cir->signatures, error, der, der_end)))))))); | |
131 | } | |
132 | ||
133 | CFDataRef SOSCircleCreateIncompatibleCircleDER(CFErrorRef* error) | |
134 | { | |
135 | size_t total_payload = 0; | |
136 | size_t encoded_size = 0; | |
137 | uint8_t* der = 0; | |
138 | uint8_t* der_end = 0; | |
139 | CFMutableDataRef result = NULL; | |
140 | ||
141 | require_quiet(accumulate_size(&total_payload, ccder_sizeof_uint64(kAlwaysIncompatibleVersion)), fail); | |
142 | ||
143 | encoded_size = ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, total_payload); | |
144 | ||
145 | result = CFDataCreateMutableWithScratch(kCFAllocatorDefault, encoded_size); | |
146 | ||
147 | der = CFDataGetMutableBytePtr(result); | |
148 | der_end = der + CFDataGetLength(result); | |
149 | ||
150 | der_end = ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, | |
151 | ccder_encode_uint64(kAlwaysIncompatibleVersion, der, der_end)); | |
152 | ||
153 | fail: | |
154 | if (der == NULL || der != der_end) | |
155 | CFReleaseNull(result); | |
156 | ||
157 | return result; | |
158 | } | |
159 | ||
160 | ||
161 | CFDataRef SOSCircleCopyEncodedData(SOSCircleRef circle, CFAllocatorRef allocator, CFErrorRef *error) | |
162 | { | |
fa7225c8 A |
163 | return CFDataCreateWithDER(kCFAllocatorDefault, SOSCircleGetDEREncodedSize(circle, error), ^uint8_t*(size_t size, uint8_t *buffer) { |
164 | return SOSCircleEncodeToDER(circle, error, buffer, (uint8_t *) buffer + size); | |
165 | }); | |
5c19dc3a | 166 | } |