]> git.saurik.com Git - apple/security.git/blob - OSX/sec/Security/SecOTRPacketData.h
Security-57740.60.18.tar.gz
[apple/security.git] / OSX / 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 <Security/SecOTRPackets.h>
39
40 #include <AssertMacros.h>
41
42 __BEGIN_DECLS
43
44 static CC_NONNULL((1,2))
45 OSStatus ReadAndVerifyByte(const uint8_t**bytes, size_t*size, uint8_t expected);
46
47 static CC_NONNULL((1,2))
48 OSStatus ReadAndVerifyShort(const uint8_t**bytes, size_t*size, uint16_t expected);
49
50 static CC_NONNULL((1,2))
51 OSStatus ReadAndVerifyMessageType(const uint8_t**bytes, size_t*size, OTRMessageType expected);
52
53 static CC_NONNULL((1,2,3,4))
54 OSStatus SizeAndSkipDATA(const uint8_t **bytes, size_t *size,
55 const uint8_t **dataBytes, size_t *dataSize);
56 static CC_NONNULL((1,2,3,4))
57 OSStatus SizeAndSkipMPI(const uint8_t **bytes, size_t *size,
58 const uint8_t **mpiBytes, size_t *mpiSize);
59
60
61 static CC_NONNULL((1,2,3))
62 OSStatus ReadLongLongCompact(const uint8_t**bytesPtr, size_t*sizePtr, uint64_t* value);
63
64 static CC_NONNULL((1,2,3))
65 OSStatus ReadLongLong(const uint8_t**bytesPtr, size_t*sizePtr, uint64_t* value);
66
67 static CC_NONNULL((1,2,3))
68 OSStatus ReadLong(const uint8_t**bytesPtr, size_t*sizePtr, uint32_t* value);
69
70 static CC_NONNULL((1,2,3))
71 OSStatus ReadShort(const uint8_t**bytesPtr, size_t*sizePtr, uint16_t* value);
72
73 static CC_NONNULL((1,2,3))
74 OSStatus ReadByte(const uint8_t**bytesPtr, size_t*sizePtr, uint8_t* value);
75
76 static CC_NONNULL((1,2,3))
77 OSStatus ReadMessageType(const uint8_t**bytesPtr, size_t*sizePtr, OTRMessageType* type);
78
79 static CC_NONNULL((1,2,4))
80 OSStatus ReadMPI(const uint8_t**bytesPtr, size_t*sizePtr, cc_size n, cc_unit *x);
81
82 static CC_NONNULL((1,2,3,4))
83 OSStatus ReadDATA(const uint8_t**bytesPtr, size_t*sizePtr, size_t* dataSize, uint8_t* data);
84
85 static CC_NONNULL((1,2,3))
86 OSStatus CreatePublicKey(const uint8_t**bytesPtr, size_t*sizePtr, SecOTRPublicIdentityRef* publicId);
87
88 static CC_NONNULL((1,2,3))
89 CFMutableDataRef CFDataCreateMutableFromOTRDATA(CFAllocatorRef allocator, const uint8_t**bytesPtr, size_t*sizePtr);
90
91 static CC_NONNULL((1))
92 void AppendLongLongCompact(CFMutableDataRef appendTo, uint64_t value);
93
94 static CC_NONNULL((1))
95 void AppendLongLong(CFMutableDataRef appendTo, uint64_t value);
96
97 static CC_NONNULL((1))
98 void AppendLong(CFMutableDataRef appendTo, uint32_t value);
99
100 static CC_NONNULL((1))
101 void AppendShort(CFMutableDataRef appendTo, uint16_t value);
102
103 static CC_NONNULL((1))
104 void AppendByte(CFMutableDataRef appendTo, uint8_t type);
105
106 static CC_NONNULL((1))
107 void AppendMessageType(CFMutableDataRef appendTo, OTRMessageType type);
108
109 static CC_NONNULL((1,3))
110 void AppendMPI(CFMutableDataRef appendTo, cc_size n, const cc_unit *x);
111
112 static CC_NONNULL((1,3))
113 void AppendDATA(CFMutableDataRef appendTo, size_t size, const uint8_t*data);
114
115 static CC_NONNULL((1,2))
116 void AppendPublicKey(CFMutableDataRef appendTo, SecOTRPublicIdentityRef publicId);
117
118
119 //
120 // Inline implementation
121 //
122
123 static uint16_t kCurrentOTRVersion = 0x2;
124
125 static inline OSStatus ReadLongLong(const uint8_t**bytesPtr, size_t*sizePtr, uint64_t* value)
126 {
127 require(bytesPtr != NULL, fail);
128 require(sizePtr != NULL, fail);
129 require(value != NULL, fail);
130 require(*sizePtr >= 8, fail);
131
132 *value = ((uint64_t)(*bytesPtr)[0]) << 56 |
133 ((uint64_t)(*bytesPtr)[1]) << 48 |
134 ((uint64_t)(*bytesPtr)[2]) << 40 |
135 ((uint64_t)(*bytesPtr)[3]) << 32 |
136 ((uint64_t)(*bytesPtr)[4]) << 24 |
137 ((uint64_t)(*bytesPtr)[5]) << 16 |
138 ((uint64_t)(*bytesPtr)[6]) << 8 |
139 ((uint64_t)(*bytesPtr)[7]) << 0;
140
141 *bytesPtr += 8;
142 *sizePtr -= 8;
143
144 return errSecSuccess;
145 fail:
146 return errSecParam;
147 }
148
149 static inline OSStatus ReadLongLongCompact(const uint8_t**bytesPtr, size_t*sizePtr, uint64_t* value)
150 {
151 bool moreBytes = true;
152
153 require(bytesPtr != NULL, fail);
154 require(sizePtr != NULL, fail);
155 require(value != NULL, fail);
156
157 *value = 0;
158
159 while (moreBytes && *sizePtr > 0) {
160 uint8_t thisByte = **bytesPtr;
161
162 moreBytes = (0x80 & thisByte) != 0;
163
164 *value <<= 7;
165 *value |= (thisByte & 0x7F);
166
167 ++*bytesPtr;
168 --*sizePtr;
169 }
170
171 fail:
172 return !moreBytes ? errSecSuccess : errSecDecode;
173 }
174
175 static inline OSStatus ReadLong(const uint8_t**bytesPtr, size_t*sizePtr, uint32_t* value)
176 {
177 require(bytesPtr != NULL, fail);
178 require(sizePtr != NULL, fail);
179 require(value != NULL, fail);
180 require(*sizePtr >= 4, fail);
181
182 *value = (uint32_t)(*bytesPtr)[0] << 24 |
183 (uint32_t)(*bytesPtr)[1] << 16 |
184 (uint32_t)(*bytesPtr)[2] << 8 |
185 (uint32_t)(*bytesPtr)[3] << 0;
186
187 *bytesPtr += 4;
188 *sizePtr -= 4;
189
190 return errSecSuccess;
191 fail:
192 return errSecParam;
193 }
194
195 static inline OSStatus ReadShort(const uint8_t**bytesPtr, size_t*sizePtr, uint16_t* value)
196 {
197 require(bytesPtr != NULL, fail);
198 require(sizePtr != NULL, fail);
199 require(value != NULL, fail);
200 require(*sizePtr >= 2, fail);
201
202 *value = (*bytesPtr)[0] << 8 |
203 (*bytesPtr)[1] << 0;
204
205 *bytesPtr += 2;
206 *sizePtr -= 2;
207
208 return errSecSuccess;
209 fail:
210 return errSecParam;
211 }
212
213 static inline OSStatus ReadByte(const uint8_t**bytesPtr, size_t*sizePtr, uint8_t* value)
214 {
215 require(bytesPtr != NULL, fail);
216 require(sizePtr != NULL, fail);
217 require(value != NULL, fail);
218 require(*sizePtr >= 1, fail);
219
220 *value = *bytesPtr[0];
221
222 *bytesPtr += 1;
223 *sizePtr -= 1;
224
225 return errSecSuccess;
226 fail:
227 return errSecParam;
228 }
229
230 static inline OSStatus ReadByteAsBool(const uint8_t**bytesPtr, size_t*sizePtr, bool* value)
231 {
232 uint8_t byte = 0;
233
234 OSStatus result = ReadByte(bytesPtr, sizePtr, &byte);
235
236 if (result == noErr)
237 *value = byte != 0;
238
239 return result;
240 }
241
242 static inline OSStatus ReadMessageType(const uint8_t**bytesPtr, size_t*sizePtr, OTRMessageType* type)
243 {
244 OSStatus result = errSecParam;
245 uint8_t value;
246
247 require(type != NULL, fail);
248 require_noerr_quiet(result = ReadByte(bytesPtr, sizePtr, &value), fail);
249
250 *type = value;
251 fail:
252 return result;
253 }
254
255 static inline OSStatus ReadMPI(const uint8_t**bytesPtr, size_t*sizePtr, cc_size n, cc_unit *x)
256 {
257 require(bytesPtr != NULL, fail);
258 require(sizePtr != NULL, fail);
259 require(x != NULL, fail);
260 require_quiet(*sizePtr >= 5, fail);
261
262 uint32_t mpiLength;
263
264 ReadLong(bytesPtr, sizePtr, &mpiLength);
265
266 require_quiet(mpiLength <= *sizePtr, fail);
267
268 ccn_read_uint(n, x, mpiLength, *bytesPtr);
269
270 *bytesPtr += mpiLength;
271 *sizePtr -= mpiLength;
272
273 return errSecSuccess;
274 fail:
275 return errSecParam;
276
277 }
278
279 static inline OSStatus ReadDATA(const uint8_t**bytesPtr, size_t*sizePtr, size_t* dataSize, uint8_t* data)
280 {
281 require(bytesPtr != NULL, fail);
282 require(sizePtr != NULL, fail);
283 require(data != NULL, fail);
284 require_quiet(*sizePtr >= 5, fail);
285
286 uint32_t dataLength;
287
288 ReadLong(bytesPtr, sizePtr, &dataLength);
289
290 require_quiet(dataLength <= *sizePtr, fail);
291 memmove(data, bytesPtr, dataLength);
292
293 *bytesPtr += dataLength;
294 *sizePtr -= dataLength;
295
296 *dataSize = dataLength;
297
298 return errSecSuccess;
299 fail:
300 return errSecParam;
301
302 }
303
304 static inline OSStatus CreatePublicKey(const uint8_t**bytesPtr, size_t*sizePtr, SecOTRPublicIdentityRef* publicId)
305 {
306 require(bytesPtr != NULL, fail);
307 require(sizePtr != NULL, fail);
308 require(publicId != NULL, fail);
309 require(*sizePtr >= 7, fail);
310
311 uint16_t type = 0;
312 ReadShort(bytesPtr, sizePtr, &type);
313
314 require_quiet(type == 0xF000, fail);
315 require_quiet(*sizePtr >= 5, fail);
316
317 uint32_t serializedIDLength = 0;
318 ReadLong(bytesPtr, sizePtr, &serializedIDLength);
319
320 require_quiet(*sizePtr >= serializedIDLength, fail);
321 require_quiet(((CFIndex)serializedIDLength) >= 0, fail);
322
323 CFDataRef serializedBytes = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, *bytesPtr, (CFIndex)serializedIDLength, kCFAllocatorNull);
324
325 *publicId = SecOTRPublicIdentityCreateFromData(kCFAllocatorDefault, serializedBytes, NULL);
326
327 *bytesPtr += serializedIDLength;
328 *sizePtr -= serializedIDLength;
329
330 if(serializedBytes)
331 CFRelease(serializedBytes);
332
333 return errSecSuccess;
334 fail:
335 return errSecParam;
336
337 }
338
339 static inline CFMutableDataRef CFDataCreateMutableFromOTRDATA(CFAllocatorRef allocator, const uint8_t**bytesPtr, size_t*sizePtr)
340 {
341 CFMutableDataRef result = NULL;
342 uint32_t sizeInStream;
343 require_noerr_quiet(ReadLong(bytesPtr, sizePtr, &sizeInStream), exit);
344 require_quiet(sizeInStream <= *sizePtr, exit);
345 require_quiet(((CFIndex)sizeInStream) >= 0, exit);
346
347 result = CFDataCreateMutable(allocator, 0);
348
349 CFDataAppendBytes(result, *bytesPtr, (CFIndex)sizeInStream);
350
351 *bytesPtr += sizeInStream;
352 *sizePtr -= sizeInStream;
353
354 exit:
355 return result;
356 }
357
358
359 //
360 // Parse and verify functions
361 //
362 static inline OSStatus ReadAndVerifyByte(const uint8_t**bytes, size_t*size, uint8_t expected)
363 {
364 uint8_t found;
365 OSStatus result = ReadByte(bytes, size, &found);
366 require_noerr_quiet(result, exit);
367 require_action_quiet(found == expected, exit, result = errSecDecode);
368 exit:
369 return result;
370 }
371
372 static inline OSStatus ReadAndVerifyShort(const uint8_t**bytes, size_t*size, uint16_t expected)
373 {
374 uint16_t found;
375 OSStatus result = ReadShort(bytes, size, &found);
376 require_noerr_quiet(result, exit);
377 require_action_quiet(found == expected, exit, result = errSecDecode);
378 exit:
379 return result;
380 }
381
382 static inline OSStatus ReadAndVerifyMessageType(const uint8_t**bytes, size_t*size, OTRMessageType expected)
383 {
384 OTRMessageType found;
385 OSStatus result = ReadMessageType(bytes, size, &found);
386 require_noerr_quiet(result, exit);
387 require_action_quiet(found == expected, exit, result = errSecDecode);
388 exit:
389 return result;
390 }
391
392 static inline OSStatus ReadAndVerifyVersion(const uint8_t**bytes, size_t*size)
393 {
394 return ReadAndVerifyShort(bytes, size, kCurrentOTRVersion);
395 }
396
397 static inline OSStatus ReadAndVerifyHeader(const uint8_t**bytes, size_t*size, OTRMessageType expected)
398 {
399 OSStatus result = ReadAndVerifyVersion(bytes, size);
400 require_noerr_quiet(result, exit);
401
402 result = ReadAndVerifyMessageType(bytes, size, expected);
403 require_noerr_quiet(result, exit);
404
405 exit:
406 return result;
407 }
408
409 static inline OSStatus ReadHeader(const uint8_t**bytes, size_t*size, OTRMessageType *messageType)
410 {
411 OSStatus result = ReadAndVerifyVersion(bytes, size);
412 require_noerr_quiet(result, exit);
413
414 result = ReadMessageType(bytes, size, messageType);
415 require_noerr_quiet(result, exit);
416
417 exit:
418 return result;
419 }
420
421 static inline OSStatus SizeAndSkipDATA(const uint8_t **bytes, size_t *size,
422 const uint8_t **dataBytes, size_t *dataSize)
423 {
424 OSStatus result;
425 uint32_t sizeRead;
426 result = ReadLong(bytes, size, &sizeRead);
427
428 require_noerr_quiet(result, exit);
429 require_action_quiet(sizeRead <= *size, exit, result = errSecDecode);
430
431 *dataSize = sizeRead;
432 *dataBytes = *bytes;
433 *bytes += sizeRead;
434 *size -= sizeRead;
435 exit:
436 return result;
437 }
438
439 static inline OSStatus SizeAndSkipMPI(const uint8_t **bytes, size_t *size,
440 const uint8_t **mpiBytes, size_t *mpiSize)
441 {
442 // MPIs looke like data for skipping.
443 return SizeAndSkipDATA(bytes, size, mpiBytes, mpiSize);
444 }
445
446
447 //
448 // Appending functions
449 //
450 static inline void AppendLongLongCompact(CFMutableDataRef appendTo, uint64_t value)
451 {
452 uint8_t compact[(sizeof(value) * 8 + 7) / 7]; // We can only need enough bytes to hold 8/7 expansion.
453
454 uint8_t *end = compact + sizeof(compact);
455 uint8_t *lastFilled = end;
456
457 --lastFilled;
458 *lastFilled = (value & 0x7F);
459
460 for (value >>= 7; value != 0; value >>= 7) {
461 --lastFilled;
462 *lastFilled = (value & 0x7f) | 0x80;
463 }
464
465 CFDataAppendBytes(appendTo, lastFilled, end - lastFilled);
466 }
467
468 static inline void AppendLongLong(CFMutableDataRef appendTo, uint64_t value)
469 {
470 uint8_t bigEndian[sizeof(value)] = { value >> 56, value >> 48, value >> 40, value >> 32,
471 value >> 24, value >> 16, value >> 8 , value >> 0 };
472
473 CFDataAppendBytes(appendTo, bigEndian, sizeof(bigEndian));
474 }
475
476 static inline void AppendLong(CFMutableDataRef appendTo, uint32_t value)
477 {
478 uint8_t bigEndian[sizeof(value)] = { value >> 24, value >> 16, value >> 8, value };
479
480 CFDataAppendBytes(appendTo, bigEndian, sizeof(bigEndian));
481 }
482
483 static inline void AppendShort(CFMutableDataRef appendTo, uint16_t value)
484 {
485 uint8_t bigEndian[sizeof(value)] = { value >> 8, value };
486
487 CFDataAppendBytes(appendTo, bigEndian, sizeof(bigEndian));
488 }
489
490 static inline void AppendByte(CFMutableDataRef appendTo, uint8_t byte)
491 {
492 CFDataAppendBytes(appendTo, &byte, 1);
493 }
494
495 static inline void AppendMessageType(CFMutableDataRef appendTo, OTRMessageType type)
496 {
497 AppendByte(appendTo, type);
498 }
499
500 static inline void AppendMPI(CFMutableDataRef appendTo, cc_size n, const cc_unit *x)
501 {
502 size_t size = ccn_write_uint_size(n, x);
503 /* 64 bits cast: we are appending an identity, whose size is hardcoded and less then 2^32 bytes */
504 /* Worst case is we encoded a truncated length. No security issue. */
505 assert(size<UINT32_MAX); /* Debug check */
506 AppendLong(appendTo, (uint32_t)size);
507 assert(((CFIndex)size) >= 0);
508 CFIndex startOffset = CFDataGetLength(appendTo);
509 CFDataIncreaseLength(appendTo, (CFIndex)size);
510 uint8_t* insertionPtr = CFDataGetMutableBytePtr(appendTo) + startOffset;
511 ccn_write_uint(n, x, size, insertionPtr);
512 }
513
514 static inline void AppendDATA(CFMutableDataRef appendTo, size_t size, const uint8_t*data)
515 {
516 /* 64 bits cast: we are appending Public Key or Signature, whose sizes are hardcoded and less then 2^32 bytes */
517 /* Worst case is we encoded a truncated length. No security issue. */
518 assert(size<=UINT32_MAX); /* Debug check */
519 AppendLong(appendTo, (uint32_t)size);
520 assert(((CFIndex)size) >= 0);
521 CFDataAppendBytes(appendTo, data, (CFIndex)size);
522 }
523
524 static inline void AppendCFDataAsDATA(CFMutableDataRef appendTo, CFDataRef dataToAppend)
525 {
526 AppendDATA(appendTo, (size_t)CFDataGetLength(dataToAppend), CFDataGetBytePtr(dataToAppend));
527 }
528
529 static inline void AppendPublicKey(CFMutableDataRef appendTo, SecOTRPublicIdentityRef publicId)
530 {
531 AppendShort(appendTo, 0xF000); // Custom type reserved by no one
532
533 CFMutableDataRef serializedID = CFDataCreateMutable(kCFAllocatorDefault, 0);
534
535 SecOTRPIAppendSerialization(publicId, serializedID, NULL);
536 AppendDATA(appendTo, (size_t)CFDataGetLength(serializedID), CFDataGetBytePtr(serializedID));
537
538 if(serializedID)
539 CFRelease(serializedID);
540 }
541
542 static inline void AppendVersion(CFMutableDataRef appendTo)
543 {
544 AppendShort(appendTo, kCurrentOTRVersion);
545 }
546
547 static inline void AppendHeader(CFMutableDataRef appendTo, OTRMessageType type)
548 {
549 AppendVersion(appendTo);
550 AppendMessageType(appendTo, type);
551 }
552
553 __END_DECLS
554
555 #endif