]> git.saurik.com Git - apple/security.git/blob - OSX/sec/SOSCircle/SecureObjectSync/SOSPeerInfoDER.m
Security-58286.1.32.tar.gz
[apple/security.git] / OSX / sec / SOSCircle / SecureObjectSync / SOSPeerInfoDER.m
1 //
2 // SOSPeerInfoDER.c
3 // sec
4 //
5 // Created by Richard Murphy on 2/9/15.
6 //
7 //
8
9 #include <AssertMacros.h>
10 #include <SOSPeerInfoDER.h>
11
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>
17
18 #include <utilities/der_plist.h>
19 #include <utilities/der_plist_internal.h>
20 #include <corecrypto/ccder.h>
21 #include <utilities/der_date.h>
22
23 #include <utilities/SecCFError.h>
24
25 size_t SOSPeerInfoGetDEREncodedSize(SOSPeerInfoRef peer, CFErrorRef *error) {
26 size_t plist_size = der_sizeof_plist(peer->description, error);
27 if (plist_size == 0)
28 return 0;
29
30 size_t signature_size = der_sizeof_data(peer->signature, error);
31 if (signature_size == 0)
32 return 0;
33
34 return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE,
35 plist_size + signature_size);
36 }
37
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)));
43 }
44
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);
48 });
49 }
50
51
52
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;
58
59 CFPropertyListRef pl = NULL;
60
61 pi->gestalt = 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);
66
67 if (*der_p == NULL || *der_p != sequence_end) {
68 SOSCreateError(kSOSErrorBadFormat, CFSTR("Bad Format of Peer Info DER"), NULL, error);
69 goto fail;
70 }
71
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);
77 goto fail;
78 }
79
80 pi->description = (CFMutableDictionaryRef) pl;
81 CFRetain(pi->description);
82 CFReleaseNull(pl);
83
84 CFNumberRef versionNumber = CFDictionaryGetValue(pi->description, sVersionKey);
85
86 if (versionNumber) {
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);
92 goto fail;
93 }
94 CFNumberGetValue(versionNumber, kCFNumberCFIndexType, &pi->version);
95 }
96
97 CFDictionaryRef gestalt = CFDictionaryGetValue(pi->description, sGestaltKey);
98
99 if (gestalt == NULL) {
100 SOSCreateErrorWithFormat(kSOSErrorUnexpectedType, NULL, error, NULL,
101 CFSTR("gestalt key missing"));
102 goto fail;
103 }
104
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);
110 goto fail;
111 }
112
113 pi->gestalt = gestalt;
114 CFRetain(pi->gestalt);
115
116 pubKey = SOSPeerInfoCopyPubKey(pi, error);
117 require_quiet(pubKey, fail);
118
119 pi->id = SOSCopyIDOfKey(pubKey, error);
120 require_quiet(pi->id, fail);
121
122 if(pi->version >= 2) SOSPeerInfoExpandV2Data(pi, error);
123
124 if(!SOSPeerInfoVerify(pi, error)) {
125 SOSCreateErrorWithFormat(kSOSErrorBadSignature, NULL, error, NULL, CFSTR("Signature doesn't validate"));
126 if (error)
127 secerror("Can't validate PeerInfo: %@", *error);
128 goto fail;
129 }
130
131 CFReleaseNull(pubKey);
132 return pi;
133
134 fail:
135 CFReleaseNull(pi);
136 CFReleaseNull(pl);
137 CFReleaseNull(pubKey);
138
139 return NULL;
140 }
141
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);
147 }
148