3 * Release $Name: MATRIXSSL_1_8_8_OPEN $
5 * SSLv3.0 specific code per http://wp.netscape.com/eng/ssl3.
6 * Primarily dealing with secret generation, message authentication codes
7 * and handshake hashing.
10 * Copyright (c) PeerSec Networks, 2002-2009. All Rights Reserved.
11 * The latest version of this code is available at http://www.matrixssl.org
13 * This software is open source; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * This General Public License does NOT permit incorporating this software
19 * into proprietary programs. If you are unable to comply with the GPL, a
20 * commercial license for this software may be purchased from PeerSec Networks
21 * at http://www.peersec.com
23 * This program is distributed in WITHOUT ANY WARRANTY; without even the
24 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
25 * See the GNU General Public License for more details.
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 * http://www.gnu.org/copyleft/gpl.html
32 /******************************************************************************/
34 #include "matrixInternal.h"
36 /******************************************************************************/
38 Constants used for key generation
40 static const unsigned char SENDER_CLIENT
[5] = "CLNT"; /* 0x434C4E54 */
41 static const unsigned char SENDER_SERVER
[5] = "SRVR"; /* 0x53525652 */
43 static const unsigned char pad1
[48]={
44 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
45 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
46 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
47 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
48 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
49 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36
52 static const unsigned char pad2
[48]={
53 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
54 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
55 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
56 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
57 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
58 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c
61 static const unsigned char *salt
[10]={
62 (const unsigned char *)"A",
63 (const unsigned char *)"BB",
64 (const unsigned char *)"CCC",
65 (const unsigned char *)"DDDD",
66 (const unsigned char *)"EEEEE",
67 (const unsigned char *)"FFFFFF",
68 (const unsigned char *)"GGGGGGG",
69 (const unsigned char *)"HHHHHHHH",
70 (const unsigned char *)"IIIIIIIII",
71 (const unsigned char *)"JJJJJJJJJJ"
74 /******************************************************************************/
76 static int32
createKeyBlock(ssl_t
*ssl
, unsigned char *clientRandom
,
77 unsigned char *serverRandom
,
78 unsigned char *masterSecret
, int32 secretLen
);
80 /******************************************************************************/
82 * Generates all key material.
84 int32
sslDeriveKeys(ssl_t
*ssl
)
86 sslMd5Context_t md5Ctx
;
87 sslSha1Context_t sha1Ctx
;
88 unsigned char buf
[SSL_MD5_HASH_SIZE
+ SSL_SHA1_HASH_SIZE
];
93 If this session is resumed, we want to reuse the master secret to
94 regenerate the key block with the new random values.
96 if (ssl
->flags
& SSL_FLAGS_RESUMED
) {
101 MD5(pre_master_secret + SHA('A' + pre_master_secret +
102 ClientHello.random + ServerHello.random)) +
103 MD5(pre_master_secret + SHA('BB' + pre_master_secret +
104 ClientHello.random + ServerHello.random)) +
105 MD5(pre_master_secret + SHA('CCC' + pre_master_secret +
106 ClientHello.random + ServerHello.random));
108 tmp
= ssl
->sec
.masterSecret
;
109 for (i
= 0; i
< 3; i
++) {
110 matrixSha1Init(&sha1Ctx
);
111 matrixSha1Update(&sha1Ctx
, salt
[i
], i
+ 1);
112 matrixSha1Update(&sha1Ctx
, ssl
->sec
.premaster
, ssl
->sec
.premasterSize
);
113 matrixSha1Update(&sha1Ctx
, ssl
->sec
.clientRandom
, SSL_HS_RANDOM_SIZE
);
114 matrixSha1Update(&sha1Ctx
, ssl
->sec
.serverRandom
, SSL_HS_RANDOM_SIZE
);
115 matrixSha1Final(&sha1Ctx
, buf
);
117 matrixMd5Init(&md5Ctx
);
118 matrixMd5Update(&md5Ctx
, ssl
->sec
.premaster
, ssl
->sec
.premasterSize
);
119 matrixMd5Update(&md5Ctx
, buf
, SSL_SHA1_HASH_SIZE
);
120 matrixMd5Final(&md5Ctx
, tmp
);
121 tmp
+= SSL_MD5_HASH_SIZE
;
123 memset(buf
, 0x0, SSL_MD5_HASH_SIZE
+ SSL_SHA1_HASH_SIZE
);
125 premaster is now allocated for DH reasons. Can free here
127 psFree(ssl
->sec
.premaster
);
128 ssl
->sec
.premaster
= NULL
;
129 ssl
->sec
.premasterSize
= 0;
132 if (createKeyBlock(ssl
, ssl
->sec
.clientRandom
, ssl
->sec
.serverRandom
,
133 ssl
->sec
.masterSecret
, SSL_HS_MASTER_SIZE
) < 0) {
134 matrixStrDebugMsg("Unable to create key block\n", NULL
);
138 return SSL_HS_MASTER_SIZE
;
141 /******************************************************************************/
143 Generate the key block as follows. '+' indicates concatination.
145 MD5(master_secret + SHA(`A' + master_secret +
146 ServerHello.random + ClientHello.random)) +
147 MD5(master_secret + SHA(`BB' + master_secret +
148 ServerHello.random + ClientHello.random)) +
149 MD5(master_secret + SHA(`CCC' + master_secret +
150 ServerHello.random + ClientHello.random)) +
153 static int32
createKeyBlock(ssl_t
*ssl
, unsigned char *clientRandom
,
154 unsigned char *serverRandom
,
155 unsigned char *masterSecret
, int32 secretLen
)
157 sslMd5Context_t md5Ctx
;
158 sslSha1Context_t sha1Ctx
;
159 unsigned char buf
[SSL_MD5_HASH_SIZE
+ SSL_SHA1_HASH_SIZE
];
161 int32 keyIter
, i
, ret
= 0;
165 We must generate enough key material to fill the various keys
167 reqKeyLen
= 2 * ssl
->cipher
->macSize
+
168 2 * ssl
->cipher
->keySize
+
169 2 * ssl
->cipher
->ivSize
;
171 Find the right number of iterations to make the requested length key block
174 while (SSL_MD5_HASH_SIZE
* keyIter
< reqKeyLen
) {
177 if (keyIter
> sizeof(salt
)/sizeof(char*)) {
178 matrixIntDebugMsg("Error: Not enough salt for key length of %d\n",
183 tmp
= ssl
->sec
.keyBlock
;
184 for (i
= 0; i
< keyIter
; i
++) {
185 matrixSha1Init(&sha1Ctx
);
186 matrixSha1Update(&sha1Ctx
, salt
[i
], i
+ 1);
187 matrixSha1Update(&sha1Ctx
, masterSecret
, secretLen
);
188 matrixSha1Update(&sha1Ctx
, serverRandom
, SSL_HS_RANDOM_SIZE
);
189 matrixSha1Update(&sha1Ctx
, clientRandom
, SSL_HS_RANDOM_SIZE
);
190 matrixSha1Final(&sha1Ctx
, buf
);
192 matrixMd5Init(&md5Ctx
);
193 matrixMd5Update(&md5Ctx
, masterSecret
, secretLen
);
194 matrixMd5Update(&md5Ctx
, buf
, SSL_SHA1_HASH_SIZE
);
195 matrixMd5Final(&md5Ctx
, tmp
);
196 tmp
+= SSL_MD5_HASH_SIZE
;
197 ret
+= SSL_MD5_HASH_SIZE
;
199 memset(buf
, 0x0, SSL_MD5_HASH_SIZE
+ SSL_SHA1_HASH_SIZE
);
201 Client and server use different read/write values, with the Client
202 write value being the server read value.
204 if (ssl
->flags
& SSL_FLAGS_SERVER
) {
205 ssl
->sec
.rMACptr
= ssl
->sec
.keyBlock
;
206 ssl
->sec
.wMACptr
= ssl
->sec
.rMACptr
+ ssl
->cipher
->macSize
;
207 ssl
->sec
.rKeyptr
= ssl
->sec
.wMACptr
+ ssl
->cipher
->macSize
;
208 ssl
->sec
.wKeyptr
= ssl
->sec
.rKeyptr
+ ssl
->cipher
->keySize
;
209 ssl
->sec
.rIVptr
= ssl
->sec
.wKeyptr
+ ssl
->cipher
->keySize
;
210 ssl
->sec
.wIVptr
= ssl
->sec
.rIVptr
+ ssl
->cipher
->ivSize
;
212 ssl
->sec
.wMACptr
= ssl
->sec
.keyBlock
;
213 ssl
->sec
.rMACptr
= ssl
->sec
.wMACptr
+ ssl
->cipher
->macSize
;
214 ssl
->sec
.wKeyptr
= ssl
->sec
.rMACptr
+ ssl
->cipher
->macSize
;
215 ssl
->sec
.rKeyptr
= ssl
->sec
.wKeyptr
+ ssl
->cipher
->keySize
;
216 ssl
->sec
.wIVptr
= ssl
->sec
.rKeyptr
+ ssl
->cipher
->keySize
;
217 ssl
->sec
.rIVptr
= ssl
->sec
.wIVptr
+ ssl
->cipher
->ivSize
;
223 /******************************************************************************/
225 Combine the running hash of the handshake mesages with some constants
226 and mix them up a bit more. Output the result to the given buffer.
227 This data will be part of the Finished handshake message.
229 int32
sslGenerateFinishedHash(sslMd5Context_t
*md5
, sslSha1Context_t
*sha1
,
230 unsigned char *masterSecret
,
231 unsigned char *out
, int32 sender
)
233 sslMd5Context_t omd5
;
234 sslSha1Context_t osha1
;
236 unsigned char ihash
[SSL_SHA1_HASH_SIZE
];
239 md5Hash = MD5(master_secret + pad2 +
240 MD5(handshake_messages + sender + master_secret + pad1));
244 (sender
& SSL_FLAGS_SERVER
) ? SENDER_SERVER
: SENDER_CLIENT
, 4);
246 matrixMd5Update(md5
, masterSecret
, SSL_HS_MASTER_SIZE
);
247 matrixMd5Update(md5
, pad1
, sizeof(pad1
));
248 matrixMd5Final(md5
, ihash
);
250 matrixMd5Init(&omd5
);
251 matrixMd5Update(&omd5
, masterSecret
, SSL_HS_MASTER_SIZE
);
252 matrixMd5Update(&omd5
, pad2
, sizeof(pad2
));
253 matrixMd5Update(&omd5
, ihash
, SSL_MD5_HASH_SIZE
);
254 matrixMd5Final(&omd5
, out
);
256 The SHA1 hash is generated in the same way, except only 40 bytes
257 of pad1 and pad2 are used.
258 sha1Hash = SHA1(master_secret + pad2 +
259 SHA1(handshake_messages + sender + master_secret + pad1));
262 matrixSha1Update(sha1
,
263 (sender
& SSL_FLAGS_SERVER
) ? SENDER_SERVER
: SENDER_CLIENT
, 4);
265 matrixSha1Update(sha1
, masterSecret
, SSL_HS_MASTER_SIZE
);
266 matrixSha1Update(sha1
, pad1
, 40);
267 matrixSha1Final(sha1
, ihash
);
269 matrixSha1Init(&osha1
);
270 matrixSha1Update(&osha1
, masterSecret
, SSL_HS_MASTER_SIZE
);
271 matrixSha1Update(&osha1
, pad2
, 40);
272 matrixSha1Update(&osha1
, ihash
, SSL_SHA1_HASH_SIZE
);
273 matrixSha1Final(&osha1
, out
+ SSL_MD5_HASH_SIZE
);
275 return SSL_MD5_HASH_SIZE
+ SSL_SHA1_HASH_SIZE
;
279 /******************************************************************************/
281 SSLv3 uses a method similar to HMAC to generate the SHA1 message MAC.
282 For SHA1, 40 bytes of the pad are used.
284 SHA1(MAC_write_secret + pad2 +
285 SHA1(MAC_write_secret + pad1 + seq_num + length + content));
287 int32
ssl3HMACSha1(unsigned char *key
, unsigned char *seq
,
288 unsigned char type
, unsigned char *data
, int32 len
,
291 sslSha1Context_t sha1
;
292 unsigned char ihash
[SSL_SHA1_HASH_SIZE
];
295 matrixSha1Init(&sha1
);
296 matrixSha1Update(&sha1
, key
, SSL_SHA1_HASH_SIZE
);
297 matrixSha1Update(&sha1
, pad1
, 40);
298 matrixSha1Update(&sha1
, seq
, 8);
300 ihash
[1] = (len
& 0xFF00) >> 8;
301 ihash
[2] = len
& 0xFF;
302 matrixSha1Update(&sha1
, ihash
, 3);
303 matrixSha1Update(&sha1
, data
, len
);
304 matrixSha1Final(&sha1
, ihash
);
306 matrixSha1Init(&sha1
);
307 matrixSha1Update(&sha1
, key
, SSL_SHA1_HASH_SIZE
);
308 matrixSha1Update(&sha1
, pad2
, 40);
309 matrixSha1Update(&sha1
, ihash
, SSL_SHA1_HASH_SIZE
);
310 matrixSha1Final(&sha1
, mac
);
313 Increment sequence number
315 for (i
= 7; i
>= 0; i
--) {
321 return SSL_SHA1_HASH_SIZE
;
323 #endif /* USE_SHA1_MAC */
326 /******************************************************************************/
328 SSLv3 uses a method similar to HMAC to generate the MD5 message MAC.
329 For MD5, 48 bytes of the pad are used.
331 MD5(MAC_write_secret + pad2 +
332 MD5(MAC_write_secret + pad1 + seq_num + length + content));
334 int32
ssl3HMACMd5(unsigned char *key
, unsigned char *seq
,
335 unsigned char type
, unsigned char *data
, int32 len
,
339 unsigned char ihash
[SSL_MD5_HASH_SIZE
];
343 matrixMd5Update(&md5
, key
, SSL_MD5_HASH_SIZE
);
344 matrixMd5Update(&md5
, pad1
, 48);
345 matrixMd5Update(&md5
, seq
, 8);
347 ihash
[1] = (len
& 0xFF00) >> 8;
348 ihash
[2] = len
& 0xFF;
349 matrixMd5Update(&md5
, ihash
, 3);
350 matrixMd5Update(&md5
, data
, len
);
351 matrixMd5Final(&md5
, ihash
);
354 matrixMd5Update(&md5
, key
, SSL_MD5_HASH_SIZE
);
355 matrixMd5Update(&md5
, pad2
, 48);
356 matrixMd5Update(&md5
, ihash
, SSL_MD5_HASH_SIZE
);
357 matrixMd5Final(&md5
, mac
);
360 Increment sequence number
362 for (i
= 7; i
>= 0; i
--) {
368 return SSL_MD5_HASH_SIZE
;
371 #endif /* USE_MD5_MAC */
373 /******************************************************************************/