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