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