8 + // Created by Richard Murphy on 2/9/15.
12 + #include <AssertMacros.h>
13 + #include "SOSPeerInfoDER.h"
15 + #include <SecureObjectSync/SOSPeerInfo.h>
16 + #include <SecureObjectSync/SOSPeerInfoInternal.h>
17 + #include <SecureObjectSync/SOSPeerInfoPriv.h>
18 + #include <SecureObjectSync/SOSPeerInfoV2.h>
19 + #include <SecureObjectSync/SOSInternal.h>
21 + #include <utilities/der_plist.h>
22 + #include <utilities/der_plist_internal.h>
23 + #include <corecrypto/ccder.h>
24 + #include <utilities/der_date.h>
26 + #include <utilities/SecCFError.h>
28 + size_t SOSPeerInfoGetDEREncodedSize(SOSPeerInfoRef peer
, CFErrorRef
*error
) {
29 + size_t plist_size
= der_sizeof_plist(peer
->description
, error
);
30 + if (plist_size
== 0)
33 + size_t signature_size
= der_sizeof_data(peer
->signature
, error
);
34 + if (signature_size
== 0)
37 + return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE
,
38 + plist_size
+ signature_size
);
41 + uint8_t* SOSPeerInfoEncodeToDER(SOSPeerInfoRef peer
, CFErrorRef
* error
, const uint8_t* der
, uint8_t* der_end
) {
42 + if(peer
->version
>= 2) SOSPeerInfoPackV2Data(peer
);
43 + return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE
, der_end
, der
,
44 + der_encode_plist(peer
->description
, error
, der
,
45 + der_encode_data(peer
->signature
, error
, der
, der_end
)));
48 + CFDataRef
SOSPeerInfoCopyEncodedData(SOSPeerInfoRef peer
, CFAllocatorRef allocator
, CFErrorRef
*error
) {
49 + size_t size
= SOSPeerInfoGetDEREncodedSize(peer
, error
);
50 + if (size
== 0) return NULL
;
52 + uint8_t buffer
[size
];
53 + uint8_t* start
= SOSPeerInfoEncodeToDER(peer
, error
, buffer
, buffer
+ sizeof(buffer
));
54 + CFDataRef result
= CFDataCreate(kCFAllocatorDefault
, start
, size
);
60 + SOSPeerInfoRef
SOSPeerInfoCreateFromDER(CFAllocatorRef allocator
, CFErrorRef
* error
,
61 + const uint8_t** der_p
, const uint8_t *der_end
) {
62 + SOSPeerInfoRef pi
= SOSPeerInfoAllocate(allocator
);
63 + SecKeyRef pubKey
= NULL
;
64 + const uint8_t *sequence_end
;
66 + CFPropertyListRef pl
= NULL
;
69 + pi
->version
= 0; // TODO: Encode this in the DER
70 + *der_p
= ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE
, &sequence_end
, *der_p
, der_end
);
71 + *der_p
= der_decode_plist(allocator
, kCFPropertyListImmutable
, &pl
, error
, *der_p
, sequence_end
);
72 + *der_p
= der_decode_data(allocator
, kCFPropertyListImmutable
, &pi
->signature
, error
, *der_p
, sequence_end
);
74 + if (*der_p
== NULL
|| *der_p
!= sequence_end
) {
75 + SOSCreateError(kSOSErrorBadFormat
, CFSTR("Bad Format of Peer Info DER"), NULL
, error
);
79 + if (CFGetTypeID(pl
) != CFDictionaryGetTypeID()) {
80 + CFStringRef description
= CFCopyTypeIDDescription(CFGetTypeID(pl
));
81 + SOSCreateErrorWithFormat(kSOSErrorUnexpectedType
, NULL
, error
, NULL
,
82 + CFSTR("Expected dictionary got %@"), description
);
83 + CFReleaseSafe(description
);
87 + pi
->description
= (CFMutableDictionaryRef
) pl
;
88 + CFRetain(pi
->description
);
91 + CFNumberRef versionNumber
= CFDictionaryGetValue(pi
->description
, sVersionKey
);
93 + if (versionNumber
) {
94 + if (CFGetTypeID(versionNumber
) != CFNumberGetTypeID()) {
95 + CFStringRef description
= CFCopyTypeIDDescription(CFGetTypeID(versionNumber
));
96 + SOSCreateErrorWithFormat(kSOSErrorUnexpectedType
, NULL
, error
, NULL
,
97 + CFSTR("Expected (version) number got %@"), description
);
98 + CFReleaseSafe(description
);
101 + CFNumberGetValue(versionNumber
, kCFNumberCFIndexType
, &pi
->version
);
104 + CFDictionaryRef gestalt
= CFDictionaryGetValue(pi
->description
, sGestaltKey
);
106 + if (gestalt
== NULL
) {
107 + SOSCreateErrorWithFormat(kSOSErrorUnexpectedType
, NULL
, error
, NULL
,
108 + CFSTR("gestalt key missing"));
112 + if (!isDictionary(gestalt
)) {
113 + CFStringRef description
= CFCopyTypeIDDescription(CFGetTypeID(gestalt
));
114 + SOSCreateErrorWithFormat(kSOSErrorUnexpectedType
, NULL
, error
, NULL
,
115 + CFSTR("Expected dictionary got %@"), description
);
116 + CFReleaseSafe(description
);
120 + pi
->gestalt
= gestalt
;
121 + CFRetain(pi
->gestalt
);
123 + pubKey
= SOSPeerInfoCopyPubKey(pi
);
124 + require_quiet(pubKey
, fail
);
126 + pi
->id
= SOSCopyIDOfKey(pubKey
, error
);
127 + require_quiet(pi
->id
, fail
);
129 + if(pi
->version
>= 2) SOSPeerInfoExpandV2Data(pi
, error
);
131 + if(!SOSPeerInfoVerify(pi
, error
)) {
132 + SOSCreateErrorWithFormat(kSOSErrorBadSignature
, NULL
, error
, NULL
, CFSTR("Signature doesn't validate"));
134 + secerror("Can't validate PeerInfo: %@", *error
);
138 + CFReleaseNull(pubKey
);
144 + CFReleaseNull(pubKey
);
149 + SOSPeerInfoRef
SOSPeerInfoCreateFromData(CFAllocatorRef allocator
, CFErrorRef
* error
,
150 + CFDataRef peerinfo_data
) {
151 + const uint8_t *der
= CFDataGetBytePtr(peerinfo_data
);
152 + CFIndex len
= CFDataGetLength(peerinfo_data
);
153 + return SOSPeerInfoCreateFromDER(NULL
, error
, &der
, der
+len
);