5 // Created by Richard Murphy on 2/9/15.
9 #include <AssertMacros.h>
10 #include <SOSPeerInfoDER.h>
12 #include <Security/SecureObjectSync/SOSPeerInfo.h>
13 #include <Security/SecureObjectSync/SOSPeerInfoInternal.h>
14 #include <Security/SecureObjectSync/SOSPeerInfoPriv.h>
15 #include <Security/SecureObjectSync/SOSPeerInfoV2.h>
16 #include <Security/SecureObjectSync/SOSInternal.h>
18 #include <utilities/der_plist.h>
19 #include <utilities/der_plist_internal.h>
20 #include <corecrypto/ccder.h>
21 #include <utilities/der_date.h>
23 #include <utilities/SecCFError.h>
25 size_t SOSPeerInfoGetDEREncodedSize(SOSPeerInfoRef peer
, CFErrorRef
*error
) {
26 size_t plist_size
= der_sizeof_plist(peer
->description
, error
);
30 size_t signature_size
= der_sizeof_data(peer
->signature
, error
);
31 if (signature_size
== 0)
34 return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE
,
35 plist_size
+ signature_size
);
38 uint8_t* SOSPeerInfoEncodeToDER(SOSPeerInfoRef peer
, CFErrorRef
* error
, const uint8_t* der
, uint8_t* der_end
) {
39 if(peer
->version
>= 2) SOSPeerInfoPackV2Data(peer
);
40 return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE
, der_end
, der
,
41 der_encode_plist(peer
->description
, error
, der
,
42 der_encode_data(peer
->signature
, error
, der
, der_end
)));
45 CFDataRef
SOSPeerInfoCopyEncodedData(SOSPeerInfoRef peer
, CFAllocatorRef allocator
, CFErrorRef
*error
) {
46 size_t size
= SOSPeerInfoGetDEREncodedSize(peer
, error
);
47 if (size
== 0) return NULL
;
50 uint8_t* start
= SOSPeerInfoEncodeToDER(peer
, error
, buffer
, buffer
+ sizeof(buffer
));
51 CFDataRef result
= CFDataCreate(kCFAllocatorDefault
, start
, size
);
57 SOSPeerInfoRef
SOSPeerInfoCreateFromDER(CFAllocatorRef allocator
, CFErrorRef
* error
,
58 const uint8_t** der_p
, const uint8_t *der_end
) {
59 SOSPeerInfoRef pi
= SOSPeerInfoAllocate(allocator
);
60 SecKeyRef pubKey
= NULL
;
61 const uint8_t *sequence_end
;
63 CFPropertyListRef pl
= NULL
;
66 pi
->version
= 0; // TODO: Encode this in the DER
67 *der_p
= ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE
, &sequence_end
, *der_p
, der_end
);
68 *der_p
= der_decode_plist(allocator
, kCFPropertyListImmutable
, &pl
, error
, *der_p
, sequence_end
);
69 *der_p
= der_decode_data(allocator
, kCFPropertyListImmutable
, &pi
->signature
, error
, *der_p
, sequence_end
);
71 if (*der_p
== NULL
|| *der_p
!= sequence_end
) {
72 SOSCreateError(kSOSErrorBadFormat
, CFSTR("Bad Format of Peer Info DER"), NULL
, error
);
76 if (CFGetTypeID(pl
) != CFDictionaryGetTypeID()) {
77 CFStringRef description
= CFCopyTypeIDDescription(CFGetTypeID(pl
));
78 SOSCreateErrorWithFormat(kSOSErrorUnexpectedType
, NULL
, error
, NULL
,
79 CFSTR("Expected dictionary got %@"), description
);
80 CFReleaseSafe(description
);
84 pi
->description
= (CFMutableDictionaryRef
) pl
;
85 CFRetain(pi
->description
);
88 CFNumberRef versionNumber
= CFDictionaryGetValue(pi
->description
, sVersionKey
);
91 if (CFGetTypeID(versionNumber
) != CFNumberGetTypeID()) {
92 CFStringRef description
= CFCopyTypeIDDescription(CFGetTypeID(versionNumber
));
93 SOSCreateErrorWithFormat(kSOSErrorUnexpectedType
, NULL
, error
, NULL
,
94 CFSTR("Expected (version) number got %@"), description
);
95 CFReleaseSafe(description
);
98 CFNumberGetValue(versionNumber
, kCFNumberCFIndexType
, &pi
->version
);
101 CFDictionaryRef gestalt
= CFDictionaryGetValue(pi
->description
, sGestaltKey
);
103 if (gestalt
== NULL
) {
104 SOSCreateErrorWithFormat(kSOSErrorUnexpectedType
, NULL
, error
, NULL
,
105 CFSTR("gestalt key missing"));
109 if (!isDictionary(gestalt
)) {
110 CFStringRef description
= CFCopyTypeIDDescription(CFGetTypeID(gestalt
));
111 SOSCreateErrorWithFormat(kSOSErrorUnexpectedType
, NULL
, error
, NULL
,
112 CFSTR("Expected dictionary got %@"), description
);
113 CFReleaseSafe(description
);
117 pi
->gestalt
= gestalt
;
118 CFRetain(pi
->gestalt
);
120 pubKey
= SOSPeerInfoCopyPubKey(pi
);
121 require_quiet(pubKey
, fail
);
123 pi
->id
= SOSCopyIDOfKey(pubKey
, error
);
124 require_quiet(pi
->id
, fail
);
126 if(pi
->version
>= 2) SOSPeerInfoExpandV2Data(pi
, error
);
128 if(!SOSPeerInfoVerify(pi
, error
)) {
129 SOSCreateErrorWithFormat(kSOSErrorBadSignature
, NULL
, error
, NULL
, CFSTR("Signature doesn't validate"));
131 secerror("Can't validate PeerInfo: %@", *error
);
135 CFReleaseNull(pubKey
);
141 CFReleaseNull(pubKey
);
146 SOSPeerInfoRef
SOSPeerInfoCreateFromData(CFAllocatorRef allocator
, CFErrorRef
* error
,
147 CFDataRef peerinfo_data
) {
148 const uint8_t *der
= CFDataGetBytePtr(peerinfo_data
);
149 CFIndex len
= CFDataGetLength(peerinfo_data
);
150 return SOSPeerInfoCreateFromDER(NULL
, error
, &der
, der
+len
);