3 // libsecurity_libSecOTR
5 // Created by Mitch Adler on 2/23/11.
6 // Copyright 2011 Apple Inc. All rights reserved.
9 #include "SecOTRSessionPriv.h"
10 #include "SecOTRPackets.h"
13 #include "SecOTRIdentityPriv.h"
15 //*****************************************#include "SecCFWrappers.h"
16 #include "SecOTRPacketData.h"
17 #include "SecOTRDHKey.h"
19 #ifdef USECOMMONCRYPTO
20 #include <CommonCrypto/CommonHMAC.h>
23 #include <corecrypto/ccn.h>
24 #include <corecrypto/ccdigest.h>
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>
36 static inline void AppendSHA256HMAC(CFMutableDataRef appendTo
,
42 uint8_t *to
= CFDataIncreaseLengthAndGetMutableBytes(appendTo
, CCSHA256_OUTPUT_SIZE
);
44 #ifdef USECOMMONCRYPTO
45 CCHmac(kCCHmacAlgSHA256
, key
, keybytes
, from
, howMuch
, to
);
47 cchmac(ccsha256_di(), keybytes
, key
, howMuch
, from
, to
);
51 // First 160 bits of the HMAC
52 static inline void AppendSHA256HMAC_160(CFMutableDataRef appendTo
,
58 AppendSHA256HMAC(appendTo
, keySize
, key
, howMuch
, from
);
59 const CFIndex bytesToRemove
= CCSHA256_OUTPUT_SIZE
- kSHA256HMAC160Bytes
;
60 const CFRange rangeToDelete
= CFRangeMake(CFDataGetLength(appendTo
) - bytesToRemove
, bytesToRemove
);
62 CFDataDeleteBytes(appendTo
, rangeToDelete
);
65 static inline void DeriveAndAppendSHA256HMAC(CFMutableDataRef appendTo
,
72 size_t localKeySize
= CCSHA256_OUTPUT_SIZE
;
73 uint8_t localKey
[localKeySize
];
75 DeriveOTR256BitsFromS(whichKey
, sN
, s
, localKeySize
, localKey
);
77 AppendSHA256HMAC(appendTo
, localKeySize
, localKey
, howMuch
, from
);
79 bzero(localKey
, localKeySize
);
82 static inline void DeriveAndAppendSHA256HMAC_160(CFMutableDataRef appendTo
,
89 size_t localKeySize
= CCSHA256_OUTPUT_SIZE
;
90 uint8_t localKey
[localKeySize
];
92 DeriveOTR256BitsFromS(whichKey
, sN
, s
, localKeySize
, localKey
);
94 AppendSHA256HMAC_160(appendTo
, localKeySize
, localKey
, howMuch
, from
);
96 bzero(localKey
, sizeof(localKey
));
103 void SecOTRAppendDHMessage(SecOTRSessionRef session
,
104 CFMutableDataRef appendTo
)
107 // Message Type: kDHMessage (0x02)
108 // AES_CTR(r, 0) of G^X MPI
113 CFMutableDataRef gxmpi
= CFDataCreateMutable(kCFAllocatorDefault
, 0);
116 AppendHeader(appendTo
, kDHMessage
);
118 SecFDHKAppendPublicSerialization(session
->_myKey
, gxmpi
);
120 size_t gxmpiSize
= (size_t)CFDataGetLength(gxmpi
);
122 CFReleaseNull(gxmpi
);
125 const uint8_t* gxmpiLocation
= CFDataGetBytePtr(gxmpi
);
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
);
134 AppendLong(appendTo
, CCSHA256_OUTPUT_SIZE
);
135 uint8_t* hashLocation
= CFDataIncreaseLengthAndGetMutableBytes(appendTo
, CCSHA256_OUTPUT_SIZE
);
137 #ifdef USECOMMONCRYPTO
138 (void) CC_SHA256(gxmpiLocation
, (uint32_t)gxmpiSize
, hashLocation
);
140 ccdigest(ccsha256_di(), gxmpiSize
, gxmpiLocation
, hashLocation
);
142 CFReleaseNull(gxmpi
);
145 void SecOTRAppendDHKeyMessage(SecOTRSessionRef session
,
146 CFMutableDataRef appendTo
)
149 // Message Type: kDHKeyMessage (0x0A)
153 AppendHeader(appendTo
, kDHKeyMessage
);
154 SecFDHKAppendPublicSerialization(session
->_myKey
, appendTo
);
157 static uint8_t* AppendEncryptedSignature(SecOTRSessionRef session
,
160 CFMutableDataRef appendTo
)
162 CFMutableDataRef signature
= CFDataCreateMutable(kCFAllocatorDefault
, 0);
163 CFMutableDataRef mbData
= CFDataCreateMutable(kCFAllocatorDefault
, 0);
164 CFMutableDataRef mb
= CFDataCreateMutable(kCFAllocatorDefault
, 0);
166 SecFDHKAppendPublicSerialization(session
->_myKey
, mbData
);
167 SecPDHKAppendSerialization(session
->_theirKey
, mbData
);
169 CFIndex publicKeyOffset
= CFDataGetLength(mbData
);
171 SecOTRPublicIdentityRef myPublic
= SecOTRPublicIdentityCopyFromPrivate(kCFAllocatorDefault
, session
->_me
, NULL
);
172 AppendPublicKey(mbData
, myPublic
);
173 CFReleaseNull(myPublic
);
175 AppendLong(mbData
, session
->_keyID
);
177 DeriveAndAppendSHA256HMAC(mb
,
178 kExponentiationUnits
, s
,
179 usePrime
? kM1Prime
: kM1
,
180 (size_t)CFDataGetLength(mbData
), CFDataGetBytePtr(mbData
));
182 CFDataDeleteBytes(mbData
, CFRangeMake(0, publicKeyOffset
));
184 CFMutableDataRef xb
= mbData
; mbData
= NULL
;
185 SecOTRFIAppendSignature(session
->_me
, mb
, signature
, NULL
);
188 AppendCFDataAsDATA(xb
, signature
);
189 CFReleaseNull(signature
);
191 CFIndex dataLength
= CFDataGetLength(xb
);
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
);
199 uint8_t c
[kOTRAuthKeyBytes
];
200 DeriveOTR128BitPairFromS(kCs
, kExponentiationUnits
, s
,
201 sizeof(c
), usePrime
? NULL
: c
,
202 sizeof(c
), usePrime
? c
: NULL
);
204 AES_CTR_IV0_Transform(sizeof(c
), c
,
205 (size_t)dataLength
, CFDataGetBytePtr(xb
),
210 return CFDataGetMutableBytePtr(appendTo
) + signatureStartIndex
;
214 static void AppendMACedEncryptedSignature(SecOTRSessionRef session
,
216 CFMutableDataRef appendTo
)
219 cc_unit s
[kExponentiationUnits
];
221 SecPDHKeyGenerateS(session
->_myKey
, session
->_theirKey
, s
);
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
;
228 DeriveAndAppendSHA256HMAC_160(appendTo
,
229 kExponentiationUnits
, s
,
230 usePrime
? kM2Prime
: kM2
,
231 signatureSize
, signatureStart
);
236 void SecOTRAppendRevealSignatureMessage(SecOTRSessionRef session
,
237 CFMutableDataRef appendTo
)
240 // Message Type: kRevealSignatureMessage (0x11)
244 AppendHeader(appendTo
, kRevealSignatureMessage
);
246 AppendLong(appendTo
, kOTRAuthKeyBytes
);
247 uint8_t* keyPosition
= CFDataIncreaseLengthAndGetMutableBytes(appendTo
, kOTRAuthKeyBytes
);
248 memcpy(keyPosition
, session
->_r
, kOTRAuthKeyBytes
);
250 AppendMACedEncryptedSignature(session
, false, appendTo
);
253 void SecOTRAppendSignatureMessage(SecOTRSessionRef session
,
254 CFMutableDataRef appendTo
)
257 // Message Type: kSignatureMessage (0x12)
261 AppendHeader(appendTo
, kSignatureMessage
);
262 AppendMACedEncryptedSignature(session
, true, appendTo
);