]> git.saurik.com Git - apple/security.git/blame - sec/Security/SecOTRPacketData.h
Security-55471.14.4.tar.gz
[apple/security.git] / sec / Security / SecOTRPacketData.h
CommitLineData
427c49bc
A
1//
2// SecOTRPacketData.h
3// libsecurity_libSecOTR
4//
5// Created by Mitch Adler on 2/26/11.
6// Copyright 2011 Apple Inc. All rights reserved.
7//
8
9#ifndef _SECOTRPACKETDATA_H_
10#define _SECOTRPACKETDATA_H_
11
12#include <CoreFoundation/CFBase.h>
13#include <CoreFoundation/CFRuntime.h>
14#include <CoreFoundation/CFData.h>
15
16#include <corecrypto/ccn.h>
17
18#include <CommonCrypto/CommonDigest.h>
19
20#include <Security/SecBase.h>
21
22#include <utilities/SecCFWrappers.h>
23#include <Security/SecOTRPackets.h>
24
25#include <AssertMacros.h>
26
27__BEGIN_DECLS
28
29static OSStatus ReadAndVerifyByte(const uint8_t**bytes, size_t*size, uint8_t expected);
30static OSStatus ReadAndVerifyShort(const uint8_t**bytes, size_t*size, uint16_t expected);
31static OSStatus ReadAndVerifyMessageType(const uint8_t**bytes, size_t*size, OTRMessageType expected);
32
33static OSStatus SizeAndSkipDATA(const uint8_t **bytes, size_t *size,
34 const uint8_t **dataBytes, size_t *dataSize);
35static OSStatus SizeAndSkipMPI(const uint8_t **bytes, size_t *size,
36 const uint8_t **mpiBytes, size_t *mpiSize);
37
38
39static OSStatus ReadLongLong(const uint8_t**bytesPtr, size_t*sizePtr, uint64_t* value);
40static OSStatus ReadLong(const uint8_t**bytesPtr, size_t*sizePtr, uint32_t* value);
41static OSStatus ReadShort(const uint8_t**bytesPtr, size_t*sizePtr, uint16_t* value);
42static OSStatus ReadByte(const uint8_t**bytesPtr, size_t*sizePtr, uint8_t* value);
43static OSStatus ReadMessageType(const uint8_t**bytesPtr, size_t*sizePtr, OTRMessageType* type);
44static OSStatus ReadMPI(const uint8_t**bytesPtr, size_t*sizePtr, cc_size n, cc_unit *x);
45static OSStatus ReadDATA(const uint8_t**bytesPtr, size_t*sizePtr, size_t* dataSize, uint8_t* data);
46static OSStatus CreatePublicKey(const uint8_t**bytesPtr, size_t*sizePtr, SecOTRPublicIdentityRef* publicId);
47static CFMutableDataRef CFDataCreateMutableFromOTRDATA(CFAllocatorRef allocator, const uint8_t**bytesPtr, size_t*sizePtr);
48
49static void AppendLongLong(CFMutableDataRef appendTo, uint64_t value);
50static void AppendLong(CFMutableDataRef appendTo, uint32_t value);
51static void AppendShort(CFMutableDataRef appendTo, uint16_t value);
52static void AppendByte(CFMutableDataRef appendTo, uint8_t type);
53static void AppendMessageType(CFMutableDataRef appendTo, OTRMessageType type);
54static void AppendMPI(CFMutableDataRef appendTo, cc_size n, const cc_unit *x);
55static void AppendDATA(CFMutableDataRef appendTo, size_t size, const uint8_t*data);
56static void AppendPublicKey(CFMutableDataRef appendTo, SecOTRPublicIdentityRef publicId);
57
58
59//
60// Inline implementation
61//
62
63static uint16_t kCurrentOTRVersion = 0x2;
64
65static inline OSStatus ReadLongLong(const uint8_t**bytesPtr, size_t*sizePtr, uint64_t* value)
66{
67 require(bytesPtr != NULL, fail);
68 require(sizePtr != NULL, fail);
69 require(value != NULL, fail);
70 require(*sizePtr >= 4, fail);
71
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;
80
81 *bytesPtr += 8;
82 *sizePtr -= 8;
83
84 return errSecSuccess;
85fail:
86 return errSecParam;
87}
88
89static inline OSStatus ReadLong(const uint8_t**bytesPtr, size_t*sizePtr, uint32_t* value)
90{
91 require(bytesPtr != NULL, fail);
92 require(sizePtr != NULL, fail);
93 require(value != NULL, fail);
94 require(*sizePtr >= 4, fail);
95
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;
100
101 *bytesPtr += 4;
102 *sizePtr -= 4;
103
104 return errSecSuccess;
105fail:
106 return errSecParam;
107}
108
109static inline OSStatus ReadShort(const uint8_t**bytesPtr, size_t*sizePtr, uint16_t* value)
110{
111 require(bytesPtr != NULL, fail);
112 require(sizePtr != NULL, fail);
113 require(value != NULL, fail);
114 require(*sizePtr >= 2, fail);
115
116 *value = (*bytesPtr)[0] << 8 |
117 (*bytesPtr)[1] << 0;
118
119 *bytesPtr += 2;
120 *sizePtr -= 2;
121
122 return errSecSuccess;
123fail:
124 return errSecParam;
125}
126
127static inline OSStatus ReadByte(const uint8_t**bytesPtr, size_t*sizePtr, uint8_t* value)
128{
129 require(bytesPtr != NULL, fail);
130 require(sizePtr != NULL, fail);
131 require(value != NULL, fail);
132 require(*sizePtr >= 1, fail);
133
134 *value = *bytesPtr[0];
135
136 *bytesPtr += 1;
137 *sizePtr -= 1;
138
139 return errSecSuccess;
140fail:
141 return errSecParam;
142}
143
144static inline OSStatus ReadMessageType(const uint8_t**bytesPtr, size_t*sizePtr, OTRMessageType* type)
145{
146 OSStatus result = errSecParam;
147 uint8_t value;
148
149 require(type != NULL, fail);
150 require_noerr(result = ReadByte(bytesPtr, sizePtr, &value), fail);
151
152 *type = value;
153fail:
154 return result;
155}
156
157static inline OSStatus ReadMPI(const uint8_t**bytesPtr, size_t*sizePtr, cc_size n, cc_unit *x)
158{
159 require(bytesPtr != NULL, fail);
160 require(sizePtr != NULL, fail);
161 require(x != NULL, fail);
162 require(*sizePtr >= 5, fail);
163
164 uint32_t mpiLength;
165
166 ReadLong(bytesPtr, sizePtr, &mpiLength);
167
168 require(mpiLength <= *sizePtr, fail);
169
170 ccn_read_uint(n, x, mpiLength, *bytesPtr);
171
172 *bytesPtr += mpiLength;
173 *sizePtr -= mpiLength;
174
175 return errSecSuccess;
176fail:
177 return errSecParam;
178
179}
180
181static inline OSStatus ReadDATA(const uint8_t**bytesPtr, size_t*sizePtr, size_t* dataSize, uint8_t* data)
182{
183 require(bytesPtr != NULL, fail);
184 require(sizePtr != NULL, fail);
185 require(data != NULL, fail);
186 require(*sizePtr >= 5, fail);
187
188 uint32_t dataLength;
189
190 ReadLong(bytesPtr, sizePtr, &dataLength);
191
192 require(dataLength <= *sizePtr, fail);
193 memmove(data, bytesPtr, dataLength);
194
195 *bytesPtr += dataLength;
196 *sizePtr -= dataLength;
197
198 *dataSize = dataLength;
199
200 return errSecSuccess;
201fail:
202 return errSecParam;
203
204}
205
206static inline OSStatus CreatePublicKey(const uint8_t**bytesPtr, size_t*sizePtr, SecOTRPublicIdentityRef* publicId)
207{
208 require(bytesPtr != NULL, fail);
209 require(sizePtr != NULL, fail);
210 require(publicId != NULL, fail);
211 require(*sizePtr >= 7, fail);
212
213 uint16_t type = 0;
214 ReadShort(bytesPtr, sizePtr, &type);
215
216 require(type == 0xF000, fail);
217 require(*sizePtr >= 5, fail);
218
219 uint32_t serializedIDLength = 0;
220 ReadLong(bytesPtr, sizePtr, &serializedIDLength);
221
222 require(*sizePtr >= serializedIDLength, fail);
223 require(((CFIndex)serializedIDLength) >= 0, fail);
224
225 CFDataRef serializedBytes = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, *bytesPtr, (CFIndex)serializedIDLength, kCFAllocatorNull);
226
227 *publicId = SecOTRPublicIdentityCreateFromData(kCFAllocatorDefault, serializedBytes, NULL);
228
229 *bytesPtr += serializedIDLength;
230 *sizePtr -= serializedIDLength;
231
232 CFReleaseNull(serializedBytes);
233
234 return errSecSuccess;
235fail:
236 return errSecParam;
237
238}
239
240static inline CFMutableDataRef CFDataCreateMutableFromOTRDATA(CFAllocatorRef allocator, const uint8_t**bytesPtr, size_t*sizePtr)
241{
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);
247
248 result = CFDataCreateMutable(allocator, 0);
249
250 CFDataAppendBytes(result, *bytesPtr, (CFIndex)sizeInStream);
251
252 *bytesPtr += sizeInStream;
253 *sizePtr += sizeInStream;
254
255exit:
256 return result;
257}
258
259
260//
261// Parse and verify functions
262//
263static inline OSStatus ReadAndVerifyByte(const uint8_t**bytes, size_t*size, uint8_t expected)
264{
265 uint8_t found;
266 OSStatus result = ReadByte(bytes, size, &found);
267 require_noerr(result, exit);
268 require_action(found == expected, exit, result = errSecDecode);
269exit:
270 return result;
271}
272
273static inline OSStatus ReadAndVerifyShort(const uint8_t**bytes, size_t*size, uint16_t expected)
274{
275 uint16_t found;
276 OSStatus result = ReadShort(bytes, size, &found);
277 require_noerr(result, exit);
278 require_action(found == expected, exit, result = errSecDecode);
279exit:
280 return result;
281}
282
283static inline OSStatus ReadAndVerifyMessageType(const uint8_t**bytes, size_t*size, OTRMessageType expected)
284{
285 OTRMessageType found;
286 OSStatus result = ReadMessageType(bytes, size, &found);
287 require_noerr(result, exit);
288 require_action(found == expected, exit, result = errSecDecode);
289exit:
290 return result;
291}
292
293static inline OSStatus ReadAndVerifyVersion(const uint8_t**bytes, size_t*size)
294{
295 return ReadAndVerifyShort(bytes, size, kCurrentOTRVersion);
296}
297
298static inline OSStatus ReadAndVerifyHeader(const uint8_t**bytes, size_t*size, OTRMessageType expected)
299{
300 OSStatus result = ReadAndVerifyVersion(bytes, size);
301 require_noerr(result, exit);
302
303 result = ReadAndVerifyMessageType(bytes, size, expected);
304 require_noerr(result, exit);
305
306exit:
307 return result;
308}
309
310static inline OSStatus ReadHeader(const uint8_t**bytes, size_t*size, OTRMessageType *messageType)
311{
312 OSStatus result = ReadAndVerifyVersion(bytes, size);
313 require_noerr(result, exit);
314
315 result = ReadMessageType(bytes, size, messageType);
316 require_noerr(result, exit);
317
318exit:
319 return result;
320}
321
322static inline OSStatus SizeAndSkipDATA(const uint8_t **bytes, size_t *size,
323 const uint8_t **dataBytes, size_t *dataSize)
324{
325 OSStatus result;
326 uint32_t sizeRead;
327 result = ReadLong(bytes, size, &sizeRead);
328
329 require_noerr(result, exit);
330 require_action(sizeRead <= *size, exit, result = errSecDecode);
331
332 *dataSize = sizeRead;
333 *dataBytes = *bytes;
334 *bytes += sizeRead;
335 *size -= sizeRead;
336exit:
337 return result;
338}
339
340static inline OSStatus SizeAndSkipMPI(const uint8_t **bytes, size_t *size,
341 const uint8_t **mpiBytes, size_t *mpiSize)
342{
343 // MPIs looke like data for skipping.
344 return SizeAndSkipDATA(bytes, size, mpiBytes, mpiSize);
345}
346
347
348//
349// Appending functions
350//
351static inline void AppendLongLong(CFMutableDataRef appendTo, uint64_t value)
352{
353 uint8_t bigEndian[sizeof(value)] = { value >> 56, value >> 48, value >> 40, value >> 32,
354 value >> 24, value >> 16, value >> 8 , value >> 0 };
355
356 CFDataAppendBytes(appendTo, bigEndian, sizeof(bigEndian));
357}
358
359static inline void AppendLong(CFMutableDataRef appendTo, uint32_t value)
360{
361 uint8_t bigEndian[sizeof(value)] = { value >> 24, value >> 16, value >> 8, value };
362
363 CFDataAppendBytes(appendTo, bigEndian, sizeof(bigEndian));
364}
365
366static inline void AppendShort(CFMutableDataRef appendTo, uint16_t value)
367{
368 uint8_t bigEndian[sizeof(value)] = { value >> 8, value };
369
370 CFDataAppendBytes(appendTo, bigEndian, sizeof(bigEndian));
371}
372
373static inline void AppendByte(CFMutableDataRef appendTo, uint8_t byte)
374{
375 CFDataAppendBytes(appendTo, &byte, 1);
376}
377
378static inline void AppendMessageType(CFMutableDataRef appendTo, OTRMessageType type)
379{
380 AppendByte(appendTo, type);
381}
382
383static inline void AppendMPI(CFMutableDataRef appendTo, cc_size n, const cc_unit *x)
384{
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);
393}
394
395static inline void AppendDATA(CFMutableDataRef appendTo, size_t size, const uint8_t*data)
396{
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);
403}
404
405static inline void AppendCFDataAsDATA(CFMutableDataRef appendTo, CFDataRef dataToAppend)
406{
407 AppendDATA(appendTo, (size_t)CFDataGetLength(dataToAppend), CFDataGetBytePtr(dataToAppend));
408}
409
410static inline void AppendPublicKey(CFMutableDataRef appendTo, SecOTRPublicIdentityRef publicId)
411{
412 AppendShort(appendTo, 0xF000); // Custom type reserved by no one
413
414 CFMutableDataRef serializedID = CFDataCreateMutable(kCFAllocatorDefault, 0);
415
416 SecOTRPIAppendSerialization(publicId, serializedID, NULL);
417 AppendDATA(appendTo, (size_t)CFDataGetLength(serializedID), CFDataGetBytePtr(serializedID));
418
419 CFReleaseNull(serializedID);
420}
421
422static inline void AppendVersion(CFMutableDataRef appendTo)
423{
424 AppendShort(appendTo, kCurrentOTRVersion);
425}
426
427static inline void AppendHeader(CFMutableDataRef appendTo, OTRMessageType type)
428{
429 AppendVersion(appendTo);
430 AppendMessageType(appendTo, type);
431}
432
433__END_DECLS
434
435#endif