]> git.saurik.com Git - apple/security.git/blob - OSX/sec/SOSCircle/SOSPeerInfoDER.c
Security-57336.10.29.tar.gz
[apple/security.git] / OSX / sec / SOSCircle / SOSPeerInfoDER.c
1 ***************
2 *** 0 ****
3 --- 1,151 ----
4 + //
5 + // SOSPeerInfoDER.c
6 + // sec
7 + //
8 + // Created by Richard Murphy on 2/9/15.
9 + //
10 + //
11 +
12 + #include <AssertMacros.h>
13 + #include "SOSPeerInfoDER.h"
14 +
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>
20 +
21 + #include <utilities/der_plist.h>
22 + #include <utilities/der_plist_internal.h>
23 + #include <corecrypto/ccder.h>
24 + #include <utilities/der_date.h>
25 +
26 + #include <utilities/SecCFError.h>
27 +
28 + size_t SOSPeerInfoGetDEREncodedSize(SOSPeerInfoRef peer, CFErrorRef *error) {
29 + size_t plist_size = der_sizeof_plist(peer->description, error);
30 + if (plist_size == 0)
31 + return 0;
32 +
33 + size_t signature_size = der_sizeof_data(peer->signature, error);
34 + if (signature_size == 0)
35 + return 0;
36 +
37 + return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE,
38 + plist_size + signature_size);
39 + }
40 +
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)));
46 + }
47 +
48 + CFDataRef SOSPeerInfoCopyEncodedData(SOSPeerInfoRef peer, CFAllocatorRef allocator, CFErrorRef *error) {
49 + size_t size = SOSPeerInfoGetDEREncodedSize(peer, error);
50 + if (size == 0) return NULL;
51 +
52 + uint8_t buffer[size];
53 + uint8_t* start = SOSPeerInfoEncodeToDER(peer, error, buffer, buffer + sizeof(buffer));
54 + CFDataRef result = CFDataCreate(kCFAllocatorDefault, start, size);
55 + return result;
56 + }
57 +
58 +
59 +
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;
65 +
66 + CFPropertyListRef pl = NULL;
67 +
68 + pi->gestalt = 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);
73 +
74 + if (*der_p == NULL || *der_p != sequence_end) {
75 + SOSCreateError(kSOSErrorBadFormat, CFSTR("Bad Format of Peer Info DER"), NULL, error);
76 + goto fail;
77 + }
78 +
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);
84 + goto fail;
85 + }
86 +
87 + pi->description = (CFMutableDictionaryRef) pl;
88 + CFRetain(pi->description);
89 + CFReleaseNull(pl);
90 +
91 + CFNumberRef versionNumber = CFDictionaryGetValue(pi->description, sVersionKey);
92 +
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);
99 + goto fail;
100 + }
101 + CFNumberGetValue(versionNumber, kCFNumberCFIndexType, &pi->version);
102 + }
103 +
104 + CFDictionaryRef gestalt = CFDictionaryGetValue(pi->description, sGestaltKey);
105 +
106 + if (gestalt == NULL) {
107 + SOSCreateErrorWithFormat(kSOSErrorUnexpectedType, NULL, error, NULL,
108 + CFSTR("gestalt key missing"));
109 + goto fail;
110 + }
111 +
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);
117 + goto fail;
118 + }
119 +
120 + pi->gestalt = gestalt;
121 + CFRetain(pi->gestalt);
122 +
123 + pubKey = SOSPeerInfoCopyPubKey(pi);
124 + require_quiet(pubKey, fail);
125 +
126 + pi->id = SOSCopyIDOfKey(pubKey, error);
127 + require_quiet(pi->id, fail);
128 +
129 + if(pi->version >= 2) SOSPeerInfoExpandV2Data(pi, error);
130 +
131 + if(!SOSPeerInfoVerify(pi, error)) {
132 + SOSCreateErrorWithFormat(kSOSErrorBadSignature, NULL, error, NULL, CFSTR("Signature doesn't validate"));
133 + if (error)
134 + secerror("Can't validate PeerInfo: %@", *error);
135 + goto fail;
136 + }
137 +
138 + CFReleaseNull(pubKey);
139 + return pi;
140 +
141 + fail:
142 + CFReleaseNull(pi);
143 + CFReleaseNull(pl);
144 + CFReleaseNull(pubKey);
145 +
146 + return NULL;
147 + }
148 +
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);
154 + }