]> git.saurik.com Git - apple/security.git/blob - KeychainCircle/KCJoiningMessages.m
Security-59754.41.1.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 #import <Security/SecureObjectSync/SOSTypes.h>
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 secondData: (nullable NSData*) secondData
36 error: (NSError**) error {
37 return [[KCJoiningMessage alloc] initWithType:type data:firstData payload:secondData error:error];
38 }
39
40 + (nullable instancetype) messageWithType: (KCJoiningMessageType) type
41 data: (NSData*) firstData
42 payload: (nullable NSData*) secondData
43 error: (NSError**) error {
44 return [[KCJoiningMessage alloc] initWithType:type data:firstData payload:secondData error:error];
45
46 }
47
48 - (bool) inflatePartsOfEncoding: (NSError**) error {
49 const uint8_t *der = self.der.bytes;
50 const uint8_t *der_end = der + self.der.length;
51
52 const uint8_t *sequence_end = 0;
53
54 der = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, der, der_end);
55
56 if (der == 0) {
57 KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Not sequence");
58 return false;
59 }
60
61 if (sequence_end != der_end) {
62 KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Extra data at end of message");
63 return false;
64 }
65
66 uint64_t type;
67 der = ccder_decode_uint64(&type, der, der_end);
68
69 self->_type = (type > kLargestMessageType) ? kUnknown : (KCJoiningMessageType) type;
70
71 NSData* firstData;
72 NSData* secondData;
73
74 der = kcder_decode_data_nocopy(&firstData, error, der, der_end);
75
76 if (der != der_end) {
77 der = kcder_decode_data_nocopy(&secondData, error, der, der_end);
78 }
79
80 self->_firstData = firstData;
81 self->_secondData = secondData;
82
83 if (der != der_end) {
84 KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Extra in sequence");
85 return false;
86 }
87
88 return true;
89 }
90
91 + (size_t) encodedSizeType: (KCJoiningMessageType) type
92 data: (NSData*) firstData
93 payload: (nullable NSData*) secondData
94 error: (NSError**) error {
95 size_t type_size = ccder_sizeof_uint64(type);
96
97 size_t srp_data_size = kcder_sizeof_data(firstData, error);
98 if (srp_data_size == 0) return 0;
99
100 size_t encrypted_payload_size = 0;
101
102 if (secondData != nil) {
103 encrypted_payload_size = kcder_sizeof_data(secondData, error);
104 if (srp_data_size == 0) return 0;
105 }
106
107
108 return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, type_size + srp_data_size + encrypted_payload_size);
109 }
110
111 + (nullable NSData*) encodeToDERType: (KCJoiningMessageType) type
112 data: (NSData*) firstData
113 payload: (nullable NSData*) secondData
114 error: (NSError**) error {
115
116 size_t length = [KCJoiningMessage encodedSizeType:type
117 data:firstData
118 payload:secondData
119 error: error];
120 if (length == 0) return nil;
121
122 NSMutableData* encoded = [NSMutableData dataWithLength: length];
123
124 uint8_t* der = encoded.mutableBytes;
125 uint8_t* der_end = der + encoded.length;
126
127 uint8_t* encode_end = ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der,
128 ccder_encode_uint64(type, der,
129 kcder_encode_data(firstData, error, der,
130 kcder_encode_data_optional(secondData, error, der, der_end))));
131
132 if (encode_end == NULL) return nil;
133 if (encode_end != der) {
134 KCJoiningErrorCreate(kDEREncodingFailed, error, @"Size didn't match encoding");
135 return nil;
136 }
137
138 return encoded;
139 }
140
141 - (nullable instancetype) initWithDER: (NSData*) message
142 error: (NSError**) error {
143 if ((self = [super init])) {
144 self->_der = [NSData dataWithData: message];
145 }
146 return [self inflatePartsOfEncoding: error] ? self : nil;
147 }
148
149 - (nullable instancetype) initWithType: (KCJoiningMessageType) type
150 data: (NSData*) firstData
151 payload: (nullable NSData*) secondData
152 error: (NSError**) error {
153 if ((self = [super init])) {
154 self->_der = [KCJoiningMessage encodeToDERType:type
155 data:firstData
156 payload:secondData
157 error:error];
158 if (self->_der == nil) return nil;
159 }
160 return [self inflatePartsOfEncoding: error] ? self : nil;
161 }
162
163 @end
164
165
166 @implementation NSData(KCJoiningMessages)
167
168 + (nullable instancetype) dataWithEncodedString: (NSString*) string
169 error: (NSError**) error {
170 size_t result_size = kcder_sizeof_string(string, error);
171 if (result_size == 0) return nil;
172
173 NSMutableData *result = [NSMutableData dataWithLength: result_size];
174
175 uint8_t *der = result.mutableBytes;
176 uint8_t *der_end = der + result.length;
177
178 uint8_t *encode_done = kcder_encode_string(string, error,
179 der, der_end);
180
181 if (encode_done != der) {
182 KCJoiningErrorCreate(kDEREncodingFailed, error, @"extra data");
183 return nil;
184 }
185
186 return result;
187 }
188
189 + (nullable instancetype) dataWithEncodedSequenceData: (NSData*) data1
190 data: (NSData*) data2
191 error: (NSError**) error {
192 size_t result_size = sizeof_seq_data_data(data1, data2, error);
193 if (result_size == 0) return nil;
194
195 NSMutableData *result = [NSMutableData dataWithLength: result_size];
196
197 uint8_t *der = result.mutableBytes;
198 uint8_t *der_end = der + result.length;
199
200 uint8_t *encode_done = encode_seq_data_data(data1, data2, error,
201 der, der_end);
202
203 if (encode_done != der) {
204 KCJoiningErrorCreate(kDEREncodingFailed, error, @"extra data");
205 return nil;
206 }
207
208 return result;
209 }
210
211 - (bool) decodeSequenceData: (NSData* _Nullable * _Nonnull) data1
212 data: (NSData* _Nullable * _Nonnull) data2
213 error: (NSError** _Nullable) error {
214
215 return NULL != decode_seq_data_data(data1, data2, error, self.bytes, self.bytes + self.length);
216 }
217
218 + (nullable instancetype) dataWithEncodedSequenceString: (NSString*) string
219 data: (NSData*) data
220 error: (NSError**) error {
221 size_t result_size = sizeof_seq_string_data(string, data, error);
222 if (result_size == 0) return nil;
223
224 NSMutableData *result = [NSMutableData dataWithLength: result_size];
225
226 uint8_t *der = result.mutableBytes;
227 uint8_t *der_end = der + result.length;
228
229 uint8_t *encode_done = encode_seq_string_data(string, data, error,
230 der, der_end);
231
232 if (encode_done != der) {
233 KCJoiningErrorCreate(kDEREncodingFailed, error, @"extra data");
234 return nil;
235 }
236
237 return result;
238 }
239
240 - (bool) decodeSequenceString: (NSString* _Nullable * _Nonnull) string
241 data: (NSData* _Nullable * _Nonnull) data
242 error: (NSError** _Nullable) error {
243 return NULL != decode_seq_string_data(string, data, error, self.bytes, self.bytes + self.length);
244 }
245
246 @end
247
248 @implementation NSString(KCJoiningMessages)
249 + (nullable instancetype) decodeFromDER: (NSData*)der error: (NSError** _Nullable) error {
250 NSString* result = nil;
251 const uint8_t* decode_result = kcder_decode_string(&result, error, der.bytes, der.bytes+der.length);
252 if (decode_result == nil) return nil;
253 if (decode_result != der.bytes + der.length) {
254 KCJoiningErrorCreate(kDERUnknownEncoding, error, @"extra data in string");
255 return nil;
256 }
257
258 return result;
259 }
260 @end
261
262
263 NSData* extractStartFromInitialMessage(NSData* initialMessage, uint64_t* version, NSString** uuidString, NSData** octagon, NSError** error) {
264 NSData* result = nil;
265 const uint8_t *der = [initialMessage bytes];
266 const uint8_t *der_end = der + [initialMessage length];
267 const uint8_t *parse_end = decode_initialmessage(&result, error, der, der_end);
268
269 // Allow extra stuff in here for future start messages.
270 if (parse_end == NULL) {
271 return nil;
272 }
273 else if (parse_end != der_end) {
274 NSData *extraStuff = nil;
275 NSData *uuidData = nil;
276 uint64_t piggy_version = 0;
277 NSData* octagonData = nil;
278
279 parse_end = decode_version2(&extraStuff, &uuidData, &octagonData, &piggy_version, error, parse_end, der_end);
280 require_action_quiet(parse_end != NULL, fail, secerror("decoding piggybacking message failed for version (%llu)", piggy_version));
281
282 switch(piggy_version){
283 case kPiggyV2:
284 *octagon = octagonData;
285 //fall through to pick up v1
286 case kPiggyV1:{
287 NSUUID *uuid = [[NSUUID alloc]initWithUUIDBytes:uuidData.bytes];
288 *uuidString = uuid.UUIDString;
289 *version = piggy_version;
290 break;
291 }
292 case kPiggyV0:
293 *version = kPiggyV0;
294 break;
295 default:
296 secerror("unsupported version");
297 break;
298 }
299 }
300 fail:
301 return result;
302
303 }
304
305 const uint8_t* decode_version1(NSData** data, NSData** uuid, uint64_t *piggy_version, NSError** error,
306 const uint8_t* der, const uint8_t *der_end)
307 {
308 if (NULL == der)
309 return NULL;
310
311 uint64_t versionFromBlob = 0;
312 der = ccder_decode_uint64(&versionFromBlob, der, der_end);
313
314 if (der == NULL) {
315 KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Version mising");
316 return nil;
317 }
318
319 if(versionFromBlob == 1){ //decode uuid
320 size_t payloadSize = 0;
321 const uint8_t *payload = ccder_decode_tl(CCDER_OCTET_STRING, &payloadSize, der, der_end);
322
323 *uuid = [NSData dataWithBytes: (void*)payload length: payloadSize];
324 *piggy_version = versionFromBlob;
325 der = payload + payloadSize;
326 }
327 else{
328 KCJoiningErrorCreate(kDERUnknownVersion, error, @"Bad version: %llu", versionFromBlob);
329 return nil;
330 }
331
332 return der;
333 }
334
335 const uint8_t* decode_version2(NSData** data, NSData** uuid, NSData** octagon, uint64_t *piggy_version, NSError** error,
336 const uint8_t* der, const uint8_t *der_end)
337 {
338 const uint8_t* end = nil;
339
340 const uint8_t* parse_version1 = decode_version1(data, uuid, piggy_version, error, der, der_end);
341
342 if(parse_version1 == NULL){
343 secerror("error parsing version 1");
344 return NULL;
345 }
346 else if (parse_version1 == der_end){
347 secnotice("octagon", "first message is piggybacking v1, no more data");
348 return parse_version1;
349 }
350 else{
351 end = kcder_decode_data(octagon, error, parse_version1, der_end);
352
353 if(end == NULL){
354 secerror("failed to decode v2");
355 return NULL;
356 }
357 else if(*octagon && [*octagon length] != 0){
358 *piggy_version = kPiggyV2;
359 }
360 else{
361 secerror("no octagon version set");
362 return NULL;
363 }
364 }
365
366 return end;
367 }
368
369 const uint8_t* decode_initialmessage(NSData** data, NSError** error,
370 const uint8_t* der, const uint8_t *der_end)
371 {
372 if (NULL == der)
373 return NULL;
374
375 const uint8_t *sequence_end = 0;
376 der = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, der, der_end);
377
378 if (der == NULL || sequence_end != der_end) {
379 KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Decoding failed");
380 return nil;
381 }
382 uint64_t version = 0;
383 der = ccder_decode_uint64(&version, der, der_end);
384
385 if (der == NULL) {
386 KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Version mising");
387 return nil;
388 }
389
390 if (version != 0) {
391 KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Bad version: %llu", version);
392 return nil;
393 }
394
395 return kcder_decode_data(data, error, der, der_end);
396 }
397
398 size_t sizeof_initialmessage(NSData*data) {
399 size_t version_size = ccder_sizeof_uint64(0);
400 if (version_size == 0) {
401 return 0;
402 }
403 size_t message_size = kcder_sizeof_data(data, nil);
404 if (message_size == 0) {
405 return 0;
406 }
407 return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, version_size + message_size);
408 }
409
410 uint8_t* encode_initialmessage(NSData* data, NSError**error,
411 const uint8_t *der, uint8_t *der_end)
412 {
413 return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der,
414 ccder_encode_uint64(0, der,
415 kcder_encode_data(data, error, der, der_end)));
416 }
417
418 size_t sizeof_initialmessage_version2(NSData*data, uint64_t version1, NSData *uuid, NSData* octagon)
419 {
420 size_t version_size = ccder_sizeof_uint64(0);
421 if (version_size == 0) {
422 return 0;
423 }
424 size_t message_size = kcder_sizeof_data(data, nil);
425 if (message_size == 0) {
426 return 0;
427 }
428 size_t version1_size = ccder_sizeof_uint64(version1);
429 if (version1_size == 0) {
430 return 0;
431 }
432 size_t uuid_size = kcder_sizeof_data(uuid, nil);
433 if (uuid_size == 0) {
434 return 0;
435 }
436 size_t octagon_size = kcder_sizeof_data(octagon, nil);
437 if (octagon_size == 0) {
438 return 0;
439 }
440 return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, version_size + message_size +
441 version1_size + uuid_size +
442 octagon_size);
443 }
444
445 size_t sizeof_initialmessage_version1(NSData*data, uint64_t version1, NSData *uuid) {
446 size_t version_size = ccder_sizeof_uint64(0);
447 if (version_size == 0) {
448 return 0;
449 }
450 size_t message_size = kcder_sizeof_data(data, nil);
451 if (message_size == 0) {
452 return 0;
453 }
454 size_t version1_size = ccder_sizeof_uint64(version1);
455 if (version1_size == 0) {
456 return 0;
457 }
458 size_t uuid_size = kcder_sizeof_data(uuid, nil);
459 if (uuid_size == 0) {
460 return 0;
461 }
462 return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, version_size + message_size + version1_size + uuid_size);
463 }
464
465
466 uint8_t* encode_initialmessage_version1(NSData* data, NSData* uuidData, uint64_t piggy_version, NSError**error,
467 const uint8_t *der, uint8_t *der_end)
468 {
469 return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der,
470 ccder_encode_uint64(0, der,
471 kcder_encode_data(data, error, der,
472 ccder_encode_uint64(piggy_version, der,
473 kcder_encode_data(uuidData, error, der, der_end)))));
474
475 }
476
477 uint8_t* encode_initialmessage_version2(NSData* data, NSData* uuidData, NSData* octagon_version, NSError**error,
478 const uint8_t *der, uint8_t *der_end)
479 {
480
481 return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der,
482 ccder_encode_uint64(0, der,
483 kcder_encode_data(data, error, der,
484 ccder_encode_uint64(kPiggyV1, der,
485 kcder_encode_data(uuidData, error, der, kcder_encode_data(octagon_version, error, der, der_end))))));
486 }
487
488 size_t sizeof_seq_data_data(NSData*data1, NSData*data2, NSError**error) {
489 size_t data1_size = kcder_sizeof_data(data1, error);
490 if (data1_size == 0) {
491 return 0;
492 }
493 size_t data2_size = kcder_sizeof_data(data2, error);
494 if (data2_size == 0) {
495 return 0;
496 }
497 return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, data1_size + data2_size);
498 }
499
500 uint8_t* encode_seq_data_data(NSData* data1, NSData*data2, NSError**error,
501 const uint8_t *der, uint8_t *der_end) {
502 return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der,
503 kcder_encode_data(data1, error, der,
504 kcder_encode_data(data2, error, der, der_end)));
505 }
506
507 const uint8_t* decode_seq_data_data(NSData** data1, NSData** data2, NSError** error,
508 const uint8_t* der, const uint8_t *der_end) {
509 if (NULL == der)
510 return NULL;
511
512 const uint8_t *sequence_end = 0;
513 der = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, der, der_end);
514
515 if (der == NULL || sequence_end != der_end) {
516 KCJoiningErrorCreate(kDERUnknownEncoding, error, @"decode failed");
517 return nil;
518 }
519
520 der = kcder_decode_data(data1, error, der, der_end);
521 return kcder_decode_data(data2, error, der, der_end);
522 }
523
524 size_t sizeof_seq_string_data(NSString*string, NSData*data, NSError** error) {
525 size_t string_size = kcder_sizeof_string(string, error);
526 if (string_size == 0) {
527 return 0;
528 }
529 size_t data_size = kcder_sizeof_data(data, error);
530 if (data_size == 0) {
531 return 0;
532 }
533 return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, string_size + data_size);
534 }
535
536 uint8_t* _Nullable encode_seq_string_data(NSString* string, NSData*data, NSError**error,
537 const uint8_t *der, uint8_t *der_end) {
538 return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der,
539 kcder_encode_string(string, error, der,
540 kcder_encode_data(data, error, der, der_end)));
541 }
542
543 const uint8_t* _Nullable decode_seq_string_data(NSString* _Nonnull * _Nonnull string, NSData* _Nonnull * _Nonnull data,
544 NSError** error,
545 const uint8_t* der, const uint8_t *der_end) {
546 if (NULL == der)
547 return NULL;
548
549 const uint8_t *sequence_end = 0;
550 der = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, der, der_end);
551
552 if (der == NULL || sequence_end != der_end) {
553 KCJoiningErrorCreate(kDERUnknownEncoding, error, @"decode failed");
554 return nil;
555 }
556
557 der = kcder_decode_string(string, error, der, der_end);
558 return kcder_decode_data(data, error, der, der_end);
559 }