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 return CFDataCreateWithDER(kCFAllocatorDefault
, SOSPeerInfoGetDEREncodedSize(peer
, error
), ^uint8_t*(size_t size
, uint8_t *buffer
) {
47 return SOSPeerInfoEncodeToDER(peer
, error
, buffer
, (uint8_t *) buffer
+ size
);
53 SOSPeerInfoRef
SOSPeerInfoCreateFromDER(CFAllocatorRef allocator
, CFErrorRef
* error
,
54 const uint8_t** der_p
, const uint8_t *der_end
) {
55 SOSPeerInfoRef pi
= SOSPeerInfoAllocate(allocator
);
56 SecKeyRef pubKey
= NULL
;
57 const uint8_t *sequence_end
;
59 CFPropertyListRef pl
= NULL
;
62 pi
->version
= 0; // TODO: Encode this in the DER
63 *der_p
= ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE
, &sequence_end
, *der_p
, der_end
);
64 *der_p
= der_decode_plist(allocator
, kCFPropertyListImmutable
, &pl
, error
, *der_p
, sequence_end
);
65 *der_p
= der_decode_data(allocator
, kCFPropertyListImmutable
, &pi
->signature
, error
, *der_p
, sequence_end
);
67 if (*der_p
== NULL
|| *der_p
!= sequence_end
) {
68 SOSCreateError(kSOSErrorBadFormat
, CFSTR("Bad Format of Peer Info DER"), NULL
, error
);
72 if (CFGetTypeID(pl
) != CFDictionaryGetTypeID()) {
73 CFStringRef description
= CFCopyTypeIDDescription(CFGetTypeID(pl
));
74 SOSCreateErrorWithFormat(kSOSErrorUnexpectedType
, NULL
, error
, NULL
,
75 CFSTR("Expected dictionary got %@"), description
);
76 CFReleaseSafe(description
);
80 pi
->description
= (CFMutableDictionaryRef
) pl
;
81 CFRetain(pi
->description
);
84 CFNumberRef versionNumber
= CFDictionaryGetValue(pi
->description
, sVersionKey
);
87 if (CFGetTypeID(versionNumber
) != CFNumberGetTypeID()) {
88 CFStringRef description
= CFCopyTypeIDDescription(CFGetTypeID(versionNumber
));
89 SOSCreateErrorWithFormat(kSOSErrorUnexpectedType
, NULL
, error
, NULL
,
90 CFSTR("Expected (version) number got %@"), description
);
91 CFReleaseSafe(description
);
94 CFNumberGetValue(versionNumber
, kCFNumberCFIndexType
, &pi
->version
);
97 CFDictionaryRef gestalt
= CFDictionaryGetValue(pi
->description
, sGestaltKey
);
99 if (gestalt
== NULL
) {
100 SOSCreateErrorWithFormat(kSOSErrorUnexpectedType
, NULL
, error
, NULL
,
101 CFSTR("gestalt key missing"));
105 if (!isDictionary(gestalt
)) {
106 CFStringRef description
= CFCopyTypeIDDescription(CFGetTypeID(gestalt
));
107 SOSCreateErrorWithFormat(kSOSErrorUnexpectedType
, NULL
, error
, NULL
,
108 CFSTR("Expected dictionary got %@"), description
);
109 CFReleaseSafe(description
);
113 pi
->gestalt
= gestalt
;
114 CFRetain(pi
->gestalt
);
116 pubKey
= SOSPeerInfoCopyPubKey(pi
, error
);
117 require_quiet(pubKey
, fail
);
119 pi
->id
= SOSCopyIDOfKey(pubKey
, error
);
120 require_quiet(pi
->id
, fail
);
122 if(pi
->version
>= 2) SOSPeerInfoExpandV2Data(pi
, error
);
124 if(!SOSPeerInfoVerify(pi
, error
)) {
125 SOSCreateErrorWithFormat(kSOSErrorBadSignature
, NULL
, error
, NULL
, CFSTR("Signature doesn't validate"));
127 secerror("Can't validate PeerInfo: %@", *error
);
131 CFReleaseNull(pubKey
);
137 CFReleaseNull(pubKey
);
142 SOSPeerInfoRef
SOSPeerInfoCreateFromData(CFAllocatorRef allocator
, CFErrorRef
* error
,
143 CFDataRef peerinfo_data
) {
144 const uint8_t *der
= CFDataGetBytePtr(peerinfo_data
);
145 CFIndex len
= CFDataGetLength(peerinfo_data
);
146 return SOSPeerInfoCreateFromDER(NULL
, error
, &der
, der
+len
);