2 * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 #ifndef _SECOTRPACKETDATA_H_
26 #define _SECOTRPACKETDATA_H_
28 #include <CoreFoundation/CFBase.h>
29 #include <CoreFoundation/CFRuntime.h>
30 #include <CoreFoundation/CFData.h>
32 #include <corecrypto/ccn.h>
34 #include <CommonCrypto/CommonDigest.h>
36 #include <Security/SecBase.h>
38 #include <Security/SecOTRPackets.h>
40 #include <AssertMacros.h>
42 #include <security_utilities/simulatecrash_assert.h>
46 CF_ASSUME_NONNULL_BEGIN
49 OSStatus
ReadAndVerifyByte(const uint8_t *_Nonnull
*_Nonnull bytes
, size_t*size
, uint8_t expected
);
52 OSStatus
ReadAndVerifyShort(const uint8_t *_Nonnull
*_Nonnull bytes
, size_t*size
, uint16_t expected
);
55 OSStatus
ReadAndVerifyMessageType(const uint8_t *_Nonnull
*_Nonnull bytes
, size_t*size
, OTRMessageType expected
);
58 OSStatus
SizeAndSkipDATA(const uint8_t *_Nonnull
*_Nonnull bytes
, size_t *size
,
59 const uint8_t *_Nonnull
*_Nonnull dataBytes
, size_t *dataSize
);
61 OSStatus
SizeAndSkipMPI(const uint8_t *_Nonnull
*_Nonnull bytes
, size_t *size
,
62 const uint8_t *_Nonnull
*_Nonnull mpiBytes
, size_t *mpiSize
);
66 OSStatus
ReadLongLongCompact(const uint8_t *_Nonnull
*_Nonnull bytesPtr
, size_t*sizePtr
, uint64_t* value
);
69 OSStatus
ReadLongLong(const uint8_t *_Nonnull
*_Nonnull bytesPtr
, size_t*sizePtr
, uint64_t* value
);
72 OSStatus
ReadLong(const uint8_t *_Nonnull
*_Nonnull bytesPtr
, size_t*sizePtr
, uint32_t* value
);
75 OSStatus
ReadShort(const uint8_t *_Nonnull
*_Nonnull bytesPtr
, size_t*sizePtr
, uint16_t* value
);
78 OSStatus
ReadByte(const uint8_t *_Nonnull
*_Nonnull bytesPtr
, size_t*sizePtr
, uint8_t* value
);
81 OSStatus
ReadMessageType(const uint8_t *_Nonnull
*_Nonnull bytesPtr
, size_t*sizePtr
, OTRMessageType
* type
);
84 OSStatus
ReadMPI(const uint8_t *_Nonnull
*_Nonnull bytesPtr
, size_t*sizePtr
, cc_size n
, cc_unit
*x
);
87 OSStatus
ReadDATA(const uint8_t *_Nonnull
*_Nonnull bytesPtr
, size_t*sizePtr
, size_t* dataSize
, uint8_t* data
);
90 OSStatus
CreatePublicKey(const uint8_t *_Nonnull
*_Nonnull bytesPtr
, size_t*sizePtr
, _Nonnull SecOTRPublicIdentityRef
*_Nonnull publicId
);
93 CFMutableDataRef
CFDataCreateMutableFromOTRDATA(CFAllocatorRef _Nullable allocator
, const uint8_t *_Nonnull
*_Nonnull bytesPtr
, size_t*sizePtr
);
96 void AppendLongLongCompact(CFMutableDataRef appendTo
, uint64_t value
);
99 void AppendLongLong(CFMutableDataRef appendTo
, uint64_t value
);
102 void AppendLong(CFMutableDataRef appendTo
, uint32_t value
);
105 void AppendShort(CFMutableDataRef appendTo
, uint16_t value
);
108 void AppendByte(CFMutableDataRef appendTo
, uint8_t type
);
111 void AppendMessageType(CFMutableDataRef appendTo
, OTRMessageType type
);
114 void AppendMPI(CFMutableDataRef appendTo
, cc_size n
, const cc_unit
*x
);
117 void AppendDATA(CFMutableDataRef appendTo
, size_t size
, const uint8_t*data
);
120 void AppendPublicKey(CFMutableDataRef appendTo
, SecOTRPublicIdentityRef publicId
);
124 // Inline implementation
127 static uint16_t kCurrentOTRVersion
= 0x2;
129 static inline OSStatus
ReadLongLong(const uint8_t *_Nonnull
*_Nonnull bytesPtr
, size_t*sizePtr
, uint64_t* value
)
131 require(bytesPtr
!= NULL
, fail
);
132 require(sizePtr
!= NULL
, fail
);
133 require(value
!= NULL
, fail
);
134 require(*sizePtr
>= 8, fail
);
136 *value
= ((uint64_t)(*bytesPtr
)[0]) << 56 |
137 ((uint64_t)(*bytesPtr
)[1]) << 48 |
138 ((uint64_t)(*bytesPtr
)[2]) << 40 |
139 ((uint64_t)(*bytesPtr
)[3]) << 32 |
140 ((uint64_t)(*bytesPtr
)[4]) << 24 |
141 ((uint64_t)(*bytesPtr
)[5]) << 16 |
142 ((uint64_t)(*bytesPtr
)[6]) << 8 |
143 ((uint64_t)(*bytesPtr
)[7]) << 0;
148 return errSecSuccess
;
153 static inline OSStatus
ReadLongLongCompact(const uint8_t *_Nonnull
*_Nonnull bytesPtr
, size_t*sizePtr
, uint64_t* value
)
155 bool moreBytes
= true;
157 require(bytesPtr
!= NULL
, fail
);
158 require(sizePtr
!= NULL
, fail
);
159 require(value
!= NULL
, fail
);
163 while (moreBytes
&& *sizePtr
> 0) {
164 uint8_t thisByte
= **bytesPtr
;
166 moreBytes
= (0x80 & thisByte
) != 0;
169 *value
|= (thisByte
& 0x7F);
176 return !moreBytes
? errSecSuccess
: errSecDecode
;
179 static inline OSStatus
ReadLong(const uint8_t *_Nonnull
*_Nonnull bytesPtr
, size_t*sizePtr
, uint32_t* value
)
181 require(bytesPtr
!= NULL
, fail
);
182 require(sizePtr
!= NULL
, fail
);
183 require(value
!= NULL
, fail
);
184 require(*sizePtr
>= 4, fail
);
186 *value
= (uint32_t)(*bytesPtr
)[0] << 24 |
187 (uint32_t)(*bytesPtr
)[1] << 16 |
188 (uint32_t)(*bytesPtr
)[2] << 8 |
189 (uint32_t)(*bytesPtr
)[3] << 0;
194 return errSecSuccess
;
199 static inline OSStatus
ReadShort(const uint8_t *_Nonnull
*_Nonnull bytesPtr
, size_t*sizePtr
, uint16_t* value
)
201 require(bytesPtr
!= NULL
, fail
);
202 require(sizePtr
!= NULL
, fail
);
203 require(value
!= NULL
, fail
);
204 require(*sizePtr
>= 2, fail
);
206 *value
= (*bytesPtr
)[0] << 8 |
212 return errSecSuccess
;
217 static inline OSStatus
ReadByte(const uint8_t *_Nonnull
*_Nonnull bytesPtr
, size_t*sizePtr
, uint8_t* value
)
219 require(bytesPtr
!= NULL
, fail
);
220 require(sizePtr
!= NULL
, fail
);
221 require(value
!= NULL
, fail
);
222 require(*sizePtr
>= 1, fail
);
224 *value
= *bytesPtr
[0];
229 return errSecSuccess
;
234 static inline OSStatus
ReadByteAsBool(const uint8_t *_Nonnull
*_Nonnull bytesPtr
, size_t*sizePtr
, bool* value
)
238 OSStatus result
= ReadByte(bytesPtr
, sizePtr
, &byte
);
246 static inline OSStatus
ReadMessageType(const uint8_t *_Nonnull
*_Nonnull bytesPtr
, size_t*sizePtr
, OTRMessageType
* type
)
248 OSStatus result
= errSecParam
;
251 require(type
!= NULL
, fail
);
252 require_noerr_quiet(result
= ReadByte(bytesPtr
, sizePtr
, &value
), fail
);
259 static inline OSStatus
ReadMPI(const uint8_t *_Nonnull
*_Nonnull bytesPtr
, size_t*sizePtr
, cc_size n
, cc_unit
*x
)
261 require(bytesPtr
!= NULL
, fail
);
262 require(sizePtr
!= NULL
, fail
);
263 require(x
!= NULL
, fail
);
264 require_quiet(*sizePtr
>= 5, fail
);
268 ReadLong(bytesPtr
, sizePtr
, &mpiLength
);
270 require_quiet(mpiLength
<= *sizePtr
, fail
);
272 ccn_read_uint(n
, x
, mpiLength
, *bytesPtr
);
274 *bytesPtr
+= mpiLength
;
275 *sizePtr
-= mpiLength
;
277 return errSecSuccess
;
283 static inline OSStatus
ReadDATA(const uint8_t *_Nonnull
*_Nonnull bytesPtr
, size_t*sizePtr
, size_t* dataSize
, uint8_t* data
)
285 require(bytesPtr
!= NULL
, fail
);
286 require(sizePtr
!= NULL
, fail
);
287 require(data
!= NULL
, fail
);
288 require_quiet(*sizePtr
>= 5, fail
);
292 ReadLong(bytesPtr
, sizePtr
, &dataLength
);
294 require_quiet(dataLength
<= *sizePtr
, fail
);
295 memmove(data
, bytesPtr
, dataLength
);
297 *bytesPtr
+= dataLength
;
298 *sizePtr
-= dataLength
;
300 *dataSize
= dataLength
;
302 return errSecSuccess
;
308 static inline OSStatus
CreatePublicKey(const uint8_t *_Nonnull
*_Nonnull bytesPtr
, size_t*sizePtr
, _Nonnull SecOTRPublicIdentityRef
*_Nonnull publicId
)
310 require(bytesPtr
!= NULL
, fail
);
311 require(sizePtr
!= NULL
, fail
);
312 require(publicId
!= NULL
, fail
);
313 require(*sizePtr
>= 7, fail
);
316 ReadShort(bytesPtr
, sizePtr
, &type
);
318 require_quiet(type
== 0xF000, fail
);
319 require_quiet(*sizePtr
>= 5, fail
);
321 uint32_t serializedIDLength
= 0;
322 ReadLong(bytesPtr
, sizePtr
, &serializedIDLength
);
324 require_quiet(*sizePtr
>= serializedIDLength
, fail
);
325 require_quiet(((CFIndex
)serializedIDLength
) >= 0, fail
);
327 CFDataRef serializedBytes
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, *bytesPtr
, (CFIndex
)serializedIDLength
, kCFAllocatorNull
);
329 *publicId
= SecOTRPublicIdentityCreateFromData(kCFAllocatorDefault
, serializedBytes
, NULL
);
331 *bytesPtr
+= serializedIDLength
;
332 *sizePtr
-= serializedIDLength
;
335 CFRelease(serializedBytes
);
337 return errSecSuccess
;
343 static inline CFMutableDataRef
CFDataCreateMutableFromOTRDATA(CFAllocatorRef _Nullable allocator
, const uint8_t *_Nonnull
*_Nonnull bytesPtr
, size_t*sizePtr
)
345 CFMutableDataRef result
= NULL
;
346 uint32_t sizeInStream
;
347 require_noerr_quiet(ReadLong(bytesPtr
, sizePtr
, &sizeInStream
), exit
);
348 require_quiet(sizeInStream
<= *sizePtr
, exit
);
349 require_quiet(((CFIndex
)sizeInStream
) >= 0, exit
);
351 result
= CFDataCreateMutable(allocator
, 0);
353 CFDataAppendBytes(result
, *bytesPtr
, (CFIndex
)sizeInStream
);
355 *bytesPtr
+= sizeInStream
;
356 *sizePtr
-= sizeInStream
;
364 // Parse and verify functions
366 static inline OSStatus
ReadAndVerifyByte(const uint8_t *_Nonnull
*_Nonnull bytes
, size_t*size
, uint8_t expected
)
369 OSStatus result
= ReadByte(bytes
, size
, &found
);
370 require_noerr_quiet(result
, exit
);
371 require_action_quiet(found
== expected
, exit
, result
= errSecDecode
);
376 static inline OSStatus
ReadAndVerifyShort(const uint8_t *_Nonnull
*_Nonnull bytes
, size_t*size
, uint16_t expected
)
379 OSStatus result
= ReadShort(bytes
, size
, &found
);
380 require_noerr_quiet(result
, exit
);
381 require_action_quiet(found
== expected
, exit
, result
= errSecDecode
);
386 static inline OSStatus
ReadAndVerifyMessageType(const uint8_t *_Nonnull
*_Nonnull bytes
, size_t*size
, OTRMessageType expected
)
388 OTRMessageType found
;
389 OSStatus result
= ReadMessageType(bytes
, size
, &found
);
390 require_noerr_quiet(result
, exit
);
391 require_action_quiet(found
== expected
, exit
, result
= errSecDecode
);
396 static inline OSStatus
ReadAndVerifyVersion(const uint8_t *_Nonnull
*_Nonnull bytes
, size_t*size
)
398 return ReadAndVerifyShort(bytes
, size
, kCurrentOTRVersion
);
401 static inline OSStatus
ReadAndVerifyHeader(const uint8_t *_Nonnull
*_Nonnull bytes
, size_t*size
, OTRMessageType expected
)
403 OSStatus result
= ReadAndVerifyVersion(bytes
, size
);
404 require_noerr_quiet(result
, exit
);
406 result
= ReadAndVerifyMessageType(bytes
, size
, expected
);
407 require_noerr_quiet(result
, exit
);
413 static inline OSStatus
ReadHeader(const uint8_t *_Nonnull
*_Nonnull bytes
, size_t*size
, OTRMessageType
*messageType
)
415 OSStatus result
= ReadAndVerifyVersion(bytes
, size
);
416 require_noerr_quiet(result
, exit
);
418 result
= ReadMessageType(bytes
, size
, messageType
);
419 require_noerr_quiet(result
, exit
);
425 static inline OSStatus
SizeAndSkipDATA(const uint8_t *_Nonnull
*_Nonnull bytes
, size_t *size
,
426 const uint8_t *_Nonnull
*_Nonnull dataBytes
, size_t *dataSize
)
430 result
= ReadLong(bytes
, size
, &sizeRead
);
432 require_noerr_quiet(result
, exit
);
433 require_action_quiet(sizeRead
<= *size
, exit
, result
= errSecDecode
);
435 *dataSize
= sizeRead
;
443 static inline OSStatus
SizeAndSkipMPI(const uint8_t *_Nonnull
*_Nonnull bytes
, size_t *size
,
444 const uint8_t *_Nonnull
*_Nonnull mpiBytes
, size_t *mpiSize
)
446 // MPIs looke like data for skipping.
447 return SizeAndSkipDATA(bytes
, size
, mpiBytes
, mpiSize
);
452 // Appending functions
454 static inline void AppendLongLongCompact(CFMutableDataRef appendTo
, uint64_t value
)
456 uint8_t compact
[(sizeof(value
) * 8 + 7) / 7]; // We can only need enough bytes to hold 8/7 expansion.
458 uint8_t *end
= compact
+ sizeof(compact
);
459 uint8_t *lastFilled
= end
;
462 *lastFilled
= (value
& 0x7F);
464 for (value
>>= 7; value
!= 0; value
>>= 7) {
466 *lastFilled
= (value
& 0x7f) | 0x80;
469 CFDataAppendBytes(appendTo
, lastFilled
, end
- lastFilled
);
472 static inline void AppendLongLong(CFMutableDataRef appendTo
, uint64_t value
)
474 uint8_t bigEndian
[sizeof(value
)] = { value
>> 56, value
>> 48, value
>> 40, value
>> 32,
475 value
>> 24, value
>> 16, value
>> 8 , value
>> 0 };
477 CFDataAppendBytes(appendTo
, bigEndian
, sizeof(bigEndian
));
480 static inline void AppendLong(CFMutableDataRef appendTo
, uint32_t value
)
482 uint8_t bigEndian
[sizeof(value
)] = { value
>> 24, value
>> 16, value
>> 8, value
};
484 CFDataAppendBytes(appendTo
, bigEndian
, sizeof(bigEndian
));
487 static inline void AppendShort(CFMutableDataRef appendTo
, uint16_t value
)
489 uint8_t bigEndian
[sizeof(value
)] = { value
>> 8, value
};
491 CFDataAppendBytes(appendTo
, bigEndian
, sizeof(bigEndian
));
494 static inline void AppendByte(CFMutableDataRef appendTo
, uint8_t byte
)
496 CFDataAppendBytes(appendTo
, &byte
, 1);
499 static inline void AppendMessageType(CFMutableDataRef appendTo
, OTRMessageType type
)
501 AppendByte(appendTo
, type
);
504 static inline void AppendMPI(CFMutableDataRef appendTo
, cc_size n
, const cc_unit
*x
)
506 size_t size
= ccn_write_uint_size(n
, x
);
507 /* 64 bits cast: we are appending an identity, whose size is hardcoded and less then 2^32 bytes */
508 /* Worst case is we encoded a truncated length. No security issue. */
509 assert(size
<UINT32_MAX
); /* Debug check */
510 AppendLong(appendTo
, (uint32_t)size
);
511 assert(((CFIndex
)size
) >= 0);
512 CFIndex startOffset
= CFDataGetLength(appendTo
);
513 CFDataIncreaseLength(appendTo
, (CFIndex
)size
);
514 uint8_t* insertionPtr
= CFDataGetMutableBytePtr(appendTo
) + startOffset
;
515 ccn_write_uint(n
, x
, size
, insertionPtr
);
518 static inline void AppendDATA(CFMutableDataRef appendTo
, size_t size
, const uint8_t*data
)
520 /* 64 bits cast: we are appending Public Key or Signature, whose sizes are hardcoded and less then 2^32 bytes */
521 /* Worst case is we encoded a truncated length. No security issue. */
522 assert(size
<=UINT32_MAX
); /* Debug check */
523 AppendLong(appendTo
, (uint32_t)size
);
524 assert(((CFIndex
)size
) >= 0);
525 CFDataAppendBytes(appendTo
, data
, (CFIndex
)size
);
528 static inline void AppendCFDataAsDATA(CFMutableDataRef appendTo
, CFDataRef dataToAppend
)
530 AppendDATA(appendTo
, (size_t)CFDataGetLength(dataToAppend
), CFDataGetBytePtr(dataToAppend
));
533 static inline void AppendPublicKey(CFMutableDataRef appendTo
, SecOTRPublicIdentityRef publicId
)
535 AppendShort(appendTo
, 0xF000); // Custom type reserved by no one
537 CFMutableDataRef serializedID
= CFDataCreateMutable(kCFAllocatorDefault
, 0);
539 SecOTRPIAppendSerialization(publicId
, serializedID
, NULL
);
540 AppendDATA(appendTo
, (size_t)CFDataGetLength(serializedID
), CFDataGetBytePtr(serializedID
));
543 CFRelease(serializedID
);
546 static inline void AppendVersion(CFMutableDataRef appendTo
)
548 AppendShort(appendTo
, kCurrentOTRVersion
);
551 static inline void AppendHeader(CFMutableDataRef appendTo
, OTRMessageType type
)
553 AppendVersion(appendTo
);
554 AppendMessageType(appendTo
, type
);
557 CF_ASSUME_NONNULL_END