]> git.saurik.com Git - apple/security.git/blob - Security/sec/Security/SecOTRPacketData.h
c7b3d67f004bbc580b3a51f657379eae5d5c5f15
[apple/security.git] / Security / sec / Security / SecOTRPacketData.h
1 /*
2 * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25 #ifndef _SECOTRPACKETDATA_H_
26 #define _SECOTRPACKETDATA_H_
27
28 #include <CoreFoundation/CFBase.h>
29 #include <CoreFoundation/CFRuntime.h>
30 #include <CoreFoundation/CFData.h>
31
32 #include <corecrypto/ccn.h>
33
34 #include <CommonCrypto/CommonDigest.h>
35
36 #include <Security/SecBase.h>
37
38 #include <utilities/SecCFWrappers.h>
39 #include <Security/SecOTRPackets.h>
40
41 #include <AssertMacros.h>
42
43 __BEGIN_DECLS
44
45 static OSStatus ReadAndVerifyByte(const uint8_t**bytes, size_t*size, uint8_t expected);
46 static OSStatus ReadAndVerifyShort(const uint8_t**bytes, size_t*size, uint16_t expected);
47 static OSStatus ReadAndVerifyMessageType(const uint8_t**bytes, size_t*size, OTRMessageType expected);
48
49 static OSStatus SizeAndSkipDATA(const uint8_t **bytes, size_t *size,
50 const uint8_t **dataBytes, size_t *dataSize);
51 static OSStatus SizeAndSkipMPI(const uint8_t **bytes, size_t *size,
52 const uint8_t **mpiBytes, size_t *mpiSize);
53
54
55 static OSStatus ReadLongLongCompact(const uint8_t**bytesPtr, size_t*sizePtr, uint64_t* value);
56 static OSStatus ReadLongLong(const uint8_t**bytesPtr, size_t*sizePtr, uint64_t* value);
57 static OSStatus ReadLong(const uint8_t**bytesPtr, size_t*sizePtr, uint32_t* value);
58 static OSStatus ReadShort(const uint8_t**bytesPtr, size_t*sizePtr, uint16_t* value);
59 static OSStatus ReadByte(const uint8_t**bytesPtr, size_t*sizePtr, uint8_t* value);
60 static OSStatus ReadMessageType(const uint8_t**bytesPtr, size_t*sizePtr, OTRMessageType* type);
61 static OSStatus ReadMPI(const uint8_t**bytesPtr, size_t*sizePtr, cc_size n, cc_unit *x);
62 static OSStatus ReadDATA(const uint8_t**bytesPtr, size_t*sizePtr, size_t* dataSize, uint8_t* data);
63 static OSStatus CreatePublicKey(const uint8_t**bytesPtr, size_t*sizePtr, SecOTRPublicIdentityRef* publicId);
64 static CFMutableDataRef CFDataCreateMutableFromOTRDATA(CFAllocatorRef allocator, const uint8_t**bytesPtr, size_t*sizePtr);
65
66 static void AppendLongLongCompact(CFMutableDataRef appendTo, uint64_t value);
67 static void AppendLongLong(CFMutableDataRef appendTo, uint64_t value);
68 static void AppendLong(CFMutableDataRef appendTo, uint32_t value);
69 static void AppendShort(CFMutableDataRef appendTo, uint16_t value);
70 static void AppendByte(CFMutableDataRef appendTo, uint8_t type);
71 static void AppendMessageType(CFMutableDataRef appendTo, OTRMessageType type);
72 static void AppendMPI(CFMutableDataRef appendTo, cc_size n, const cc_unit *x);
73 static void AppendDATA(CFMutableDataRef appendTo, size_t size, const uint8_t*data);
74 static void AppendPublicKey(CFMutableDataRef appendTo, SecOTRPublicIdentityRef publicId);
75
76
77 //
78 // Inline implementation
79 //
80
81 static uint16_t kCurrentOTRVersion = 0x2;
82
83 static inline OSStatus ReadLongLong(const uint8_t**bytesPtr, size_t*sizePtr, uint64_t* value)
84 {
85 require(bytesPtr != NULL, fail);
86 require(sizePtr != NULL, fail);
87 require(value != NULL, fail);
88 require(*sizePtr >= 8, fail);
89
90 *value = ((uint64_t)(*bytesPtr)[0]) << 56 |
91 ((uint64_t)(*bytesPtr)[1]) << 48 |
92 ((uint64_t)(*bytesPtr)[2]) << 40 |
93 ((uint64_t)(*bytesPtr)[3]) << 32 |
94 ((uint64_t)(*bytesPtr)[4]) << 24 |
95 ((uint64_t)(*bytesPtr)[5]) << 16 |
96 ((uint64_t)(*bytesPtr)[6]) << 8 |
97 ((uint64_t)(*bytesPtr)[7]) << 0;
98
99 *bytesPtr += 8;
100 *sizePtr -= 8;
101
102 return errSecSuccess;
103 fail:
104 return errSecParam;
105 }
106
107 static inline OSStatus ReadLongLongCompact(const uint8_t**bytesPtr, size_t*sizePtr, uint64_t* value)
108 {
109 bool moreBytes = true;
110
111 require(bytesPtr != NULL, fail);
112 require(sizePtr != NULL, fail);
113 require(value != NULL, fail);
114
115 *value = 0;
116
117 while (moreBytes && *sizePtr > 0) {
118 uint8_t thisByte = **bytesPtr;
119
120 moreBytes = (0x80 & thisByte) != 0;
121
122 *value <<= 7;
123 *value |= (thisByte & 0x7F);
124
125 ++*bytesPtr;
126 --*sizePtr;
127 }
128
129 fail:
130 return !moreBytes ? errSecSuccess : errSecDecode;
131 }
132
133 static inline OSStatus ReadLong(const uint8_t**bytesPtr, size_t*sizePtr, uint32_t* value)
134 {
135 require(bytesPtr != NULL, fail);
136 require(sizePtr != NULL, fail);
137 require(value != NULL, fail);
138 require(*sizePtr >= 4, fail);
139
140 *value = (uint32_t)(*bytesPtr)[0] << 24 |
141 (uint32_t)(*bytesPtr)[1] << 16 |
142 (uint32_t)(*bytesPtr)[2] << 8 |
143 (uint32_t)(*bytesPtr)[3] << 0;
144
145 *bytesPtr += 4;
146 *sizePtr -= 4;
147
148 return errSecSuccess;
149 fail:
150 return errSecParam;
151 }
152
153 static inline OSStatus ReadShort(const uint8_t**bytesPtr, size_t*sizePtr, uint16_t* value)
154 {
155 require(bytesPtr != NULL, fail);
156 require(sizePtr != NULL, fail);
157 require(value != NULL, fail);
158 require(*sizePtr >= 2, fail);
159
160 *value = (*bytesPtr)[0] << 8 |
161 (*bytesPtr)[1] << 0;
162
163 *bytesPtr += 2;
164 *sizePtr -= 2;
165
166 return errSecSuccess;
167 fail:
168 return errSecParam;
169 }
170
171 static inline OSStatus ReadByte(const uint8_t**bytesPtr, size_t*sizePtr, uint8_t* value)
172 {
173 require(bytesPtr != NULL, fail);
174 require(sizePtr != NULL, fail);
175 require(value != NULL, fail);
176 require(*sizePtr >= 1, fail);
177
178 *value = *bytesPtr[0];
179
180 *bytesPtr += 1;
181 *sizePtr -= 1;
182
183 return errSecSuccess;
184 fail:
185 return errSecParam;
186 }
187
188 static inline OSStatus ReadByteAsBool(const uint8_t**bytesPtr, size_t*sizePtr, bool* value)
189 {
190 uint8_t byte = 0;
191
192 OSStatus result = ReadByte(bytesPtr, sizePtr, &byte);
193
194 if (result == noErr)
195 *value = byte != 0;
196
197 return result;
198 }
199
200 static inline OSStatus ReadMessageType(const uint8_t**bytesPtr, size_t*sizePtr, OTRMessageType* type)
201 {
202 OSStatus result = errSecParam;
203 uint8_t value;
204
205 require(type != NULL, fail);
206 require_noerr(result = ReadByte(bytesPtr, sizePtr, &value), fail);
207
208 *type = value;
209 fail:
210 return result;
211 }
212
213 static inline OSStatus ReadMPI(const uint8_t**bytesPtr, size_t*sizePtr, cc_size n, cc_unit *x)
214 {
215 require(bytesPtr != NULL, fail);
216 require(sizePtr != NULL, fail);
217 require(x != NULL, fail);
218 require(*sizePtr >= 5, fail);
219
220 uint32_t mpiLength;
221
222 ReadLong(bytesPtr, sizePtr, &mpiLength);
223
224 require(mpiLength <= *sizePtr, fail);
225
226 ccn_read_uint(n, x, mpiLength, *bytesPtr);
227
228 *bytesPtr += mpiLength;
229 *sizePtr -= mpiLength;
230
231 return errSecSuccess;
232 fail:
233 return errSecParam;
234
235 }
236
237 static inline OSStatus ReadDATA(const uint8_t**bytesPtr, size_t*sizePtr, size_t* dataSize, uint8_t* data)
238 {
239 require(bytesPtr != NULL, fail);
240 require(sizePtr != NULL, fail);
241 require(data != NULL, fail);
242 require(*sizePtr >= 5, fail);
243
244 uint32_t dataLength;
245
246 ReadLong(bytesPtr, sizePtr, &dataLength);
247
248 require(dataLength <= *sizePtr, fail);
249 memmove(data, bytesPtr, dataLength);
250
251 *bytesPtr += dataLength;
252 *sizePtr -= dataLength;
253
254 *dataSize = dataLength;
255
256 return errSecSuccess;
257 fail:
258 return errSecParam;
259
260 }
261
262 static inline OSStatus CreatePublicKey(const uint8_t**bytesPtr, size_t*sizePtr, SecOTRPublicIdentityRef* publicId)
263 {
264 require(bytesPtr != NULL, fail);
265 require(sizePtr != NULL, fail);
266 require(publicId != NULL, fail);
267 require(*sizePtr >= 7, fail);
268
269 uint16_t type = 0;
270 ReadShort(bytesPtr, sizePtr, &type);
271
272 require(type == 0xF000, fail);
273 require(*sizePtr >= 5, fail);
274
275 uint32_t serializedIDLength = 0;
276 ReadLong(bytesPtr, sizePtr, &serializedIDLength);
277
278 require(*sizePtr >= serializedIDLength, fail);
279 require(((CFIndex)serializedIDLength) >= 0, fail);
280
281 CFDataRef serializedBytes = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, *bytesPtr, (CFIndex)serializedIDLength, kCFAllocatorNull);
282
283 *publicId = SecOTRPublicIdentityCreateFromData(kCFAllocatorDefault, serializedBytes, NULL);
284
285 *bytesPtr += serializedIDLength;
286 *sizePtr -= serializedIDLength;
287
288 CFReleaseNull(serializedBytes);
289
290 return errSecSuccess;
291 fail:
292 return errSecParam;
293
294 }
295
296 static inline CFMutableDataRef CFDataCreateMutableFromOTRDATA(CFAllocatorRef allocator, const uint8_t**bytesPtr, size_t*sizePtr)
297 {
298 CFMutableDataRef result = NULL;
299 uint32_t sizeInStream;
300 require_noerr(ReadLong(bytesPtr, sizePtr, &sizeInStream), exit);
301 require(sizeInStream <= *sizePtr, exit);
302 require(((CFIndex)sizeInStream) >= 0, exit);
303
304 result = CFDataCreateMutable(allocator, 0);
305
306 CFDataAppendBytes(result, *bytesPtr, (CFIndex)sizeInStream);
307
308 *bytesPtr += sizeInStream;
309 *sizePtr += sizeInStream;
310
311 exit:
312 return result;
313 }
314
315
316 //
317 // Parse and verify functions
318 //
319 static inline OSStatus ReadAndVerifyByte(const uint8_t**bytes, size_t*size, uint8_t expected)
320 {
321 uint8_t found;
322 OSStatus result = ReadByte(bytes, size, &found);
323 require_noerr(result, exit);
324 require_action(found == expected, exit, result = errSecDecode);
325 exit:
326 return result;
327 }
328
329 static inline OSStatus ReadAndVerifyShort(const uint8_t**bytes, size_t*size, uint16_t expected)
330 {
331 uint16_t found;
332 OSStatus result = ReadShort(bytes, size, &found);
333 require_noerr(result, exit);
334 require_action(found == expected, exit, result = errSecDecode);
335 exit:
336 return result;
337 }
338
339 static inline OSStatus ReadAndVerifyMessageType(const uint8_t**bytes, size_t*size, OTRMessageType expected)
340 {
341 OTRMessageType found;
342 OSStatus result = ReadMessageType(bytes, size, &found);
343 require_noerr(result, exit);
344 require_action(found == expected, exit, result = errSecDecode);
345 exit:
346 return result;
347 }
348
349 static inline OSStatus ReadAndVerifyVersion(const uint8_t**bytes, size_t*size)
350 {
351 return ReadAndVerifyShort(bytes, size, kCurrentOTRVersion);
352 }
353
354 static inline OSStatus ReadAndVerifyHeader(const uint8_t**bytes, size_t*size, OTRMessageType expected)
355 {
356 OSStatus result = ReadAndVerifyVersion(bytes, size);
357 require_noerr(result, exit);
358
359 result = ReadAndVerifyMessageType(bytes, size, expected);
360 require_noerr(result, exit);
361
362 exit:
363 return result;
364 }
365
366 static inline OSStatus ReadHeader(const uint8_t**bytes, size_t*size, OTRMessageType *messageType)
367 {
368 OSStatus result = ReadAndVerifyVersion(bytes, size);
369 require_noerr(result, exit);
370
371 result = ReadMessageType(bytes, size, messageType);
372 require_noerr(result, exit);
373
374 exit:
375 return result;
376 }
377
378 static inline OSStatus SizeAndSkipDATA(const uint8_t **bytes, size_t *size,
379 const uint8_t **dataBytes, size_t *dataSize)
380 {
381 OSStatus result;
382 uint32_t sizeRead;
383 result = ReadLong(bytes, size, &sizeRead);
384
385 require_noerr(result, exit);
386 require_action(sizeRead <= *size, exit, result = errSecDecode);
387
388 *dataSize = sizeRead;
389 *dataBytes = *bytes;
390 *bytes += sizeRead;
391 *size -= sizeRead;
392 exit:
393 return result;
394 }
395
396 static inline OSStatus SizeAndSkipMPI(const uint8_t **bytes, size_t *size,
397 const uint8_t **mpiBytes, size_t *mpiSize)
398 {
399 // MPIs looke like data for skipping.
400 return SizeAndSkipDATA(bytes, size, mpiBytes, mpiSize);
401 }
402
403
404 //
405 // Appending functions
406 //
407 static inline void AppendLongLongCompact(CFMutableDataRef appendTo, uint64_t value)
408 {
409 uint8_t compact[(sizeof(value) * 8 + 7) / 7]; // We can only need enough bytes to hold 8/7 expansion.
410
411 uint8_t *end = compact + sizeof(compact);
412 uint8_t *lastFilled = end;
413
414 --lastFilled;
415 *lastFilled = (value & 0x7F);
416
417 for (value >>= 7; value != 0; value >>= 7) {
418 --lastFilled;
419 *lastFilled = (value & 0x7f) | 0x80;
420 }
421
422 CFDataAppendBytes(appendTo, lastFilled, end - lastFilled);
423 }
424
425 static inline void AppendLongLong(CFMutableDataRef appendTo, uint64_t value)
426 {
427 uint8_t bigEndian[sizeof(value)] = { value >> 56, value >> 48, value >> 40, value >> 32,
428 value >> 24, value >> 16, value >> 8 , value >> 0 };
429
430 CFDataAppendBytes(appendTo, bigEndian, sizeof(bigEndian));
431 }
432
433 static inline void AppendLong(CFMutableDataRef appendTo, uint32_t value)
434 {
435 uint8_t bigEndian[sizeof(value)] = { value >> 24, value >> 16, value >> 8, value };
436
437 CFDataAppendBytes(appendTo, bigEndian, sizeof(bigEndian));
438 }
439
440 static inline void AppendShort(CFMutableDataRef appendTo, uint16_t value)
441 {
442 uint8_t bigEndian[sizeof(value)] = { value >> 8, value };
443
444 CFDataAppendBytes(appendTo, bigEndian, sizeof(bigEndian));
445 }
446
447 static inline void AppendByte(CFMutableDataRef appendTo, uint8_t byte)
448 {
449 CFDataAppendBytes(appendTo, &byte, 1);
450 }
451
452 static inline void AppendMessageType(CFMutableDataRef appendTo, OTRMessageType type)
453 {
454 AppendByte(appendTo, type);
455 }
456
457 static inline void AppendMPI(CFMutableDataRef appendTo, cc_size n, const cc_unit *x)
458 {
459 size_t size = ccn_write_uint_size(n, x);
460 /* 64 bits cast: we are appending an identity, whose size is hardcoded and less then 2^32 bytes */
461 /* Worst case is we encoded a truncated length. No security issue. */
462 assert(size<UINT32_MAX); /* Debug check */
463 AppendLong(appendTo, (uint32_t)size);
464 assert(((CFIndex)size) >= 0);
465 uint8_t* insertionPtr = CFDataIncreaseLengthAndGetMutableBytes(appendTo, (CFIndex)size);
466 ccn_write_uint(n, x, size, insertionPtr);
467 }
468
469 static inline void AppendDATA(CFMutableDataRef appendTo, size_t size, const uint8_t*data)
470 {
471 /* 64 bits cast: we are appending Public Key or Signature, whose sizes are hardcoded and less then 2^32 bytes */
472 /* Worst case is we encoded a truncated length. No security issue. */
473 assert(size<=UINT32_MAX); /* Debug check */
474 AppendLong(appendTo, (uint32_t)size);
475 assert(((CFIndex)size) >= 0);
476 CFDataAppendBytes(appendTo, data, (CFIndex)size);
477 }
478
479 static inline void AppendCFDataAsDATA(CFMutableDataRef appendTo, CFDataRef dataToAppend)
480 {
481 AppendDATA(appendTo, (size_t)CFDataGetLength(dataToAppend), CFDataGetBytePtr(dataToAppend));
482 }
483
484 static inline void AppendPublicKey(CFMutableDataRef appendTo, SecOTRPublicIdentityRef publicId)
485 {
486 AppendShort(appendTo, 0xF000); // Custom type reserved by no one
487
488 CFMutableDataRef serializedID = CFDataCreateMutable(kCFAllocatorDefault, 0);
489
490 SecOTRPIAppendSerialization(publicId, serializedID, NULL);
491 AppendDATA(appendTo, (size_t)CFDataGetLength(serializedID), CFDataGetBytePtr(serializedID));
492
493 CFReleaseNull(serializedID);
494 }
495
496 static inline void AppendVersion(CFMutableDataRef appendTo)
497 {
498 AppendShort(appendTo, kCurrentOTRVersion);
499 }
500
501 static inline void AppendHeader(CFMutableDataRef appendTo, OTRMessageType type)
502 {
503 AppendVersion(appendTo);
504 AppendMessageType(appendTo, type);
505 }
506
507 __END_DECLS
508
509 #endif