]> git.saurik.com Git - apple/security.git/blob - OSX/sec/Security/SecOTRPackets.c
Security-58286.240.4.tar.gz
[apple/security.git] / OSX / sec / Security / SecOTRPackets.c
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 #include "SecOTRSessionPriv.h"
26 #include "SecOTRPackets.h"
27
28 #include "SecOTR.h"
29 #include "SecOTRIdentityPriv.h"
30
31 //*****************************************#include "SecCFWrappers.h"
32 #include "SecOTRPacketData.h"
33 #include "SecOTRDHKey.h"
34
35 #include <utilities/SecCFWrappers.h>
36
37 #include <corecrypto/ccn.h>
38 #include <corecrypto/ccdigest.h>
39
40 #include <corecrypto/ccaes.h>
41 #include <corecrypto/ccmode.h>
42 #include <corecrypto/ccmode_factory.h>
43 #include <corecrypto/cchmac.h>
44 #include <corecrypto/ccsha2.h>
45
46 //
47 // Crypto functions
48 //
49
50 static inline void AppendSHA256HMAC(CFMutableDataRef appendTo,
51 size_t keybytes,
52 const uint8_t* key,
53 size_t howMuch,
54 const uint8_t* from)
55 {
56 uint8_t *to = CFDataIncreaseLengthAndGetMutableBytes(appendTo, CCSHA256_OUTPUT_SIZE);
57
58 cchmac(ccsha256_di(), keybytes, key, howMuch, from, to);
59 }
60
61 // First 160 bits of the HMAC
62 static inline void AppendSHA256HMAC_160(CFMutableDataRef appendTo,
63 size_t keySize,
64 const uint8_t* key,
65 size_t howMuch,
66 const uint8_t* from)
67 {
68 AppendSHA256HMAC(appendTo, keySize, key, howMuch, from);
69 const CFIndex bytesToRemove = CCSHA256_OUTPUT_SIZE - kSHA256HMAC160Bytes;
70 const CFRange rangeToDelete = CFRangeMake(CFDataGetLength(appendTo) - bytesToRemove, bytesToRemove);
71
72 CFDataDeleteBytes(appendTo, rangeToDelete);
73 }
74
75 static inline void DeriveAndAppendSHA256HMAC(CFMutableDataRef appendTo,
76 cc_size sN,
77 const cc_unit* s,
78 OTRKeyType whichKey,
79 size_t howMuch,
80 const uint8_t* from)
81 {
82 size_t localKeySize = CCSHA256_OUTPUT_SIZE;
83 uint8_t localKey[localKeySize];
84
85 DeriveOTR256BitsFromS(whichKey, sN, s, localKeySize, localKey);
86
87 AppendSHA256HMAC(appendTo, localKeySize, localKey, howMuch, from);
88
89 bzero(localKey, localKeySize);
90 }
91
92 static inline void DeriveAndAppendSHA256HMAC_160(CFMutableDataRef appendTo,
93 cc_size sN,
94 const cc_unit* s,
95 OTRKeyType whichKey,
96 size_t howMuch,
97 const uint8_t* from)
98 {
99 size_t localKeySize = CCSHA256_OUTPUT_SIZE;
100 uint8_t localKey[localKeySize];
101
102 DeriveOTR256BitsFromS(whichKey, sN, s, localKeySize, localKey);
103
104 AppendSHA256HMAC_160(appendTo, localKeySize, localKey, howMuch, from);
105
106 bzero(localKey, sizeof(localKey));
107 }
108
109 //
110 // Message creators
111 //
112
113 void SecOTRAppendDHMessage(SecOTRSessionRef session,
114 CFMutableDataRef appendTo)
115 {
116 //
117 // Message Type: kDHMessage (0x02)
118 // AES_CTR(r, 0) of G^X MPI
119 // SHA256(gxmpi)
120 //
121
122 if(!session) return;
123 CFMutableDataRef gxmpi = CFDataCreateMutable(kCFAllocatorDefault, 0);
124 if(!gxmpi) return;
125
126 AppendHeader(appendTo, kDHMessage);
127
128 SecFDHKAppendPublicSerialization(session->_myKey, gxmpi);
129
130 size_t gxmpiSize = (size_t)CFDataGetLength(gxmpi);
131 if(gxmpiSize == 0) {
132 CFReleaseNull(gxmpi);
133 return;
134 }
135 const uint8_t* gxmpiLocation = CFDataGetBytePtr(gxmpi);
136
137 /* 64 bits cast: gxmpiSize is the size of the EC public key, which is hardcoded and never more than 2^32 bytes. */
138 assert(gxmpiSize<UINT32_MAX); /* debug check only */
139 AppendLong(appendTo, (uint32_t)gxmpiSize);
140 assert(gxmpiSize<INT32_MAX);
141 uint8_t* encGxmpiLocation = CFDataIncreaseLengthAndGetMutableBytes(appendTo, (CFIndex)gxmpiSize);
142 AES_CTR_IV0_Transform(sizeof(session->_r), session->_r, gxmpiSize, gxmpiLocation, encGxmpiLocation);
143
144 AppendLong(appendTo, CCSHA256_OUTPUT_SIZE);
145 uint8_t* hashLocation = CFDataIncreaseLengthAndGetMutableBytes(appendTo, CCSHA256_OUTPUT_SIZE);
146
147 ccdigest(ccsha256_di(), gxmpiSize, gxmpiLocation, hashLocation);
148
149 CFReleaseNull(gxmpi);
150 }
151
152 void SecOTRAppendDHKeyMessage(SecOTRSessionRef session,
153 CFMutableDataRef appendTo)
154 {
155 //
156 // Message Type: kDHKeyMessage (0x0A)
157 // G^X Data MPI
158 //
159
160 AppendHeader(appendTo, kDHKeyMessage);
161 SecFDHKAppendPublicSerialization(session->_myKey, appendTo);
162 }
163
164 static uint8_t* AppendEncryptedSignature(SecOTRSessionRef session,
165 const cc_unit* s,
166 bool usePrime,
167 CFMutableDataRef appendTo)
168 {
169 CFMutableDataRef signature = CFDataCreateMutable(kCFAllocatorDefault, 0);
170 CFMutableDataRef mbData = CFDataCreateMutable(kCFAllocatorDefault, 0);
171 CFMutableDataRef mb = CFDataCreateMutable(kCFAllocatorDefault, 0);
172
173 SecFDHKAppendPublicSerialization(session->_myKey, mbData);
174 SecPDHKAppendSerialization(session->_theirKey, mbData);
175
176 CFIndex publicKeyOffset = CFDataGetLength(mbData);
177
178 SecOTRPublicIdentityRef myPublic = SecOTRPublicIdentityCopyFromPrivate(kCFAllocatorDefault, session->_me, NULL);
179 AppendPublicKey(mbData, myPublic);
180 CFReleaseNull(myPublic);
181
182 AppendLong(mbData, session->_keyID);
183
184 DeriveAndAppendSHA256HMAC(mb,
185 kExponentiationUnits, s,
186 usePrime ? kM1Prime : kM1,
187 (size_t)CFDataGetLength(mbData), CFDataGetBytePtr(mbData));
188
189 CFDataDeleteBytes(mbData, CFRangeMake(0, publicKeyOffset));
190
191 CFMutableDataRef xb = mbData; mbData = NULL;
192 SecOTRFIAppendSignature(session->_me, mb, signature, NULL);
193 CFReleaseNull(mb);
194
195 AppendCFDataAsDATA(xb, signature);
196 CFReleaseNull(signature);
197
198 CFIndex dataLength = CFDataGetLength(xb);
199
200 CFIndex signatureStartIndex = CFDataGetLength(appendTo);
201 /* 64 bits cast: We are appending the signature we just generated, which is never bigger than 2^32 bytes. */
202 assert(((unsigned long)dataLength)<=UINT32_MAX); /* debug check, correct as long as CFIndex is a signed long */
203 AppendLong(appendTo, (uint32_t)dataLength);
204 uint8_t *destination = CFDataIncreaseLengthAndGetMutableBytes(appendTo, dataLength);
205
206 uint8_t c[kOTRAuthKeyBytes];
207 DeriveOTR128BitPairFromS(kCs, kExponentiationUnits, s,
208 sizeof(c), usePrime ? NULL : c,
209 sizeof(c), usePrime ? c : NULL);
210
211 AES_CTR_IV0_Transform(sizeof(c), c,
212 (size_t)dataLength, CFDataGetBytePtr(xb),
213 destination);
214 bzero(c, sizeof(c));
215 CFReleaseNull(xb);
216
217 return CFDataGetMutableBytePtr(appendTo) + signatureStartIndex;
218 }
219
220
221 static void AppendMACedEncryptedSignature(SecOTRSessionRef session,
222 bool usePrime,
223 CFMutableDataRef appendTo)
224 {
225
226 cc_unit s[kExponentiationUnits];
227
228 SecPDHKeyGenerateS(session->_myKey, session->_theirKey, s);
229
230 CFIndex signatureStartOffset = CFDataGetLength(appendTo);
231 const uint8_t *signatureStart = AppendEncryptedSignature(session, s, usePrime, appendTo);
232 size_t signatureSize = (size_t)CFDataGetLength(appendTo) - (size_t)signatureStartOffset;
233
234
235 DeriveAndAppendSHA256HMAC_160(appendTo,
236 kExponentiationUnits, s,
237 usePrime ? kM2Prime : kM2,
238 signatureSize, signatureStart);
239 bzero(s, sizeof(s));
240 }
241
242
243 void SecOTRAppendRevealSignatureMessage(SecOTRSessionRef session,
244 CFMutableDataRef appendTo)
245 {
246 //
247 // Message Type: kRevealSignatureMessage (0x11)
248 // G^X Data MPI
249 //
250
251 AppendHeader(appendTo, kRevealSignatureMessage);
252
253 AppendLong(appendTo, kOTRAuthKeyBytes);
254 uint8_t* keyPosition = CFDataIncreaseLengthAndGetMutableBytes(appendTo, kOTRAuthKeyBytes);
255 memcpy(keyPosition, session->_r, kOTRAuthKeyBytes);
256
257 AppendMACedEncryptedSignature(session, false, appendTo);
258 }
259
260 void SecOTRAppendSignatureMessage(SecOTRSessionRef session,
261 CFMutableDataRef appendTo)
262 {
263 //
264 // Message Type: kSignatureMessage (0x12)
265 // G^X Data MPI
266 //
267
268 AppendHeader(appendTo, kSignatureMessage);
269 AppendMACedEncryptedSignature(session, true, appendTo);
270 }
271