]> git.saurik.com Git - apple/security.git/blob - OSX/sec/SOSCircle/SecureObjectSync/SOSPeerInfoDER.c
Security-57336.1.9.tar.gz
[apple/security.git] / OSX / sec / SOSCircle / SecureObjectSync / SOSPeerInfoDER.c
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 size_t size = SOSPeerInfoGetDEREncodedSize(peer, error);
47 if (size == 0) return NULL;
48
49 uint8_t buffer[size];
50 uint8_t* start = SOSPeerInfoEncodeToDER(peer, error, buffer, buffer + sizeof(buffer));
51 CFDataRef result = CFDataCreate(kCFAllocatorDefault, start, size);
52 return result;
53 }
54
55
56
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;
62
63 CFPropertyListRef pl = NULL;
64
65 pi->gestalt = 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);
70
71 if (*der_p == NULL || *der_p != sequence_end) {
72 SOSCreateError(kSOSErrorBadFormat, CFSTR("Bad Format of Peer Info DER"), NULL, error);
73 goto fail;
74 }
75
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);
81 goto fail;
82 }
83
84 pi->description = (CFMutableDictionaryRef) pl;
85 CFRetain(pi->description);
86 CFReleaseNull(pl);
87
88 CFNumberRef versionNumber = CFDictionaryGetValue(pi->description, sVersionKey);
89
90 if (versionNumber) {
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);
96 goto fail;
97 }
98 CFNumberGetValue(versionNumber, kCFNumberCFIndexType, &pi->version);
99 }
100
101 CFDictionaryRef gestalt = CFDictionaryGetValue(pi->description, sGestaltKey);
102
103 if (gestalt == NULL) {
104 SOSCreateErrorWithFormat(kSOSErrorUnexpectedType, NULL, error, NULL,
105 CFSTR("gestalt key missing"));
106 goto fail;
107 }
108
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);
114 goto fail;
115 }
116
117 pi->gestalt = gestalt;
118 CFRetain(pi->gestalt);
119
120 pubKey = SOSPeerInfoCopyPubKey(pi);
121 require_quiet(pubKey, fail);
122
123 pi->id = SOSCopyIDOfKey(pubKey, error);
124 require_quiet(pi->id, fail);
125
126 if(pi->version >= 2) SOSPeerInfoExpandV2Data(pi, error);
127
128 if(!SOSPeerInfoVerify(pi, error)) {
129 SOSCreateErrorWithFormat(kSOSErrorBadSignature, NULL, error, NULL, CFSTR("Signature doesn't validate"));
130 if (error)
131 secerror("Can't validate PeerInfo: %@", *error);
132 goto fail;
133 }
134
135 CFReleaseNull(pubKey);
136 return pi;
137
138 fail:
139 CFReleaseNull(pi);
140 CFReleaseNull(pl);
141 CFReleaseNull(pubKey);
142
143 return NULL;
144 }
145
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);
151 }
152