]> git.saurik.com Git - apple/security.git/blob - sec/Security/SecOTRPacketData.h
Security-55471.14.8.tar.gz
[apple/security.git] / sec / Security / SecOTRPacketData.h
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
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);
32
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);
37
38
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);
48
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);
57
58
59 //
60 // Inline implementation
61 //
62
63 static uint16_t kCurrentOTRVersion = 0x2;
64
65 static 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;
85 fail:
86 return errSecParam;
87 }
88
89 static 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;
105 fail:
106 return errSecParam;
107 }
108
109 static 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;
123 fail:
124 return errSecParam;
125 }
126
127 static 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;
140 fail:
141 return errSecParam;
142 }
143
144 static 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;
153 fail:
154 return result;
155 }
156
157 static 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;
176 fail:
177 return errSecParam;
178
179 }
180
181 static 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;
201 fail:
202 return errSecParam;
203
204 }
205
206 static 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;
235 fail:
236 return errSecParam;
237
238 }
239
240 static 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
255 exit:
256 return result;
257 }
258
259
260 //
261 // Parse and verify functions
262 //
263 static 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);
269 exit:
270 return result;
271 }
272
273 static 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);
279 exit:
280 return result;
281 }
282
283 static 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);
289 exit:
290 return result;
291 }
292
293 static inline OSStatus ReadAndVerifyVersion(const uint8_t**bytes, size_t*size)
294 {
295 return ReadAndVerifyShort(bytes, size, kCurrentOTRVersion);
296 }
297
298 static 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
306 exit:
307 return result;
308 }
309
310 static 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
318 exit:
319 return result;
320 }
321
322 static 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;
336 exit:
337 return result;
338 }
339
340 static 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 //
351 static 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
359 static 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
366 static 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
373 static inline void AppendByte(CFMutableDataRef appendTo, uint8_t byte)
374 {
375 CFDataAppendBytes(appendTo, &byte, 1);
376 }
377
378 static inline void AppendMessageType(CFMutableDataRef appendTo, OTRMessageType type)
379 {
380 AppendByte(appendTo, type);
381 }
382
383 static 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
395 static 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
405 static inline void AppendCFDataAsDATA(CFMutableDataRef appendTo, CFDataRef dataToAppend)
406 {
407 AppendDATA(appendTo, (size_t)CFDataGetLength(dataToAppend), CFDataGetBytePtr(dataToAppend));
408 }
409
410 static 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
422 static inline void AppendVersion(CFMutableDataRef appendTo)
423 {
424 AppendShort(appendTo, kCurrentOTRVersion);
425 }
426
427 static inline void AppendHeader(CFMutableDataRef appendTo, OTRMessageType type)
428 {
429 AppendVersion(appendTo);
430 AppendMessageType(appendTo, type);
431 }
432
433 __END_DECLS
434
435 #endif