]> git.saurik.com Git - apple/security.git/blob - KeychainCircle/KCJoiningMessages.m
Security-58286.240.4.tar.gz
[apple/security.git] / KeychainCircle / KCJoiningMessages.m
1 //
2 // KCJoiningMessages.m
3 // Security
4 //
5 // Created by Mitch Adler on 2/17/16.
6 //
7 //
8
9 #import <Foundation/Foundation.h>
10 #import <AssertMacros.h>
11
12 #import <KeychainCircle/KCDer.h>
13 #import <KeychainCircle/KCError.h>
14 #import <KeychainCircle/KCJoiningMessages.h>
15 #import <utilities/debugging.h>
16
17 #include <corecrypto/ccder.h>
18
19
20 @implementation KCJoiningMessage
21
22 + (nullable instancetype) messageWithDER: (NSData*) message
23 error: (NSError**) error {
24 return [[KCJoiningMessage alloc] initWithDER: message error: nil];
25 }
26
27 + (nullable instancetype) messageWithType: (KCJoiningMessageType) type
28 data: (NSData*) firstData
29 error: (NSError**) error {
30 return [[KCJoiningMessage alloc] initWithType:type data:firstData payload:nil error:error];
31 }
32
33 + (nullable instancetype) messageWithType: (KCJoiningMessageType) type
34 data: (NSData*) firstData
35 payload: (NSData*) secondData
36 error: (NSError**) error {
37 return [[KCJoiningMessage alloc] initWithType:type data:firstData payload:secondData error:error];
38
39 }
40
41 - (bool) inflatePartsOfEncoding: (NSError**) error {
42 const uint8_t *der = self.der.bytes;
43 const uint8_t *der_end = der + self.der.length;
44
45 const uint8_t *sequence_end = 0;
46
47 der = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, der, der_end);
48
49 if (der == 0) {
50 KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Not sequence");
51 return false;
52 }
53
54 if (sequence_end != der_end) {
55 KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Extra data at end of message");
56 return false;
57 }
58
59 uint64_t type;
60 der = ccder_decode_uint64(&type, der, der_end);
61
62 self->_type = (type > kLargestMessageType) ? kUnknown : (KCJoiningMessageType) type;
63
64 NSData* firstData;
65 NSData* secondData;
66
67 der = kcder_decode_data_nocopy(&firstData, error, der, der_end);
68
69 if (der != der_end) {
70 der = kcder_decode_data_nocopy(&secondData, error, der, der_end);
71 }
72
73 self->_firstData = firstData;
74 self->_secondData = secondData;
75
76 if (der != der_end) {
77 KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Extra in sequence");
78 return false;
79 }
80
81 return true;
82 }
83
84 + (size_t) encodedSizeType: (KCJoiningMessageType) type
85 data: (NSData*) firstData
86 payload: (nullable NSData*) secondData
87 error: (NSError**) error {
88 size_t type_size = ccder_sizeof_uint64(type);
89
90 size_t srp_data_size = kcder_sizeof_data(firstData, error);
91 if (srp_data_size == 0) return 0;
92
93 size_t encrypted_payload_size = 0;
94
95 if (secondData != nil) {
96 encrypted_payload_size = kcder_sizeof_data(secondData, error);
97 if (srp_data_size == 0) return 0;
98 }
99
100
101 return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, type_size + srp_data_size + encrypted_payload_size);
102 }
103
104 + (nullable NSData*) encodeToDERType: (KCJoiningMessageType) type
105 data: (NSData*) firstData
106 payload: (nullable NSData*) secondData
107 error: (NSError**) error {
108
109 size_t length = [KCJoiningMessage encodedSizeType:type
110 data:firstData
111 payload:secondData
112 error: error];
113 if (length == 0) return nil;
114
115 NSMutableData* encoded = [NSMutableData dataWithLength: length];
116
117 uint8_t* der = encoded.mutableBytes;
118 uint8_t* der_end = der + encoded.length;
119
120 uint8_t* encode_end = ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der,
121 ccder_encode_uint64(type, der,
122 kcder_encode_data(firstData, error, der,
123 kcder_encode_data_optional(secondData, error, der, der_end))));
124
125 if (encode_end == NULL) return nil;
126 if (encode_end != der) {
127 KCJoiningErrorCreate(kDEREncodingFailed, error, @"Size didn't match encoding");
128 return nil;
129 }
130
131 return encoded;
132 }
133
134 - (nullable instancetype) initWithDER: (NSData*) message
135 error: (NSError**) error {
136 self = [super init];
137
138 self->_der = [NSData dataWithData: message];
139
140 return [self inflatePartsOfEncoding: error] ? self : nil;
141 }
142
143 - (nullable instancetype) initWithType: (KCJoiningMessageType) type
144 data: (NSData*) firstData
145 payload: (nullable NSData*) secondData
146 error: (NSError**) error {
147 self = [super init];
148
149 self->_der = [KCJoiningMessage encodeToDERType:type
150 data:firstData
151 payload:secondData
152 error:error];
153 if (self->_der == nil) return nil;
154
155 return [self inflatePartsOfEncoding: error] ? self : nil;
156 }
157
158 @end
159
160
161 @implementation NSData(KCJoiningMessages)
162
163 + (nullable instancetype) dataWithEncodedString: (NSString*) string
164 error: (NSError**) error {
165 size_t result_size = kcder_sizeof_string(string, error);
166 if (result_size == 0) return nil;
167
168 NSMutableData *result = [NSMutableData dataWithLength: result_size];
169
170 uint8_t *der = result.mutableBytes;
171 uint8_t *der_end = der + result.length;
172
173 uint8_t *encode_done = kcder_encode_string(string, error,
174 der, der_end);
175
176 if (encode_done != der) {
177 KCJoiningErrorCreate(kDEREncodingFailed, error, @"extra data");
178 return nil;
179 }
180
181 return result;
182 }
183
184 + (nullable instancetype) dataWithEncodedSequenceData: (NSData*) data1
185 data: (NSData*) data2
186 error: (NSError**) error {
187 size_t result_size = sizeof_seq_data_data(data1, data2, error);
188 if (result_size == 0) return nil;
189
190 NSMutableData *result = [NSMutableData dataWithLength: result_size];
191
192 uint8_t *der = result.mutableBytes;
193 uint8_t *der_end = der + result.length;
194
195 uint8_t *encode_done = encode_seq_data_data(data1, data2, error,
196 der, der_end);
197
198 if (encode_done != der) {
199 KCJoiningErrorCreate(kDEREncodingFailed, error, @"extra data");
200 return nil;
201 }
202
203 return result;
204 }
205
206 - (bool) decodeSequenceData: (NSData* _Nullable * _Nonnull) data1
207 data: (NSData* _Nullable * _Nonnull) data2
208 error: (NSError** _Nullable) error {
209
210 return NULL != decode_seq_data_data(data1, data2, error, self.bytes, self.bytes + self.length);
211 }
212
213 + (nullable instancetype) dataWithEncodedSequenceString: (NSString*) string
214 data: (NSData*) data
215 error: (NSError**) error {
216 size_t result_size = sizeof_seq_string_data(string, data, error);
217 if (result_size == 0) return nil;
218
219 NSMutableData *result = [NSMutableData dataWithLength: result_size];
220
221 uint8_t *der = result.mutableBytes;
222 uint8_t *der_end = der + result.length;
223
224 uint8_t *encode_done = encode_seq_string_data(string, data, error,
225 der, der_end);
226
227 if (encode_done != der) {
228 KCJoiningErrorCreate(kDEREncodingFailed, error, @"extra data");
229 return nil;
230 }
231
232 return result;
233 }
234
235 - (bool) decodeSequenceString: (NSString* _Nullable * _Nonnull) string
236 data: (NSData* _Nullable * _Nonnull) data
237 error: (NSError** _Nullable) error {
238 return NULL != decode_seq_string_data(string, data, error, self.bytes, self.bytes + self.length);
239 }
240
241 @end
242
243 @implementation NSString(KCJoiningMessages)
244 + (nullable instancetype) decodeFromDER: (NSData*)der error: (NSError** _Nullable) error {
245 NSString* result = nil;
246 const uint8_t* decode_result = kcder_decode_string(&result, error, der.bytes, der.bytes+der.length);
247 if (decode_result == nil) return nil;
248 if (decode_result != der.bytes + der.length) {
249 KCJoiningErrorCreate(kDERUnknownEncoding, error, @"extra data in string");
250 return nil;
251 }
252
253 return result;
254 }
255 @end
256
257
258 NSData* extractStartFromInitialMessage(NSData* initialMessage, uint64_t* version, NSString** uuidString, NSError** error) {
259 NSData* result = nil;
260 const uint8_t *der = [initialMessage bytes];
261 const uint8_t *der_end = der + [initialMessage length];
262 const uint8_t *parse_end = decode_initialmessage(&result, error, der, der_end);
263
264 // Allow extra stuff in here for future start messages.
265 if (parse_end == NULL) {
266 return nil;
267 }
268 else if (parse_end != der_end) {
269 NSData *extraStuff = nil;
270 NSData *uuid = nil;
271 uint64_t piggy_version = 0;
272 parse_end = decode_version1(&extraStuff, &uuid, &piggy_version, error, parse_end, der_end);
273 require_action_quiet(parse_end != NULL, fail, secerror("decoding piggybacking uuid and version failed (v1)"));
274 *uuidString = [[NSString alloc] initWithData:uuid encoding:NSUTF8StringEncoding];
275 *version = piggy_version;
276 }
277 fail:
278 return result;
279
280 }
281
282 const uint8_t* decode_version1(NSData** data, NSData** uuid, uint64_t *piggy_version, NSError** error,
283 const uint8_t* der, const uint8_t *der_end)
284 {
285 if (NULL == der)
286 return NULL;
287
288 uint64_t versionFromBlob = 0;
289 der = ccder_decode_uint64(&versionFromBlob, der, der_end);
290
291 if (der == NULL) {
292 KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Version mising");
293 return nil;
294 }
295
296 if(versionFromBlob == 1){ //decode uuid
297 size_t payload_size = 0;
298 const uint8_t *payload = ccder_decode_tl(CCDER_OCTET_STRING, &payload_size, der, der_end);
299
300 *uuid = [NSData dataWithBytes: (void*)payload length: payload_size];
301 *piggy_version = versionFromBlob;
302 }
303 else{
304 KCJoiningErrorCreate(kDERUnknownVersion, error, @"Bad version: %llu", versionFromBlob);
305 return nil;
306 }
307
308 return der;
309 }
310 const uint8_t* decode_initialmessage(NSData** data, NSError** error,
311 const uint8_t* der, const uint8_t *der_end)
312 {
313 if (NULL == der)
314 return NULL;
315
316 const uint8_t *sequence_end = 0;
317 der = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, der, der_end);
318
319 if (der == NULL || sequence_end != der_end) {
320 KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Decoding failed");
321 return nil;
322 }
323 uint64_t version = 0;
324 der = ccder_decode_uint64(&version, der, der_end);
325
326 if (der == NULL) {
327 KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Version mising");
328 return nil;
329 }
330
331 if (version != 0) {
332 KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Bad version: %llu", version);
333 return nil;
334 }
335
336 return kcder_decode_data(data, error, der, der_end);
337 }
338
339 size_t sizeof_initialmessage(NSData*data) {
340 size_t version_size = ccder_sizeof_uint64(0);
341 if (version_size == 0) {
342 return 0;
343 }
344 size_t message_size = kcder_sizeof_data(data, nil);
345 if (message_size == 0) {
346 return 0;
347 }
348 return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, version_size + message_size);
349 }
350
351 uint8_t* encode_initialmessage(NSData* data, NSError**error,
352 const uint8_t *der, uint8_t *der_end)
353 {
354 return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der,
355 ccder_encode_uint64(0, der,
356 kcder_encode_data(data, error, der, der_end)));
357 }
358
359 size_t sizeof_initialmessage_version1(NSData*data, uint64_t version1, NSData *uuid) {
360 size_t version_size = ccder_sizeof_uint64(0);
361 if (version_size == 0) {
362 return 0;
363 }
364 size_t message_size = kcder_sizeof_data(data, nil);
365 if (message_size == 0) {
366 return 0;
367 }
368 size_t version1_size = ccder_sizeof_uint64(version1);
369 if (version1_size == 0) {
370 return 0;
371 }
372 size_t uuid_size = kcder_sizeof_data(uuid, nil);
373 if (message_size == 0) {
374 return 0;
375 }
376 return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, version_size + message_size + version1_size + uuid_size);
377 }
378
379
380 uint8_t* encode_initialmessage_version1(NSData* data, NSData* uuidData, uint64_t piggy_version, NSError**error,
381 const uint8_t *der, uint8_t *der_end)
382 {
383 return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der,
384 ccder_encode_uint64(0, der,
385 kcder_encode_data(data, error, der,
386 ccder_encode_uint64(piggy_version, der,
387 kcder_encode_data(uuidData, error, der, der_end)))));
388
389 }
390
391 size_t sizeof_seq_data_data(NSData*data1, NSData*data2, NSError**error) {
392 size_t data1_size = kcder_sizeof_data(data1, error);
393 if (data1_size == 0) {
394 return 0;
395 }
396 size_t data2_size = kcder_sizeof_data(data2, error);
397 if (data2_size == 0) {
398 return 0;
399 }
400 return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, data1_size + data2_size);
401 }
402
403 uint8_t* encode_seq_data_data(NSData* data1, NSData*data2, NSError**error,
404 const uint8_t *der, uint8_t *der_end) {
405 return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der,
406 kcder_encode_data(data1, error, der,
407 kcder_encode_data(data2, error, der, der_end)));
408 }
409
410 const uint8_t* decode_seq_data_data(NSData** data1, NSData** data2, NSError** error,
411 const uint8_t* der, const uint8_t *der_end) {
412 if (NULL == der)
413 return NULL;
414
415 const uint8_t *sequence_end = 0;
416 der = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, der, der_end);
417
418 if (der == NULL || sequence_end != der_end) {
419 KCJoiningErrorCreate(kDERUnknownEncoding, error, @"decode failed");
420 return nil;
421 }
422
423 der = kcder_decode_data(data1, error, der, der_end);
424 return kcder_decode_data(data2, error, der, der_end);
425 }
426
427 size_t sizeof_seq_string_data(NSString*string, NSData*data, NSError** error) {
428 size_t string_size = kcder_sizeof_string(string, error);
429 if (string_size == 0) {
430 return 0;
431 }
432 size_t data_size = kcder_sizeof_data(data, error);
433 if (data_size == 0) {
434 return 0;
435 }
436 return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, string_size + data_size);
437 }
438
439 uint8_t* _Nullable encode_seq_string_data(NSString* string, NSData*data, NSError**error,
440 const uint8_t *der, uint8_t *der_end) {
441 return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der,
442 kcder_encode_string(string, error, der,
443 kcder_encode_data(data, error, der, der_end)));
444 }
445
446 const uint8_t* _Nullable decode_seq_string_data(NSString* _Nonnull * _Nonnull string, NSData* _Nonnull * _Nonnull data,
447 NSError** error,
448 const uint8_t* der, const uint8_t *der_end) {
449 if (NULL == der)
450 return NULL;
451
452 const uint8_t *sequence_end = 0;
453 der = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, der, der_end);
454
455 if (der == NULL || sequence_end != der_end) {
456 KCJoiningErrorCreate(kDERUnknownEncoding, error, @"decode failed");
457 return nil;
458 }
459
460 der = kcder_decode_string(string, error, der, der_end);
461 return kcder_decode_data(data, error, der, der_end);
462 }