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 <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>
27 #include <utilities/der_plist.h>
28 #include <utilities/der_plist_internal.h>
29 #include <corecrypto/ccder.h>
33 #include "SOSCircleDer.h"
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
)
39 CFDictionaryRef theDict
;
40 const uint8_t* result
= der_decode_dictionary(allocator
, mutability
, &theDict
, error
, der
, der_end
);
43 *dictionary
= (CFMutableDictionaryRef
)theDict
;
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
);
53 const uint8_t *sequence_end
;
56 cir
->generation
= NULL
;
58 cir
->applicants
= NULL
;
59 cir
->rejected_applicants
= NULL
;
60 cir
->signatures
= NULL
;
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
));
68 *der_p
= ccder_decode_uint64(&version
, *der_p
, der_end
);
70 require_action_quiet(version
== kOnlyCompatibleVersion
, fail
,
71 SOSCreateError(kSOSErrorIncompatibleCircle
, CFSTR("Bad Circle Version"), NULL
, error
));
73 *der_p
= der_decode_string(allocator
, 0, &cir
->name
, error
, *der_p
, sequence_end
);
74 cir
->generation
= SOSGenCountCreateFromDER(kCFAllocatorDefault
, error
, der_p
, sequence_end
);
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
);
80 *der_p
= der_decode_mutable_dictionary(allocator
, kCFPropertyListMutableContainersAndLeaves
,
81 &cir
->signatures
, error
, *der_p
, sequence_end
);
83 require_action_quiet(*der_p
== sequence_end
, fail
,
84 SOSCreateError(kSOSErrorBadFormat
, CFSTR("Bad Circle DER"), (error
!= NULL
) ? *error
: NULL
, error
));
93 SOSCircleRef
SOSCircleCreateFromData(CFAllocatorRef allocator
, CFDataRef circleData
, CFErrorRef
*error
)
95 size_t size
= CFDataGetLength(circleData
);
96 const uint8_t *der
= CFDataGetBytePtr(circleData
);
97 SOSCircleRef inflated
= SOSCircleCreateFromDER(allocator
, error
, &der
, der
+ size
);
101 size_t SOSCircleGetDEREncodedSize(SOSCircleRef cir
, CFErrorRef
*error
) {
102 SOSCircleAssertStable(cir
);
103 size_t total_payload
= 0;
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
, SOSGenCountGetDEREncodedSize(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
);
113 return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE
, total_payload
);
116 SecCFDERCreateError(kSecDERErrorUnknownEncoding
, CFSTR("don't know how to encode"), NULL
, error
);
120 uint8_t* SOSCircleEncodeToDER(SOSCircleRef cir
, CFErrorRef
* error
, const uint8_t* der
, uint8_t* der_end
) {
121 SOSCircleAssertStable(cir
);
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 SOSGenCountEncodeToDER(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
))))))));
133 CFDataRef
SOSCircleCreateIncompatibleCircleDER(CFErrorRef
* error
)
135 size_t total_payload
= 0;
136 size_t encoded_size
= 0;
138 uint8_t* der_end
= 0;
139 CFMutableDataRef result
= NULL
;
141 require_quiet(accumulate_size(&total_payload
, ccder_sizeof_uint64(kAlwaysIncompatibleVersion
)), fail
);
143 encoded_size
= ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE
, total_payload
);
145 result
= CFDataCreateMutableWithScratch(kCFAllocatorDefault
, encoded_size
);
147 der
= CFDataGetMutableBytePtr(result
);
148 der_end
= der
+ CFDataGetLength(result
);
150 der_end
= ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE
, der_end
, der
,
151 ccder_encode_uint64(kAlwaysIncompatibleVersion
, der
, der_end
));
154 if (der
== NULL
|| der
!= der_end
)
155 CFReleaseNull(result
);
161 CFDataRef
SOSCircleCopyEncodedData(SOSCircleRef circle
, CFAllocatorRef allocator
, CFErrorRef
*error
)
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
);