5 // Created by Richard Murphy on 1/22/15.
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>
27 #include <utilities/der_plist.h>
28 #include <utilities/der_plist_internal.h>
29 #include <corecrypto/ccder.h>
32 #include "SOSCircleDer.h"
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
);
38 const uint8_t *sequence_end
;
41 cir
->generation
= NULL
;
43 cir
->applicants
= NULL
;
44 cir
->rejected_applicants
= NULL
;
45 cir
->signatures
= NULL
;
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
));
53 *der_p
= ccder_decode_uint64(&version
, *der_p
, der_end
);
55 require_action_quiet(version
== kOnlyCompatibleVersion
, fail
,
56 SOSCreateError(kSOSErrorIncompatibleCircle
, CFSTR("Bad Circle Version"), NULL
, error
));
58 *der_p
= der_decode_string(allocator
, &cir
->name
, error
, *der_p
, sequence_end
);
59 cir
->generation
= SOSGenCountCreateFromDER(kCFAllocatorDefault
, error
, der_p
, sequence_end
);
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
);
65 CFDictionaryRef tmp
= NULL
;
66 *der_p
= der_decode_dictionary(allocator
, &tmp
, error
, *der_p
, sequence_end
);
67 cir
->signatures
= CFDictionaryCreateMutableCopy(kCFAllocatorDefault
, 0, tmp
);
70 require_action_quiet(*der_p
== sequence_end
, fail
,
71 SOSCreateError(kSOSErrorBadFormat
, CFSTR("Bad Circle DER"), (error
!= NULL
) ? *error
: NULL
, error
));
80 SOSCircleRef
SOSCircleCreateFromData(CFAllocatorRef allocator
, CFDataRef circleData
, CFErrorRef
*error
)
82 size_t size
= CFDataGetLength(circleData
);
83 const uint8_t *der
= CFDataGetBytePtr(circleData
);
84 SOSCircleRef inflated
= SOSCircleCreateFromDER(allocator
, error
, &der
, der
+ size
);
88 size_t SOSCircleGetDEREncodedSize(SOSCircleRef cir
, CFErrorRef
*error
) {
89 SOSCircleAssertStable(cir
);
90 size_t total_payload
= 0;
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
);
100 return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE
, total_payload
);
103 SecCFDERCreateError(kSecDERErrorUnknownEncoding
, CFSTR("don't know how to encode"), NULL
, error
);
107 uint8_t* SOSCircleEncodeToDER(SOSCircleRef cir
, CFErrorRef
* error
, const uint8_t* der
, uint8_t* der_end
) {
108 SOSCircleAssertStable(cir
);
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
))))))));
120 CFDataRef
SOSCircleCreateIncompatibleCircleDER(CFErrorRef
* error
)
122 size_t total_payload
= 0;
123 size_t encoded_size
= 0;
125 uint8_t* der_end
= 0;
126 CFMutableDataRef result
= NULL
;
128 require_quiet(accumulate_size(&total_payload
, ccder_sizeof_uint64(kAlwaysIncompatibleVersion
)), fail
);
130 encoded_size
= ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE
, total_payload
);
132 result
= CFDataCreateMutableWithScratch(kCFAllocatorDefault
, encoded_size
);
134 der
= CFDataGetMutableBytePtr(result
);
135 der_end
= der
+ CFDataGetLength(result
);
137 der_end
= ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE
, der_end
, der
,
138 ccder_encode_uint64(kAlwaysIncompatibleVersion
, der
, der_end
));
141 if (der
== NULL
|| der
!= der_end
)
142 CFReleaseNull(result
);
148 CFDataRef
SOSCircleCopyEncodedData(SOSCircleRef circle
, CFAllocatorRef allocator
, CFErrorRef
*error
)
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
);
156 // Encodes data or a zero length data
158 size_t der_sizeof_data_or_null(CFDataRef data
, CFErrorRef
* error
)
161 return der_sizeof_data(data
, error
);
163 return der_sizeof_null(kCFNull
, error
);
167 uint8_t* der_encode_data_or_null(CFDataRef data
, CFErrorRef
* error
, const uint8_t* der
, uint8_t* der_end
)
170 return der_encode_data(data
, error
, der
, der_end
);
172 return der_encode_null(kCFNull
, error
, der
, der_end
);
177 const uint8_t* der_decode_data_or_null(CFAllocatorRef allocator
, CFDataRef
* data
,
179 const uint8_t* der
, const uint8_t* der_end
)
181 CFTypeRef value
= NULL
;
182 der
= der_decode_plist(allocator
, &value
, error
, der
, der_end
);
183 if (value
&& CFGetTypeID(value
) != CFDataGetTypeID()) {
184 CFReleaseNull(value
);