5 // Created by Mitch Adler on 2/17/16.
9 #import <Foundation/Foundation.h>
10 #import <AssertMacros.h>
12 #import <KeychainCircle/KCDer.h>
13 #import <KeychainCircle/KCError.h>
14 #import <KeychainCircle/KCJoiningMessages.h>
15 #import <utilities/debugging.h>
17 #include <corecrypto/ccder.h>
20 @implementation KCJoiningMessage
22 + (nullable instancetype) messageWithDER: (NSData*) message
23 error: (NSError**) error {
24 return [[KCJoiningMessage alloc] initWithDER: message error: nil];
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];
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];
41 - (bool) inflatePartsOfEncoding: (NSError**) error {
42 const uint8_t *der = self.der.bytes;
43 const uint8_t *der_end = der + self.der.length;
45 const uint8_t *sequence_end = 0;
47 der = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, der, der_end);
50 KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Not sequence");
54 if (sequence_end != der_end) {
55 KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Extra data at end of message");
60 der = ccder_decode_uint64(&type, der, der_end);
62 self->_type = (type > kLargestMessageType) ? kUnknown : (KCJoiningMessageType) type;
67 der = kcder_decode_data_nocopy(&firstData, error, der, der_end);
70 der = kcder_decode_data_nocopy(&secondData, error, der, der_end);
73 self->_firstData = firstData;
74 self->_secondData = secondData;
77 KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Extra in sequence");
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);
90 size_t srp_data_size = kcder_sizeof_data(firstData, error);
91 if (srp_data_size == 0) return 0;
93 size_t encrypted_payload_size = 0;
95 if (secondData != nil) {
96 encrypted_payload_size = kcder_sizeof_data(secondData, error);
97 if (srp_data_size == 0) return 0;
101 return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, type_size + srp_data_size + encrypted_payload_size);
104 + (nullable NSData*) encodeToDERType: (KCJoiningMessageType) type
105 data: (NSData*) firstData
106 payload: (nullable NSData*) secondData
107 error: (NSError**) error {
109 size_t length = [KCJoiningMessage encodedSizeType:type
113 if (length == 0) return nil;
115 NSMutableData* encoded = [NSMutableData dataWithLength: length];
117 uint8_t* der = encoded.mutableBytes;
118 uint8_t* der_end = der + encoded.length;
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))));
125 if (encode_end == NULL) return nil;
126 if (encode_end != der) {
127 KCJoiningErrorCreate(kDEREncodingFailed, error, @"Size didn't match encoding");
134 - (nullable instancetype) initWithDER: (NSData*) message
135 error: (NSError**) error {
138 self->_der = [NSData dataWithData: message];
140 return [self inflatePartsOfEncoding: error] ? self : nil;
143 - (nullable instancetype) initWithType: (KCJoiningMessageType) type
144 data: (NSData*) firstData
145 payload: (nullable NSData*) secondData
146 error: (NSError**) error {
149 self->_der = [KCJoiningMessage encodeToDERType:type
153 if (self->_der == nil) return nil;
155 return [self inflatePartsOfEncoding: error] ? self : nil;
161 @implementation NSData(KCJoiningMessages)
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;
168 NSMutableData *result = [NSMutableData dataWithLength: result_size];
170 uint8_t *der = result.mutableBytes;
171 uint8_t *der_end = der + result.length;
173 uint8_t *encode_done = kcder_encode_string(string, error,
176 if (encode_done != der) {
177 KCJoiningErrorCreate(kDEREncodingFailed, error, @"extra data");
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;
190 NSMutableData *result = [NSMutableData dataWithLength: result_size];
192 uint8_t *der = result.mutableBytes;
193 uint8_t *der_end = der + result.length;
195 uint8_t *encode_done = encode_seq_data_data(data1, data2, error,
198 if (encode_done != der) {
199 KCJoiningErrorCreate(kDEREncodingFailed, error, @"extra data");
206 - (bool) decodeSequenceData: (NSData* _Nullable * _Nonnull) data1
207 data: (NSData* _Nullable * _Nonnull) data2
208 error: (NSError** _Nullable) error {
210 return NULL != decode_seq_data_data(data1, data2, error, self.bytes, self.bytes + self.length);
213 + (nullable instancetype) dataWithEncodedSequenceString: (NSString*) string
215 error: (NSError**) error {
216 size_t result_size = sizeof_seq_string_data(string, data, error);
217 if (result_size == 0) return nil;
219 NSMutableData *result = [NSMutableData dataWithLength: result_size];
221 uint8_t *der = result.mutableBytes;
222 uint8_t *der_end = der + result.length;
224 uint8_t *encode_done = encode_seq_string_data(string, data, error,
227 if (encode_done != der) {
228 KCJoiningErrorCreate(kDEREncodingFailed, error, @"extra data");
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);
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");
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);
264 // Allow extra stuff in here for future start messages.
265 if (parse_end == NULL) {
268 else if (parse_end != der_end) {
269 NSData *extraStuff = 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;
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)
288 uint64_t versionFromBlob = 0;
289 der = ccder_decode_uint64(&versionFromBlob, der, der_end);
292 KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Version mising");
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);
300 *uuid = [NSData dataWithBytes: (void*)payload length: payload_size];
301 *piggy_version = versionFromBlob;
304 KCJoiningErrorCreate(kDERUnknownVersion, error, @"Bad version: %llu", versionFromBlob);
310 const uint8_t* decode_initialmessage(NSData** data, NSError** error,
311 const uint8_t* der, const uint8_t *der_end)
316 const uint8_t *sequence_end = 0;
317 der = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, der, der_end);
319 if (der == NULL || sequence_end != der_end) {
320 KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Decoding failed");
323 uint64_t version = 0;
324 der = ccder_decode_uint64(&version, der, der_end);
327 KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Version mising");
332 KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Bad version: %llu", version);
336 return kcder_decode_data(data, error, der, der_end);
339 size_t sizeof_initialmessage(NSData*data) {
340 size_t version_size = ccder_sizeof_uint64(0);
341 if (version_size == 0) {
344 size_t message_size = kcder_sizeof_data(data, nil);
345 if (message_size == 0) {
348 return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, version_size + message_size);
351 uint8_t* encode_initialmessage(NSData* data, NSError**error,
352 const uint8_t *der, uint8_t *der_end)
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)));
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) {
364 size_t message_size = kcder_sizeof_data(data, nil);
365 if (message_size == 0) {
368 size_t version1_size = ccder_sizeof_uint64(version1);
369 if (version1_size == 0) {
372 size_t uuid_size = kcder_sizeof_data(uuid, nil);
373 if (message_size == 0) {
376 return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, version_size + message_size + version1_size + uuid_size);
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)
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)))));
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) {
396 size_t data2_size = kcder_sizeof_data(data2, error);
397 if (data2_size == 0) {
400 return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, data1_size + data2_size);
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)));
410 const uint8_t* decode_seq_data_data(NSData** data1, NSData** data2, NSError** error,
411 const uint8_t* der, const uint8_t *der_end) {
415 const uint8_t *sequence_end = 0;
416 der = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, der, der_end);
418 if (der == NULL || sequence_end != der_end) {
419 KCJoiningErrorCreate(kDERUnknownEncoding, error, @"decode failed");
423 der = kcder_decode_data(data1, error, der, der_end);
424 return kcder_decode_data(data2, error, der, der_end);
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) {
432 size_t data_size = kcder_sizeof_data(data, error);
433 if (data_size == 0) {
436 return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, string_size + data_size);
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)));
446 const uint8_t* _Nullable decode_seq_string_data(NSString* _Nonnull * _Nonnull string, NSData* _Nonnull * _Nonnull data,
448 const uint8_t* der, const uint8_t *der_end) {
452 const uint8_t *sequence_end = 0;
453 der = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, der, der_end);
455 if (der == NULL || sequence_end != der_end) {
456 KCJoiningErrorCreate(kDERUnknownEncoding, error, @"decode failed");
460 der = kcder_decode_string(string, error, der, der_end);
461 return kcder_decode_data(data, error, der, der_end);