3 // libsecurity_libSecOTR
5 // Created by Mitch Adler on 2/26/11.
6 // Copyright 2011 Apple Inc. All rights reserved.
9 #ifndef _SECOTRPACKETDATA_H_
10 #define _SECOTRPACKETDATA_H_
12 #include <CoreFoundation/CFBase.h>
13 #include <CoreFoundation/CFRuntime.h>
14 #include <CoreFoundation/CFData.h>
16 #include <corecrypto/ccn.h>
18 #include <CommonCrypto/CommonDigest.h>
20 #include <Security/SecBase.h>
22 #include <utilities/SecCFWrappers.h>
23 #include <Security/SecOTRPackets.h>
25 #include <AssertMacros.h>
29 static OSStatus
ReadAndVerifyByte(const uint8_t**bytes
, size_t*size
, uint8_t expected
);
30 static OSStatus
ReadAndVerifyShort(const uint8_t**bytes
, size_t*size
, uint16_t expected
);
31 static OSStatus
ReadAndVerifyMessageType(const uint8_t**bytes
, size_t*size
, OTRMessageType expected
);
33 static OSStatus
SizeAndSkipDATA(const uint8_t **bytes
, size_t *size
,
34 const uint8_t **dataBytes
, size_t *dataSize
);
35 static OSStatus
SizeAndSkipMPI(const uint8_t **bytes
, size_t *size
,
36 const uint8_t **mpiBytes
, size_t *mpiSize
);
39 static OSStatus
ReadLongLong(const uint8_t**bytesPtr
, size_t*sizePtr
, uint64_t* value
);
40 static OSStatus
ReadLong(const uint8_t**bytesPtr
, size_t*sizePtr
, uint32_t* value
);
41 static OSStatus
ReadShort(const uint8_t**bytesPtr
, size_t*sizePtr
, uint16_t* value
);
42 static OSStatus
ReadByte(const uint8_t**bytesPtr
, size_t*sizePtr
, uint8_t* value
);
43 static OSStatus
ReadMessageType(const uint8_t**bytesPtr
, size_t*sizePtr
, OTRMessageType
* type
);
44 static OSStatus
ReadMPI(const uint8_t**bytesPtr
, size_t*sizePtr
, cc_size n
, cc_unit
*x
);
45 static OSStatus
ReadDATA(const uint8_t**bytesPtr
, size_t*sizePtr
, size_t* dataSize
, uint8_t* data
);
46 static OSStatus
CreatePublicKey(const uint8_t**bytesPtr
, size_t*sizePtr
, SecOTRPublicIdentityRef
* publicId
);
47 static CFMutableDataRef
CFDataCreateMutableFromOTRDATA(CFAllocatorRef allocator
, const uint8_t**bytesPtr
, size_t*sizePtr
);
49 static void AppendLongLong(CFMutableDataRef appendTo
, uint64_t value
);
50 static void AppendLong(CFMutableDataRef appendTo
, uint32_t value
);
51 static void AppendShort(CFMutableDataRef appendTo
, uint16_t value
);
52 static void AppendByte(CFMutableDataRef appendTo
, uint8_t type
);
53 static void AppendMessageType(CFMutableDataRef appendTo
, OTRMessageType type
);
54 static void AppendMPI(CFMutableDataRef appendTo
, cc_size n
, const cc_unit
*x
);
55 static void AppendDATA(CFMutableDataRef appendTo
, size_t size
, const uint8_t*data
);
56 static void AppendPublicKey(CFMutableDataRef appendTo
, SecOTRPublicIdentityRef publicId
);
60 // Inline implementation
63 static uint16_t kCurrentOTRVersion
= 0x2;
65 static inline OSStatus
ReadLongLong(const uint8_t**bytesPtr
, size_t*sizePtr
, uint64_t* value
)
67 require(bytesPtr
!= NULL
, fail
);
68 require(sizePtr
!= NULL
, fail
);
69 require(value
!= NULL
, fail
);
70 require(*sizePtr
>= 4, fail
);
72 *value
= ((uint64_t)(*bytesPtr
)[0]) << 56 |
73 ((uint64_t)(*bytesPtr
)[1]) << 48 |
74 ((uint64_t)(*bytesPtr
)[2]) << 40 |
75 ((uint64_t)(*bytesPtr
)[3]) << 32 |
76 ((uint64_t)(*bytesPtr
)[4]) << 24 |
77 ((uint64_t)(*bytesPtr
)[5]) << 16 |
78 ((uint64_t)(*bytesPtr
)[6]) << 8 |
79 ((uint64_t)(*bytesPtr
)[7]) << 0;
89 static inline OSStatus
ReadLong(const uint8_t**bytesPtr
, size_t*sizePtr
, uint32_t* value
)
91 require(bytesPtr
!= NULL
, fail
);
92 require(sizePtr
!= NULL
, fail
);
93 require(value
!= NULL
, fail
);
94 require(*sizePtr
>= 4, fail
);
96 *value
= (uint32_t)(*bytesPtr
)[0] << 24 |
97 (uint32_t)(*bytesPtr
)[1] << 16 |
98 (uint32_t)(*bytesPtr
)[2] << 8 |
99 (uint32_t)(*bytesPtr
)[3] << 0;
104 return errSecSuccess
;
109 static inline OSStatus
ReadShort(const uint8_t**bytesPtr
, size_t*sizePtr
, uint16_t* value
)
111 require(bytesPtr
!= NULL
, fail
);
112 require(sizePtr
!= NULL
, fail
);
113 require(value
!= NULL
, fail
);
114 require(*sizePtr
>= 2, fail
);
116 *value
= (*bytesPtr
)[0] << 8 |
122 return errSecSuccess
;
127 static inline OSStatus
ReadByte(const uint8_t**bytesPtr
, size_t*sizePtr
, uint8_t* value
)
129 require(bytesPtr
!= NULL
, fail
);
130 require(sizePtr
!= NULL
, fail
);
131 require(value
!= NULL
, fail
);
132 require(*sizePtr
>= 1, fail
);
134 *value
= *bytesPtr
[0];
139 return errSecSuccess
;
144 static inline OSStatus
ReadMessageType(const uint8_t**bytesPtr
, size_t*sizePtr
, OTRMessageType
* type
)
146 OSStatus result
= errSecParam
;
149 require(type
!= NULL
, fail
);
150 require_noerr(result
= ReadByte(bytesPtr
, sizePtr
, &value
), fail
);
157 static inline OSStatus
ReadMPI(const uint8_t**bytesPtr
, size_t*sizePtr
, cc_size n
, cc_unit
*x
)
159 require(bytesPtr
!= NULL
, fail
);
160 require(sizePtr
!= NULL
, fail
);
161 require(x
!= NULL
, fail
);
162 require(*sizePtr
>= 5, fail
);
166 ReadLong(bytesPtr
, sizePtr
, &mpiLength
);
168 require(mpiLength
<= *sizePtr
, fail
);
170 ccn_read_uint(n
, x
, mpiLength
, *bytesPtr
);
172 *bytesPtr
+= mpiLength
;
173 *sizePtr
-= mpiLength
;
175 return errSecSuccess
;
181 static inline OSStatus
ReadDATA(const uint8_t**bytesPtr
, size_t*sizePtr
, size_t* dataSize
, uint8_t* data
)
183 require(bytesPtr
!= NULL
, fail
);
184 require(sizePtr
!= NULL
, fail
);
185 require(data
!= NULL
, fail
);
186 require(*sizePtr
>= 5, fail
);
190 ReadLong(bytesPtr
, sizePtr
, &dataLength
);
192 require(dataLength
<= *sizePtr
, fail
);
193 memmove(data
, bytesPtr
, dataLength
);
195 *bytesPtr
+= dataLength
;
196 *sizePtr
-= dataLength
;
198 *dataSize
= dataLength
;
200 return errSecSuccess
;
206 static inline OSStatus
CreatePublicKey(const uint8_t**bytesPtr
, size_t*sizePtr
, SecOTRPublicIdentityRef
* publicId
)
208 require(bytesPtr
!= NULL
, fail
);
209 require(sizePtr
!= NULL
, fail
);
210 require(publicId
!= NULL
, fail
);
211 require(*sizePtr
>= 7, fail
);
214 ReadShort(bytesPtr
, sizePtr
, &type
);
216 require(type
== 0xF000, fail
);
217 require(*sizePtr
>= 5, fail
);
219 uint32_t serializedIDLength
= 0;
220 ReadLong(bytesPtr
, sizePtr
, &serializedIDLength
);
222 require(*sizePtr
>= serializedIDLength
, fail
);
223 require(((CFIndex
)serializedIDLength
) >= 0, fail
);
225 CFDataRef serializedBytes
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, *bytesPtr
, (CFIndex
)serializedIDLength
, kCFAllocatorNull
);
227 *publicId
= SecOTRPublicIdentityCreateFromData(kCFAllocatorDefault
, serializedBytes
, NULL
);
229 *bytesPtr
+= serializedIDLength
;
230 *sizePtr
-= serializedIDLength
;
232 CFReleaseNull(serializedBytes
);
234 return errSecSuccess
;
240 static inline CFMutableDataRef
CFDataCreateMutableFromOTRDATA(CFAllocatorRef allocator
, const uint8_t**bytesPtr
, size_t*sizePtr
)
242 CFMutableDataRef result
= NULL
;
243 uint32_t sizeInStream
;
244 require_noerr(ReadLong(bytesPtr
, sizePtr
, &sizeInStream
), exit
);
245 require(sizeInStream
<= *sizePtr
, exit
);
246 require(((CFIndex
)sizeInStream
) >= 0, exit
);
248 result
= CFDataCreateMutable(allocator
, 0);
250 CFDataAppendBytes(result
, *bytesPtr
, (CFIndex
)sizeInStream
);
252 *bytesPtr
+= sizeInStream
;
253 *sizePtr
+= sizeInStream
;
261 // Parse and verify functions
263 static inline OSStatus
ReadAndVerifyByte(const uint8_t**bytes
, size_t*size
, uint8_t expected
)
266 OSStatus result
= ReadByte(bytes
, size
, &found
);
267 require_noerr(result
, exit
);
268 require_action(found
== expected
, exit
, result
= errSecDecode
);
273 static inline OSStatus
ReadAndVerifyShort(const uint8_t**bytes
, size_t*size
, uint16_t expected
)
276 OSStatus result
= ReadShort(bytes
, size
, &found
);
277 require_noerr(result
, exit
);
278 require_action(found
== expected
, exit
, result
= errSecDecode
);
283 static inline OSStatus
ReadAndVerifyMessageType(const uint8_t**bytes
, size_t*size
, OTRMessageType expected
)
285 OTRMessageType found
;
286 OSStatus result
= ReadMessageType(bytes
, size
, &found
);
287 require_noerr(result
, exit
);
288 require_action(found
== expected
, exit
, result
= errSecDecode
);
293 static inline OSStatus
ReadAndVerifyVersion(const uint8_t**bytes
, size_t*size
)
295 return ReadAndVerifyShort(bytes
, size
, kCurrentOTRVersion
);
298 static inline OSStatus
ReadAndVerifyHeader(const uint8_t**bytes
, size_t*size
, OTRMessageType expected
)
300 OSStatus result
= ReadAndVerifyVersion(bytes
, size
);
301 require_noerr(result
, exit
);
303 result
= ReadAndVerifyMessageType(bytes
, size
, expected
);
304 require_noerr(result
, exit
);
310 static inline OSStatus
ReadHeader(const uint8_t**bytes
, size_t*size
, OTRMessageType
*messageType
)
312 OSStatus result
= ReadAndVerifyVersion(bytes
, size
);
313 require_noerr(result
, exit
);
315 result
= ReadMessageType(bytes
, size
, messageType
);
316 require_noerr(result
, exit
);
322 static inline OSStatus
SizeAndSkipDATA(const uint8_t **bytes
, size_t *size
,
323 const uint8_t **dataBytes
, size_t *dataSize
)
327 result
= ReadLong(bytes
, size
, &sizeRead
);
329 require_noerr(result
, exit
);
330 require_action(sizeRead
<= *size
, exit
, result
= errSecDecode
);
332 *dataSize
= sizeRead
;
340 static inline OSStatus
SizeAndSkipMPI(const uint8_t **bytes
, size_t *size
,
341 const uint8_t **mpiBytes
, size_t *mpiSize
)
343 // MPIs looke like data for skipping.
344 return SizeAndSkipDATA(bytes
, size
, mpiBytes
, mpiSize
);
349 // Appending functions
351 static inline void AppendLongLong(CFMutableDataRef appendTo
, uint64_t value
)
353 uint8_t bigEndian
[sizeof(value
)] = { value
>> 56, value
>> 48, value
>> 40, value
>> 32,
354 value
>> 24, value
>> 16, value
>> 8 , value
>> 0 };
356 CFDataAppendBytes(appendTo
, bigEndian
, sizeof(bigEndian
));
359 static inline void AppendLong(CFMutableDataRef appendTo
, uint32_t value
)
361 uint8_t bigEndian
[sizeof(value
)] = { value
>> 24, value
>> 16, value
>> 8, value
};
363 CFDataAppendBytes(appendTo
, bigEndian
, sizeof(bigEndian
));
366 static inline void AppendShort(CFMutableDataRef appendTo
, uint16_t value
)
368 uint8_t bigEndian
[sizeof(value
)] = { value
>> 8, value
};
370 CFDataAppendBytes(appendTo
, bigEndian
, sizeof(bigEndian
));
373 static inline void AppendByte(CFMutableDataRef appendTo
, uint8_t byte
)
375 CFDataAppendBytes(appendTo
, &byte
, 1);
378 static inline void AppendMessageType(CFMutableDataRef appendTo
, OTRMessageType type
)
380 AppendByte(appendTo
, type
);
383 static inline void AppendMPI(CFMutableDataRef appendTo
, cc_size n
, const cc_unit
*x
)
385 size_t size
= ccn_write_uint_size(n
, x
);
386 /* 64 bits cast: we are appending an identity, whose size is hardcoded and less then 2^32 bytes */
387 /* Worst case is we encoded a truncated length. No security issue. */
388 assert(size
<UINT32_MAX
); /* Debug check */
389 AppendLong(appendTo
, (uint32_t)size
);
390 assert(((CFIndex
)size
) >= 0);
391 uint8_t* insertionPtr
= CFDataIncreaseLengthAndGetMutableBytes(appendTo
, (CFIndex
)size
);
392 ccn_write_uint(n
, x
, size
, insertionPtr
);
395 static inline void AppendDATA(CFMutableDataRef appendTo
, size_t size
, const uint8_t*data
)
397 /* 64 bits cast: we are appending Public Key or Signature, whose sizes are hardcoded and less then 2^32 bytes */
398 /* Worst case is we encoded a truncated length. No security issue. */
399 assert(size
<=UINT32_MAX
); /* Debug check */
400 AppendLong(appendTo
, (uint32_t)size
);
401 assert(((CFIndex
)size
) >= 0);
402 CFDataAppendBytes(appendTo
, data
, (CFIndex
)size
);
405 static inline void AppendCFDataAsDATA(CFMutableDataRef appendTo
, CFDataRef dataToAppend
)
407 AppendDATA(appendTo
, (size_t)CFDataGetLength(dataToAppend
), CFDataGetBytePtr(dataToAppend
));
410 static inline void AppendPublicKey(CFMutableDataRef appendTo
, SecOTRPublicIdentityRef publicId
)
412 AppendShort(appendTo
, 0xF000); // Custom type reserved by no one
414 CFMutableDataRef serializedID
= CFDataCreateMutable(kCFAllocatorDefault
, 0);
416 SecOTRPIAppendSerialization(publicId
, serializedID
, NULL
);
417 AppendDATA(appendTo
, (size_t)CFDataGetLength(serializedID
), CFDataGetBytePtr(serializedID
));
419 CFReleaseNull(serializedID
);
422 static inline void AppendVersion(CFMutableDataRef appendTo
)
424 AppendShort(appendTo
, kCurrentOTRVersion
);
427 static inline void AppendHeader(CFMutableDataRef appendTo
, OTRMessageType type
)
429 AppendVersion(appendTo
);
430 AppendMessageType(appendTo
, type
);