5 // Created by Mitch Adler on 2/17/16.
9 #import <Foundation/Foundation.h>
11 #import <KeychainCircle/KCDer.h>
12 #import <KeychainCircle/KCError.h>
13 #import <KeychainCircle/KCJoiningMessages.h>
15 #include <corecrypto/ccder.h>
18 @implementation KCJoiningMessage
20 + (nullable instancetype) messageWithDER: (NSData*) message
21 error: (NSError**) error {
22 return [[KCJoiningMessage alloc] initWithDER: message error: nil];
25 + (nullable instancetype) messageWithType: (KCJoiningMessageType) type
26 data: (NSData*) firstData
27 error: (NSError**) error {
28 return [[KCJoiningMessage alloc] initWithType:type data:firstData payload:nil error:error];
31 + (nullable instancetype) messageWithType: (KCJoiningMessageType) type
32 data: (NSData*) firstData
33 payload: (NSData*) secondData
34 error: (NSError**) error {
35 return [[KCJoiningMessage alloc] initWithType:type data:firstData payload:secondData error:error];
39 - (bool) inflatePartsOfEncoding: (NSError**) error {
40 const uint8_t *der = self.der.bytes;
41 const uint8_t *der_end = der + self.der.length;
43 const uint8_t *sequence_end = 0;
45 der = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, der, der_end);
48 KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Not sequence");
52 if (sequence_end != der_end) {
53 KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Extra data at end of message");
58 der = ccder_decode_uint64(&type, der, der_end);
60 self->_type = (type > kLargestMessageType) ? kUnknown : (KCJoiningMessageType) type;
65 der = kcder_decode_data_nocopy(&firstData, error, der, der_end);
68 der = kcder_decode_data_nocopy(&secondData, error, der, der_end);
71 self->_firstData = firstData;
72 self->_secondData = secondData;
75 KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Extra in sequence");
82 + (size_t) encodedSizeType: (KCJoiningMessageType) type
83 data: (NSData*) firstData
84 payload: (nullable NSData*) secondData
85 error: (NSError**) error {
86 size_t type_size = ccder_sizeof_uint64(type);
88 size_t srp_data_size = kcder_sizeof_data(firstData, error);
89 if (srp_data_size == 0) return 0;
91 size_t encrypted_payload_size = 0;
93 if (secondData != nil) {
94 encrypted_payload_size = kcder_sizeof_data(secondData, error);
95 if (srp_data_size == 0) return 0;
99 return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, type_size + srp_data_size + encrypted_payload_size);
102 + (nullable NSData*) encodeToDERType: (KCJoiningMessageType) type
103 data: (NSData*) firstData
104 payload: (nullable NSData*) secondData
105 error: (NSError**) error {
107 size_t length = [KCJoiningMessage encodedSizeType:type
111 if (length == 0) return nil;
113 NSMutableData* encoded = [NSMutableData dataWithLength: length];
115 uint8_t* der = encoded.mutableBytes;
116 uint8_t* der_end = der + encoded.length;
118 uint8_t* encode_end = ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der,
119 ccder_encode_uint64(type, der,
120 kcder_encode_data(firstData, error, der,
121 kcder_encode_data_optional(secondData, error, der, der_end))));
123 if (encode_end == NULL) return nil;
124 if (encode_end != der) {
125 KCJoiningErrorCreate(kDEREncodingFailed, error, @"Size didn't match encoding");
132 - (nullable instancetype) initWithDER: (NSData*) message
133 error: (NSError**) error {
136 self->_der = [NSData dataWithData: message];
138 return [self inflatePartsOfEncoding: error] ? self : nil;
141 - (nullable instancetype) initWithType: (KCJoiningMessageType) type
142 data: (NSData*) firstData
143 payload: (nullable NSData*) secondData
144 error: (NSError**) error {
147 self->_der = [KCJoiningMessage encodeToDERType:type
151 if (self->_der == nil) return nil;
153 return [self inflatePartsOfEncoding: error] ? self : nil;
159 @implementation NSData(KCJoiningMessages)
161 + (nullable instancetype) dataWithEncodedString: (NSString*) string
162 error: (NSError**) error {
163 size_t result_size = kcder_sizeof_string(string, error);
164 if (result_size == 0) return nil;
166 NSMutableData *result = [NSMutableData dataWithLength: result_size];
168 uint8_t *der = result.mutableBytes;
169 uint8_t *der_end = der + result.length;
171 uint8_t *encode_done = kcder_encode_string(string, error,
174 if (encode_done != der) {
175 KCJoiningErrorCreate(kDEREncodingFailed, error, @"extra data");
182 + (nullable instancetype) dataWithEncodedSequenceData: (NSData*) data1
183 data: (NSData*) data2
184 error: (NSError**) error {
185 size_t result_size = sizeof_seq_data_data(data1, data2, error);
186 if (result_size == 0) return nil;
188 NSMutableData *result = [NSMutableData dataWithLength: result_size];
190 uint8_t *der = result.mutableBytes;
191 uint8_t *der_end = der + result.length;
193 uint8_t *encode_done = encode_seq_data_data(data1, data2, error,
196 if (encode_done != der) {
197 KCJoiningErrorCreate(kDEREncodingFailed, error, @"extra data");
204 - (bool) decodeSequenceData: (NSData* _Nullable * _Nonnull) data1
205 data: (NSData* _Nullable * _Nonnull) data2
206 error: (NSError** _Nullable) error {
208 return NULL != decode_seq_data_data(data1, data2, error, self.bytes, self.bytes + self.length);
211 + (nullable instancetype) dataWithEncodedSequenceString: (NSString*) string
213 error: (NSError**) error {
214 size_t result_size = sizeof_seq_string_data(string, data, error);
215 if (result_size == 0) return nil;
217 NSMutableData *result = [NSMutableData dataWithLength: result_size];
219 uint8_t *der = result.mutableBytes;
220 uint8_t *der_end = der + result.length;
222 uint8_t *encode_done = encode_seq_string_data(string, data, error,
225 if (encode_done != der) {
226 KCJoiningErrorCreate(kDEREncodingFailed, error, @"extra data");
233 - (bool) decodeSequenceString: (NSString* _Nullable * _Nonnull) string
234 data: (NSData* _Nullable * _Nonnull) data
235 error: (NSError** _Nullable) error {
236 return NULL != decode_seq_string_data(string, data, error, self.bytes, self.bytes + self.length);
241 @implementation NSString(KCJoiningMessages)
242 + (nullable instancetype) decodeFromDER: (NSData*)der error: (NSError** _Nullable) error {
243 NSString* result = nil;
244 const uint8_t* decode_result = kcder_decode_string(&result, error, der.bytes, der.bytes+der.length);
245 if (decode_result == nil) return nil;
246 if (decode_result != der.bytes + der.length) {
247 KCJoiningErrorCreate(kDERUnknownEncoding, error, @"extra data in string");
256 NSData* extractStartFromInitialMessage(NSData* initialMessage, NSError** error) {
257 NSData* result = nil;
258 const uint8_t *der = [initialMessage bytes];
259 const uint8_t *der_end = der + [initialMessage length];
260 const uint8_t *parse_end = decode_initialmessage(&result, error, der, der_end);
262 // Allow extra stuff in here for future start messages.
263 if (parse_end == NULL) {
270 const uint8_t* decode_initialmessage(NSData** data, NSError** error,
271 const uint8_t* der, const uint8_t *der_end)
276 const uint8_t *sequence_end = 0;
277 der = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, der, der_end);
279 if (der == NULL || sequence_end != der_end) {
280 KCJoiningErrorCreate(kDERUnknownEncoding, error, @"decode failed");
284 uint64_t version = 0;
285 der = ccder_decode_uint64(&version, der, der_end);
288 KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Version mising");
293 KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Bad version: %d", version);
297 return kcder_decode_data(data, error, der, der_end);
300 size_t sizeof_initialmessage(NSData*data) {
301 size_t version_size = ccder_sizeof_uint64(0);
302 if (version_size == 0) {
305 size_t message_size = kcder_sizeof_data(data, nil);
306 if (message_size == 0) {
309 return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, version_size + message_size);
312 uint8_t* encode_initialmessage(NSData* data, NSError**error,
313 const uint8_t *der, uint8_t *der_end)
315 return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der,
316 ccder_encode_uint64(0, der,
317 kcder_encode_data(data, error, der, der_end)));
322 size_t sizeof_seq_data_data(NSData*data1, NSData*data2, NSError**error) {
323 size_t data1_size = kcder_sizeof_data(data1, error);
324 if (data1_size == 0) {
327 size_t data2_size = kcder_sizeof_data(data2, error);
328 if (data2_size == 0) {
331 return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, data1_size + data2_size);
334 uint8_t* encode_seq_data_data(NSData* data1, NSData*data2, NSError**error,
335 const uint8_t *der, uint8_t *der_end) {
336 return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der,
337 kcder_encode_data(data1, error, der,
338 kcder_encode_data(data2, error, der, der_end)));
341 const uint8_t* decode_seq_data_data(NSData** data1, NSData** data2, NSError** error,
342 const uint8_t* der, const uint8_t *der_end) {
346 const uint8_t *sequence_end = 0;
347 der = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, der, der_end);
349 if (der == NULL || sequence_end != der_end) {
350 KCJoiningErrorCreate(kDERUnknownEncoding, error, @"decode failed");
354 der = kcder_decode_data(data1, error, der, der_end);
355 return kcder_decode_data(data2, error, der, der_end);
358 size_t sizeof_seq_string_data(NSString*string, NSData*data, NSError** error) {
359 size_t string_size = kcder_sizeof_string(string, error);
360 if (string_size == 0) {
363 size_t data_size = kcder_sizeof_data(data, error);
364 if (data_size == 0) {
367 return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, string_size + data_size);
370 uint8_t* _Nullable encode_seq_string_data(NSString* string, NSData*data, NSError**error,
371 const uint8_t *der, uint8_t *der_end) {
372 return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der,
373 kcder_encode_string(string, error, der,
374 kcder_encode_data(data, error, der, der_end)));
377 const uint8_t* _Nullable decode_seq_string_data(NSString* _Nonnull * _Nonnull string, NSData* _Nonnull * _Nonnull data,
379 const uint8_t* der, const uint8_t *der_end) {
383 const uint8_t *sequence_end = 0;
384 der = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, der, der_end);
386 if (der == NULL || sequence_end != der_end) {
387 KCJoiningErrorCreate(kDERUnknownEncoding, error, @"decode failed");
391 der = kcder_decode_string(string, error, der, der_end);
392 return kcder_decode_data(data, error, der, der_end);