|
1 /* |
|
2 * Key Derivation that doesn't use PKCS11 |
|
3 * |
|
4 * This Source Code Form is subject to the terms of the Mozilla Public |
|
5 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
7 |
|
8 #include "ssl.h" /* prereq to sslimpl.h */ |
|
9 #include "certt.h" /* prereq to sslimpl.h */ |
|
10 #include "keythi.h" /* prereq to sslimpl.h */ |
|
11 #include "sslimpl.h" |
|
12 #ifndef NO_PKCS11_BYPASS |
|
13 #include "blapi.h" |
|
14 #endif |
|
15 |
|
16 #include "keyhi.h" |
|
17 #include "pk11func.h" |
|
18 #include "secasn1.h" |
|
19 #include "cert.h" |
|
20 #include "secmodt.h" |
|
21 |
|
22 #include "sslproto.h" |
|
23 #include "sslerr.h" |
|
24 |
|
25 #ifndef NO_PKCS11_BYPASS |
|
26 /* make this a macro! */ |
|
27 #ifdef NOT_A_MACRO |
|
28 static void |
|
29 buildSSLKey(unsigned char * keyBlock, unsigned int keyLen, SECItem * result, |
|
30 const char * label) |
|
31 { |
|
32 result->type = siBuffer; |
|
33 result->data = keyBlock; |
|
34 result->len = keyLen; |
|
35 PRINT_BUF(100, (NULL, label, keyBlock, keyLen)); |
|
36 } |
|
37 #else |
|
38 #define buildSSLKey(keyBlock, keyLen, result, label) \ |
|
39 { \ |
|
40 (result)->type = siBuffer; \ |
|
41 (result)->data = keyBlock; \ |
|
42 (result)->len = keyLen; \ |
|
43 PRINT_BUF(100, (NULL, label, keyBlock, keyLen)); \ |
|
44 } |
|
45 #endif |
|
46 |
|
47 /* |
|
48 * SSL Key generation given pre master secret |
|
49 */ |
|
50 #ifndef NUM_MIXERS |
|
51 #define NUM_MIXERS 9 |
|
52 #endif |
|
53 static const char * const mixers[NUM_MIXERS] = { |
|
54 "A", |
|
55 "BB", |
|
56 "CCC", |
|
57 "DDDD", |
|
58 "EEEEE", |
|
59 "FFFFFF", |
|
60 "GGGGGGG", |
|
61 "HHHHHHHH", |
|
62 "IIIIIIIII" |
|
63 }; |
|
64 |
|
65 |
|
66 SECStatus |
|
67 ssl3_KeyAndMacDeriveBypass( |
|
68 ssl3CipherSpec * pwSpec, |
|
69 const unsigned char * cr, |
|
70 const unsigned char * sr, |
|
71 PRBool isTLS, |
|
72 PRBool isExport) |
|
73 { |
|
74 const ssl3BulkCipherDef *cipher_def = pwSpec->cipher_def; |
|
75 unsigned char * key_block = pwSpec->key_block; |
|
76 unsigned char * key_block2 = NULL; |
|
77 unsigned int block_bytes = 0; |
|
78 unsigned int block_needed = 0; |
|
79 unsigned int i; |
|
80 unsigned int keySize; /* actual size of cipher keys */ |
|
81 unsigned int effKeySize; /* effective size of cipher keys */ |
|
82 unsigned int macSize; /* size of MAC secret */ |
|
83 unsigned int IVSize; /* size of IV */ |
|
84 PRBool explicitIV = PR_FALSE; |
|
85 SECStatus rv = SECFailure; |
|
86 SECStatus status = SECSuccess; |
|
87 PRBool isFIPS = PR_FALSE; |
|
88 PRBool isTLS12 = pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2; |
|
89 |
|
90 SECItem srcr; |
|
91 SECItem crsr; |
|
92 |
|
93 unsigned char srcrdata[SSL3_RANDOM_LENGTH * 2]; |
|
94 unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2]; |
|
95 PRUint64 md5buf[22]; |
|
96 PRUint64 shabuf[40]; |
|
97 |
|
98 #define md5Ctx ((MD5Context *)md5buf) |
|
99 #define shaCtx ((SHA1Context *)shabuf) |
|
100 |
|
101 static const SECItem zed = { siBuffer, NULL, 0 }; |
|
102 |
|
103 if (pwSpec->msItem.data == NULL || |
|
104 pwSpec->msItem.len != SSL3_MASTER_SECRET_LENGTH) { |
|
105 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
|
106 return rv; |
|
107 } |
|
108 |
|
109 PRINT_BUF(100, (NULL, "Master Secret", pwSpec->msItem.data, |
|
110 pwSpec->msItem.len)); |
|
111 |
|
112 /* figure out how much is needed */ |
|
113 macSize = pwSpec->mac_size; |
|
114 keySize = cipher_def->key_size; |
|
115 effKeySize = cipher_def->secret_key_size; |
|
116 IVSize = cipher_def->iv_size; |
|
117 if (keySize == 0) { |
|
118 effKeySize = IVSize = 0; /* only MACing */ |
|
119 } |
|
120 if (cipher_def->type == type_block && |
|
121 pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) { |
|
122 /* Block ciphers in >= TLS 1.1 use a per-record, explicit IV. */ |
|
123 explicitIV = PR_TRUE; |
|
124 } |
|
125 block_needed = |
|
126 2 * (macSize + effKeySize + ((!isExport && !explicitIV) * IVSize)); |
|
127 |
|
128 /* |
|
129 * clear out our returned keys so we can recover on failure |
|
130 */ |
|
131 pwSpec->client.write_key_item = zed; |
|
132 pwSpec->client.write_mac_key_item = zed; |
|
133 pwSpec->server.write_key_item = zed; |
|
134 pwSpec->server.write_mac_key_item = zed; |
|
135 |
|
136 /* initialize the server random, client random block */ |
|
137 srcr.type = siBuffer; |
|
138 srcr.data = srcrdata; |
|
139 srcr.len = sizeof srcrdata; |
|
140 PORT_Memcpy(srcrdata, sr, SSL3_RANDOM_LENGTH); |
|
141 PORT_Memcpy(srcrdata + SSL3_RANDOM_LENGTH, cr, SSL3_RANDOM_LENGTH); |
|
142 |
|
143 /* initialize the client random, server random block */ |
|
144 crsr.type = siBuffer; |
|
145 crsr.data = crsrdata; |
|
146 crsr.len = sizeof crsrdata; |
|
147 PORT_Memcpy(crsrdata, cr, SSL3_RANDOM_LENGTH); |
|
148 PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH, sr, SSL3_RANDOM_LENGTH); |
|
149 PRINT_BUF(100, (NULL, "Key & MAC CRSR", crsr.data, crsr.len)); |
|
150 |
|
151 /* |
|
152 * generate the key material: |
|
153 */ |
|
154 if (isTLS) { |
|
155 SECItem keyblk; |
|
156 |
|
157 keyblk.type = siBuffer; |
|
158 keyblk.data = key_block; |
|
159 keyblk.len = block_needed; |
|
160 |
|
161 if (isTLS12) { |
|
162 status = TLS_P_hash(HASH_AlgSHA256, &pwSpec->msItem, |
|
163 "key expansion", &srcr, &keyblk, isFIPS); |
|
164 } else { |
|
165 status = TLS_PRF(&pwSpec->msItem, "key expansion", &srcr, &keyblk, |
|
166 isFIPS); |
|
167 } |
|
168 if (status != SECSuccess) { |
|
169 goto key_and_mac_derive_fail; |
|
170 } |
|
171 block_bytes = keyblk.len; |
|
172 } else { |
|
173 /* key_block = |
|
174 * MD5(master_secret + SHA('A' + master_secret + |
|
175 * ServerHello.random + ClientHello.random)) + |
|
176 * MD5(master_secret + SHA('BB' + master_secret + |
|
177 * ServerHello.random + ClientHello.random)) + |
|
178 * MD5(master_secret + SHA('CCC' + master_secret + |
|
179 * ServerHello.random + ClientHello.random)) + |
|
180 * [...]; |
|
181 */ |
|
182 unsigned int made = 0; |
|
183 for (i = 0; made < block_needed && i < NUM_MIXERS; ++i) { |
|
184 unsigned int outLen; |
|
185 unsigned char sha_out[SHA1_LENGTH]; |
|
186 |
|
187 SHA1_Begin(shaCtx); |
|
188 SHA1_Update(shaCtx, (unsigned char*)(mixers[i]), i+1); |
|
189 SHA1_Update(shaCtx, pwSpec->msItem.data, pwSpec->msItem.len); |
|
190 SHA1_Update(shaCtx, srcr.data, srcr.len); |
|
191 SHA1_End(shaCtx, sha_out, &outLen, SHA1_LENGTH); |
|
192 PORT_Assert(outLen == SHA1_LENGTH); |
|
193 |
|
194 MD5_Begin(md5Ctx); |
|
195 MD5_Update(md5Ctx, pwSpec->msItem.data, pwSpec->msItem.len); |
|
196 MD5_Update(md5Ctx, sha_out, outLen); |
|
197 MD5_End(md5Ctx, key_block + made, &outLen, MD5_LENGTH); |
|
198 PORT_Assert(outLen == MD5_LENGTH); |
|
199 made += MD5_LENGTH; |
|
200 } |
|
201 block_bytes = made; |
|
202 } |
|
203 PORT_Assert(block_bytes >= block_needed); |
|
204 PORT_Assert(block_bytes <= sizeof pwSpec->key_block); |
|
205 PRINT_BUF(100, (NULL, "key block", key_block, block_bytes)); |
|
206 |
|
207 /* |
|
208 * Put the key material where it goes. |
|
209 */ |
|
210 key_block2 = key_block + block_bytes; |
|
211 i = 0; /* now shows how much consumed */ |
|
212 |
|
213 /* |
|
214 * The key_block is partitioned as follows: |
|
215 * client_write_MAC_secret[CipherSpec.hash_size] |
|
216 */ |
|
217 buildSSLKey(&key_block[i],macSize, &pwSpec->client.write_mac_key_item, \ |
|
218 "Client Write MAC Secret"); |
|
219 i += macSize; |
|
220 |
|
221 /* |
|
222 * server_write_MAC_secret[CipherSpec.hash_size] |
|
223 */ |
|
224 buildSSLKey(&key_block[i],macSize, &pwSpec->server.write_mac_key_item, \ |
|
225 "Server Write MAC Secret"); |
|
226 i += macSize; |
|
227 |
|
228 if (!keySize) { |
|
229 /* only MACing */ |
|
230 buildSSLKey(NULL, 0, &pwSpec->client.write_key_item, \ |
|
231 "Client Write Key (MAC only)"); |
|
232 buildSSLKey(NULL, 0, &pwSpec->server.write_key_item, \ |
|
233 "Server Write Key (MAC only)"); |
|
234 buildSSLKey(NULL, 0, &pwSpec->client.write_iv_item, \ |
|
235 "Client Write IV (MAC only)"); |
|
236 buildSSLKey(NULL, 0, &pwSpec->server.write_iv_item, \ |
|
237 "Server Write IV (MAC only)"); |
|
238 } else if (!isExport) { |
|
239 /* |
|
240 ** Generate Domestic write keys and IVs. |
|
241 ** client_write_key[CipherSpec.key_material] |
|
242 */ |
|
243 buildSSLKey(&key_block[i], keySize, &pwSpec->client.write_key_item, \ |
|
244 "Domestic Client Write Key"); |
|
245 i += keySize; |
|
246 |
|
247 /* |
|
248 ** server_write_key[CipherSpec.key_material] |
|
249 */ |
|
250 buildSSLKey(&key_block[i], keySize, &pwSpec->server.write_key_item, \ |
|
251 "Domestic Server Write Key"); |
|
252 i += keySize; |
|
253 |
|
254 if (IVSize > 0) { |
|
255 if (explicitIV) { |
|
256 static unsigned char zero_block[32]; |
|
257 PORT_Assert(IVSize <= sizeof zero_block); |
|
258 buildSSLKey(&zero_block[0], IVSize, \ |
|
259 &pwSpec->client.write_iv_item, \ |
|
260 "Domestic Client Write IV"); |
|
261 buildSSLKey(&zero_block[0], IVSize, \ |
|
262 &pwSpec->server.write_iv_item, \ |
|
263 "Domestic Server Write IV"); |
|
264 } else { |
|
265 /* |
|
266 ** client_write_IV[CipherSpec.IV_size] |
|
267 */ |
|
268 buildSSLKey(&key_block[i], IVSize, \ |
|
269 &pwSpec->client.write_iv_item, \ |
|
270 "Domestic Client Write IV"); |
|
271 i += IVSize; |
|
272 |
|
273 /* |
|
274 ** server_write_IV[CipherSpec.IV_size] |
|
275 */ |
|
276 buildSSLKey(&key_block[i], IVSize, \ |
|
277 &pwSpec->server.write_iv_item, \ |
|
278 "Domestic Server Write IV"); |
|
279 i += IVSize; |
|
280 } |
|
281 } |
|
282 PORT_Assert(i <= block_bytes); |
|
283 } else if (!isTLS) { |
|
284 /* |
|
285 ** Generate SSL3 Export write keys and IVs. |
|
286 */ |
|
287 unsigned int outLen; |
|
288 |
|
289 /* |
|
290 ** client_write_key[CipherSpec.key_material] |
|
291 ** final_client_write_key = MD5(client_write_key + |
|
292 ** ClientHello.random + ServerHello.random); |
|
293 */ |
|
294 MD5_Begin(md5Ctx); |
|
295 MD5_Update(md5Ctx, &key_block[i], effKeySize); |
|
296 MD5_Update(md5Ctx, crsr.data, crsr.len); |
|
297 MD5_End(md5Ctx, key_block2, &outLen, MD5_LENGTH); |
|
298 i += effKeySize; |
|
299 buildSSLKey(key_block2, keySize, &pwSpec->client.write_key_item, \ |
|
300 "SSL3 Export Client Write Key"); |
|
301 key_block2 += keySize; |
|
302 |
|
303 /* |
|
304 ** server_write_key[CipherSpec.key_material] |
|
305 ** final_server_write_key = MD5(server_write_key + |
|
306 ** ServerHello.random + ClientHello.random); |
|
307 */ |
|
308 MD5_Begin(md5Ctx); |
|
309 MD5_Update(md5Ctx, &key_block[i], effKeySize); |
|
310 MD5_Update(md5Ctx, srcr.data, srcr.len); |
|
311 MD5_End(md5Ctx, key_block2, &outLen, MD5_LENGTH); |
|
312 i += effKeySize; |
|
313 buildSSLKey(key_block2, keySize, &pwSpec->server.write_key_item, \ |
|
314 "SSL3 Export Server Write Key"); |
|
315 key_block2 += keySize; |
|
316 PORT_Assert(i <= block_bytes); |
|
317 |
|
318 if (IVSize) { |
|
319 /* |
|
320 ** client_write_IV = |
|
321 ** MD5(ClientHello.random + ServerHello.random); |
|
322 */ |
|
323 MD5_Begin(md5Ctx); |
|
324 MD5_Update(md5Ctx, crsr.data, crsr.len); |
|
325 MD5_End(md5Ctx, key_block2, &outLen, MD5_LENGTH); |
|
326 buildSSLKey(key_block2, IVSize, &pwSpec->client.write_iv_item, \ |
|
327 "SSL3 Export Client Write IV"); |
|
328 key_block2 += IVSize; |
|
329 |
|
330 /* |
|
331 ** server_write_IV = |
|
332 ** MD5(ServerHello.random + ClientHello.random); |
|
333 */ |
|
334 MD5_Begin(md5Ctx); |
|
335 MD5_Update(md5Ctx, srcr.data, srcr.len); |
|
336 MD5_End(md5Ctx, key_block2, &outLen, MD5_LENGTH); |
|
337 buildSSLKey(key_block2, IVSize, &pwSpec->server.write_iv_item, \ |
|
338 "SSL3 Export Server Write IV"); |
|
339 key_block2 += IVSize; |
|
340 } |
|
341 |
|
342 PORT_Assert(key_block2 - key_block <= sizeof pwSpec->key_block); |
|
343 } else { |
|
344 /* |
|
345 ** Generate TLS Export write keys and IVs. |
|
346 */ |
|
347 SECItem secret ; |
|
348 SECItem keyblk ; |
|
349 |
|
350 secret.type = siBuffer; |
|
351 keyblk.type = siBuffer; |
|
352 /* |
|
353 ** client_write_key[CipherSpec.key_material] |
|
354 ** final_client_write_key = PRF(client_write_key, |
|
355 ** "client write key", |
|
356 ** client_random + server_random); |
|
357 */ |
|
358 secret.data = &key_block[i]; |
|
359 secret.len = effKeySize; |
|
360 i += effKeySize; |
|
361 keyblk.data = key_block2; |
|
362 keyblk.len = keySize; |
|
363 status = TLS_PRF(&secret, "client write key", &crsr, &keyblk, isFIPS); |
|
364 if (status != SECSuccess) { |
|
365 goto key_and_mac_derive_fail; |
|
366 } |
|
367 buildSSLKey(key_block2, keySize, &pwSpec->client.write_key_item, \ |
|
368 "TLS Export Client Write Key"); |
|
369 key_block2 += keySize; |
|
370 |
|
371 /* |
|
372 ** server_write_key[CipherSpec.key_material] |
|
373 ** final_server_write_key = PRF(server_write_key, |
|
374 ** "server write key", |
|
375 ** client_random + server_random); |
|
376 */ |
|
377 secret.data = &key_block[i]; |
|
378 secret.len = effKeySize; |
|
379 i += effKeySize; |
|
380 keyblk.data = key_block2; |
|
381 keyblk.len = keySize; |
|
382 status = TLS_PRF(&secret, "server write key", &crsr, &keyblk, isFIPS); |
|
383 if (status != SECSuccess) { |
|
384 goto key_and_mac_derive_fail; |
|
385 } |
|
386 buildSSLKey(key_block2, keySize, &pwSpec->server.write_key_item, \ |
|
387 "TLS Export Server Write Key"); |
|
388 key_block2 += keySize; |
|
389 |
|
390 /* |
|
391 ** iv_block = PRF("", "IV block", client_random + server_random); |
|
392 ** client_write_IV[SecurityParameters.IV_size] |
|
393 ** server_write_IV[SecurityParameters.IV_size] |
|
394 */ |
|
395 if (IVSize) { |
|
396 secret.data = NULL; |
|
397 secret.len = 0; |
|
398 keyblk.data = key_block2; |
|
399 keyblk.len = 2 * IVSize; |
|
400 status = TLS_PRF(&secret, "IV block", &crsr, &keyblk, isFIPS); |
|
401 if (status != SECSuccess) { |
|
402 goto key_and_mac_derive_fail; |
|
403 } |
|
404 buildSSLKey(key_block2, IVSize, \ |
|
405 &pwSpec->client.write_iv_item, \ |
|
406 "TLS Export Client Write IV"); |
|
407 buildSSLKey(key_block2 + IVSize, IVSize, \ |
|
408 &pwSpec->server.write_iv_item, \ |
|
409 "TLS Export Server Write IV"); |
|
410 key_block2 += 2 * IVSize; |
|
411 } |
|
412 PORT_Assert(key_block2 - key_block <= sizeof pwSpec->key_block); |
|
413 } |
|
414 rv = SECSuccess; |
|
415 |
|
416 key_and_mac_derive_fail: |
|
417 |
|
418 MD5_DestroyContext(md5Ctx, PR_FALSE); |
|
419 SHA1_DestroyContext(shaCtx, PR_FALSE); |
|
420 |
|
421 if (rv != SECSuccess) { |
|
422 PORT_SetError(SSL_ERROR_SESSION_KEY_GEN_FAILURE); |
|
423 } |
|
424 |
|
425 return rv; |
|
426 } |
|
427 |
|
428 |
|
429 /* derive the Master Secret from the PMS */ |
|
430 /* Presently, this is only done wtih RSA PMS, and only on the server side, |
|
431 * so isRSA is always true. |
|
432 */ |
|
433 SECStatus |
|
434 ssl3_MasterKeyDeriveBypass( |
|
435 ssl3CipherSpec * pwSpec, |
|
436 const unsigned char * cr, |
|
437 const unsigned char * sr, |
|
438 const SECItem * pms, |
|
439 PRBool isTLS, |
|
440 PRBool isRSA) |
|
441 { |
|
442 unsigned char * key_block = pwSpec->key_block; |
|
443 SECStatus rv = SECSuccess; |
|
444 PRBool isFIPS = PR_FALSE; |
|
445 PRBool isTLS12 = pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2; |
|
446 |
|
447 SECItem crsr; |
|
448 |
|
449 unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2]; |
|
450 PRUint64 md5buf[22]; |
|
451 PRUint64 shabuf[40]; |
|
452 |
|
453 #define md5Ctx ((MD5Context *)md5buf) |
|
454 #define shaCtx ((SHA1Context *)shabuf) |
|
455 |
|
456 /* first do the consistancy checks */ |
|
457 if (isRSA) { |
|
458 PORT_Assert(pms->len == SSL3_RSA_PMS_LENGTH); |
|
459 if (pms->len != SSL3_RSA_PMS_LENGTH) { |
|
460 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
|
461 return SECFailure; |
|
462 } |
|
463 /* caller must test PMS version for rollback */ |
|
464 } |
|
465 |
|
466 /* initialize the client random, server random block */ |
|
467 crsr.type = siBuffer; |
|
468 crsr.data = crsrdata; |
|
469 crsr.len = sizeof crsrdata; |
|
470 PORT_Memcpy(crsrdata, cr, SSL3_RANDOM_LENGTH); |
|
471 PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH, sr, SSL3_RANDOM_LENGTH); |
|
472 PRINT_BUF(100, (NULL, "Master Secret CRSR", crsr.data, crsr.len)); |
|
473 |
|
474 /* finally do the key gen */ |
|
475 if (isTLS) { |
|
476 SECItem master = { siBuffer, NULL, 0 }; |
|
477 |
|
478 master.data = key_block; |
|
479 master.len = SSL3_MASTER_SECRET_LENGTH; |
|
480 |
|
481 if (isTLS12) { |
|
482 rv = TLS_P_hash(HASH_AlgSHA256, pms, "master secret", &crsr, |
|
483 &master, isFIPS); |
|
484 } else { |
|
485 rv = TLS_PRF(pms, "master secret", &crsr, &master, isFIPS); |
|
486 } |
|
487 if (rv != SECSuccess) { |
|
488 PORT_SetError(SSL_ERROR_SESSION_KEY_GEN_FAILURE); |
|
489 } |
|
490 } else { |
|
491 int i; |
|
492 unsigned int made = 0; |
|
493 for (i = 0; i < 3; i++) { |
|
494 unsigned int outLen; |
|
495 unsigned char sha_out[SHA1_LENGTH]; |
|
496 |
|
497 SHA1_Begin(shaCtx); |
|
498 SHA1_Update(shaCtx, (unsigned char*) mixers[i], i+1); |
|
499 SHA1_Update(shaCtx, pms->data, pms->len); |
|
500 SHA1_Update(shaCtx, crsr.data, crsr.len); |
|
501 SHA1_End(shaCtx, sha_out, &outLen, SHA1_LENGTH); |
|
502 PORT_Assert(outLen == SHA1_LENGTH); |
|
503 |
|
504 MD5_Begin(md5Ctx); |
|
505 MD5_Update(md5Ctx, pms->data, pms->len); |
|
506 MD5_Update(md5Ctx, sha_out, outLen); |
|
507 MD5_End(md5Ctx, key_block + made, &outLen, MD5_LENGTH); |
|
508 PORT_Assert(outLen == MD5_LENGTH); |
|
509 made += outLen; |
|
510 } |
|
511 } |
|
512 |
|
513 /* store the results */ |
|
514 PORT_Memcpy(pwSpec->raw_master_secret, key_block, |
|
515 SSL3_MASTER_SECRET_LENGTH); |
|
516 pwSpec->msItem.data = pwSpec->raw_master_secret; |
|
517 pwSpec->msItem.len = SSL3_MASTER_SECRET_LENGTH; |
|
518 PRINT_BUF(100, (NULL, "Master Secret", pwSpec->msItem.data, |
|
519 pwSpec->msItem.len)); |
|
520 |
|
521 return rv; |
|
522 } |
|
523 |
|
524 static SECStatus |
|
525 ssl_canExtractMS(PK11SymKey *pms, PRBool isTLS, PRBool isDH, PRBool *pcbp) |
|
526 { SECStatus rv; |
|
527 PK11SymKey * ms = NULL; |
|
528 SECItem params = {siBuffer, NULL, 0}; |
|
529 CK_SSL3_MASTER_KEY_DERIVE_PARAMS master_params; |
|
530 unsigned char rand[SSL3_RANDOM_LENGTH]; |
|
531 CK_VERSION pms_version; |
|
532 CK_MECHANISM_TYPE master_derive; |
|
533 CK_MECHANISM_TYPE key_derive; |
|
534 CK_FLAGS keyFlags; |
|
535 |
|
536 if (pms == NULL) |
|
537 return(SECFailure); |
|
538 |
|
539 PORT_Memset(rand, 0, SSL3_RANDOM_LENGTH); |
|
540 |
|
541 if (isTLS) { |
|
542 if(isDH) master_derive = CKM_TLS_MASTER_KEY_DERIVE_DH; |
|
543 else master_derive = CKM_TLS_MASTER_KEY_DERIVE; |
|
544 key_derive = CKM_TLS_KEY_AND_MAC_DERIVE; |
|
545 keyFlags = CKF_SIGN | CKF_VERIFY; |
|
546 } else { |
|
547 if (isDH) master_derive = CKM_SSL3_MASTER_KEY_DERIVE_DH; |
|
548 else master_derive = CKM_SSL3_MASTER_KEY_DERIVE; |
|
549 key_derive = CKM_SSL3_KEY_AND_MAC_DERIVE; |
|
550 keyFlags = 0; |
|
551 } |
|
552 |
|
553 master_params.pVersion = &pms_version; |
|
554 master_params.RandomInfo.pClientRandom = rand; |
|
555 master_params.RandomInfo.ulClientRandomLen = SSL3_RANDOM_LENGTH; |
|
556 master_params.RandomInfo.pServerRandom = rand; |
|
557 master_params.RandomInfo.ulServerRandomLen = SSL3_RANDOM_LENGTH; |
|
558 |
|
559 params.data = (unsigned char *) &master_params; |
|
560 params.len = sizeof master_params; |
|
561 |
|
562 ms = PK11_DeriveWithFlags(pms, master_derive, ¶ms, key_derive, |
|
563 CKA_DERIVE, 0, keyFlags); |
|
564 if (ms == NULL) |
|
565 return(SECFailure); |
|
566 |
|
567 rv = PK11_ExtractKeyValue(ms); |
|
568 *pcbp = (rv == SECSuccess); |
|
569 PK11_FreeSymKey(ms); |
|
570 |
|
571 return(rv); |
|
572 |
|
573 } |
|
574 #endif /* !NO_PKCS11_BYPASS */ |
|
575 |
|
576 /* Check the key exchange algorithm for each cipher in the list to see if |
|
577 * a master secret key can be extracted. If the KEA will use keys from the |
|
578 * specified cert make sure the extract operation is attempted from the slot |
|
579 * where the private key resides. |
|
580 * If MS can be extracted for all ciphers, (*pcanbypass) is set to TRUE and |
|
581 * SECSuccess is returned. In all other cases but one (*pcanbypass) is |
|
582 * set to FALSE and SECFailure is returned. |
|
583 * In that last case Derive() has been called successfully but the MS is null, |
|
584 * CanBypass sets (*pcanbypass) to FALSE and returns SECSuccess indicating the |
|
585 * arguments were all valid but the slot cannot be bypassed. |
|
586 */ |
|
587 |
|
588 /* XXX Add SSL_CBP_TLS1_1 and test it in protocolmask when setting isTLS. */ |
|
589 |
|
590 SECStatus |
|
591 SSL_CanBypass(CERTCertificate *cert, SECKEYPrivateKey *srvPrivkey, |
|
592 PRUint32 protocolmask, PRUint16 *ciphersuites, int nsuites, |
|
593 PRBool *pcanbypass, void *pwArg) |
|
594 { |
|
595 #ifdef NO_PKCS11_BYPASS |
|
596 if (!pcanbypass) { |
|
597 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
|
598 return SECFailure; |
|
599 } |
|
600 *pcanbypass = PR_FALSE; |
|
601 return SECSuccess; |
|
602 #else |
|
603 SECStatus rv; |
|
604 int i; |
|
605 PRUint16 suite; |
|
606 PK11SymKey * pms = NULL; |
|
607 SECKEYPublicKey * srvPubkey = NULL; |
|
608 KeyType privKeytype; |
|
609 PK11SlotInfo * slot = NULL; |
|
610 SECItem param; |
|
611 CK_VERSION version; |
|
612 CK_MECHANISM_TYPE mechanism_array[2]; |
|
613 SECItem enc_pms = {siBuffer, NULL, 0}; |
|
614 PRBool isTLS = PR_FALSE; |
|
615 SSLCipherSuiteInfo csdef; |
|
616 PRBool testrsa = PR_FALSE; |
|
617 PRBool testrsa_export = PR_FALSE; |
|
618 PRBool testecdh = PR_FALSE; |
|
619 PRBool testecdhe = PR_FALSE; |
|
620 #ifndef NSS_DISABLE_ECC |
|
621 SECKEYECParams ecParams = { siBuffer, NULL, 0 }; |
|
622 #endif |
|
623 |
|
624 if (!cert || !srvPrivkey || !ciphersuites || !pcanbypass) { |
|
625 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
|
626 return SECFailure; |
|
627 } |
|
628 |
|
629 srvPubkey = CERT_ExtractPublicKey(cert); |
|
630 if (!srvPubkey) |
|
631 return SECFailure; |
|
632 |
|
633 *pcanbypass = PR_TRUE; |
|
634 rv = SECFailure; |
|
635 |
|
636 /* determine which KEAs to test */ |
|
637 /* 0 (TLS_NULL_WITH_NULL_NULL) is used as a list terminator because |
|
638 * SSL3 and TLS specs forbid negotiating that cipher suite number. |
|
639 */ |
|
640 for (i=0; i < nsuites && (suite = *ciphersuites++) != 0; i++) { |
|
641 /* skip SSL2 cipher suites and ones NSS doesn't support */ |
|
642 if (SSL_GetCipherSuiteInfo(suite, &csdef, sizeof(csdef)) != SECSuccess |
|
643 || SSL_IS_SSL2_CIPHER(suite) ) |
|
644 continue; |
|
645 switch (csdef.keaType) { |
|
646 case ssl_kea_rsa: |
|
647 switch (csdef.cipherSuite) { |
|
648 case TLS_RSA_EXPORT1024_WITH_RC4_56_SHA: |
|
649 case TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA: |
|
650 case TLS_RSA_EXPORT_WITH_RC4_40_MD5: |
|
651 case TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5: |
|
652 testrsa_export = PR_TRUE; |
|
653 } |
|
654 if (!testrsa_export) |
|
655 testrsa = PR_TRUE; |
|
656 break; |
|
657 case ssl_kea_ecdh: |
|
658 if (strcmp(csdef.keaTypeName, "ECDHE") == 0) /* ephemeral? */ |
|
659 testecdhe = PR_TRUE; |
|
660 else |
|
661 testecdh = PR_TRUE; |
|
662 break; |
|
663 case ssl_kea_dh: |
|
664 /* this is actually DHE */ |
|
665 default: |
|
666 continue; |
|
667 } |
|
668 } |
|
669 |
|
670 /* For each protocol try to derive and extract an MS. |
|
671 * Failure of function any function except MS extract means |
|
672 * continue with the next cipher test. Stop testing when the list is |
|
673 * exhausted or when the first MS extract--not derive--fails. |
|
674 */ |
|
675 privKeytype = SECKEY_GetPrivateKeyType(srvPrivkey); |
|
676 protocolmask &= SSL_CBP_SSL3|SSL_CBP_TLS1_0; |
|
677 while (protocolmask) { |
|
678 if (protocolmask & SSL_CBP_SSL3) { |
|
679 isTLS = PR_FALSE; |
|
680 protocolmask ^= SSL_CBP_SSL3; |
|
681 } else { |
|
682 isTLS = PR_TRUE; |
|
683 protocolmask ^= SSL_CBP_TLS1_0; |
|
684 } |
|
685 |
|
686 if (privKeytype == rsaKey && testrsa_export) { |
|
687 if (PK11_GetPrivateModulusLen(srvPrivkey) > EXPORT_RSA_KEY_LENGTH) { |
|
688 *pcanbypass = PR_FALSE; |
|
689 rv = SECSuccess; |
|
690 break; |
|
691 } else |
|
692 testrsa = PR_TRUE; |
|
693 } |
|
694 for (; privKeytype == rsaKey && testrsa; ) { |
|
695 /* TLS_RSA */ |
|
696 unsigned char rsaPmsBuf[SSL3_RSA_PMS_LENGTH]; |
|
697 unsigned int outLen = 0; |
|
698 CK_MECHANISM_TYPE target; |
|
699 SECStatus irv; |
|
700 |
|
701 mechanism_array[0] = CKM_SSL3_PRE_MASTER_KEY_GEN; |
|
702 mechanism_array[1] = CKM_RSA_PKCS; |
|
703 |
|
704 slot = PK11_GetBestSlotMultiple(mechanism_array, 2, pwArg); |
|
705 if (slot == NULL) { |
|
706 PORT_SetError(SSL_ERROR_TOKEN_SLOT_NOT_FOUND); |
|
707 break; |
|
708 } |
|
709 |
|
710 /* Generate the pre-master secret ... (client side) */ |
|
711 version.major = 3 /*MSB(clientHelloVersion)*/; |
|
712 version.minor = 0 /*LSB(clientHelloVersion)*/; |
|
713 param.data = (unsigned char *)&version; |
|
714 param.len = sizeof version; |
|
715 pms = PK11_KeyGen(slot, CKM_SSL3_PRE_MASTER_KEY_GEN, ¶m, 0, pwArg); |
|
716 PK11_FreeSlot(slot); |
|
717 if (!pms) |
|
718 break; |
|
719 /* now wrap it */ |
|
720 enc_pms.len = SECKEY_PublicKeyStrength(srvPubkey); |
|
721 enc_pms.data = (unsigned char*)PORT_Alloc(enc_pms.len); |
|
722 if (enc_pms.data == NULL) { |
|
723 PORT_SetError(PR_OUT_OF_MEMORY_ERROR); |
|
724 break; |
|
725 } |
|
726 irv = PK11_PubWrapSymKey(CKM_RSA_PKCS, srvPubkey, pms, &enc_pms); |
|
727 if (irv != SECSuccess) |
|
728 break; |
|
729 PK11_FreeSymKey(pms); |
|
730 pms = NULL; |
|
731 /* now do the server side--check the triple bypass first */ |
|
732 rv = PK11_PrivDecryptPKCS1(srvPrivkey, rsaPmsBuf, &outLen, |
|
733 sizeof rsaPmsBuf, |
|
734 (unsigned char *)enc_pms.data, |
|
735 enc_pms.len); |
|
736 /* if decrypt worked we're done with the RSA test */ |
|
737 if (rv == SECSuccess) { |
|
738 *pcanbypass = PR_TRUE; |
|
739 break; |
|
740 } |
|
741 /* check for fallback to double bypass */ |
|
742 target = isTLS ? CKM_TLS_MASTER_KEY_DERIVE |
|
743 : CKM_SSL3_MASTER_KEY_DERIVE; |
|
744 pms = PK11_PubUnwrapSymKey(srvPrivkey, &enc_pms, |
|
745 target, CKA_DERIVE, 0); |
|
746 rv = ssl_canExtractMS(pms, isTLS, PR_FALSE, pcanbypass); |
|
747 if (rv == SECSuccess && *pcanbypass == PR_FALSE) |
|
748 goto done; |
|
749 break; |
|
750 } |
|
751 |
|
752 /* Check for NULL to avoid double free. |
|
753 * SECItem_FreeItem sets data NULL in secitem.c#265 |
|
754 */ |
|
755 if (enc_pms.data != NULL) { |
|
756 SECITEM_FreeItem(&enc_pms, PR_FALSE); |
|
757 } |
|
758 #ifndef NSS_DISABLE_ECC |
|
759 for (; (privKeytype == ecKey && ( testecdh || testecdhe)) || |
|
760 (privKeytype == rsaKey && testecdhe); ) { |
|
761 CK_MECHANISM_TYPE target; |
|
762 SECKEYPublicKey *keapub = NULL; |
|
763 SECKEYPrivateKey *keapriv; |
|
764 SECKEYPublicKey *cpub = NULL; /* client's ephemeral ECDH keys */ |
|
765 SECKEYPrivateKey *cpriv = NULL; |
|
766 SECKEYECParams *pecParams = NULL; |
|
767 |
|
768 if (privKeytype == ecKey && testecdhe) { |
|
769 /* TLS_ECDHE_ECDSA */ |
|
770 pecParams = &srvPubkey->u.ec.DEREncodedParams; |
|
771 } else if (privKeytype == rsaKey && testecdhe) { |
|
772 /* TLS_ECDHE_RSA */ |
|
773 ECName ec_curve; |
|
774 int serverKeyStrengthInBits; |
|
775 int signatureKeyStrength; |
|
776 int requiredECCbits; |
|
777 |
|
778 /* find a curve of equivalent strength to the RSA key's */ |
|
779 requiredECCbits = PK11_GetPrivateModulusLen(srvPrivkey); |
|
780 if (requiredECCbits < 0) |
|
781 break; |
|
782 requiredECCbits *= BPB; |
|
783 serverKeyStrengthInBits = srvPubkey->u.rsa.modulus.len; |
|
784 if (srvPubkey->u.rsa.modulus.data[0] == 0) { |
|
785 serverKeyStrengthInBits--; |
|
786 } |
|
787 /* convert to strength in bits */ |
|
788 serverKeyStrengthInBits *= BPB; |
|
789 |
|
790 signatureKeyStrength = |
|
791 SSL_RSASTRENGTH_TO_ECSTRENGTH(serverKeyStrengthInBits); |
|
792 |
|
793 if ( requiredECCbits > signatureKeyStrength ) |
|
794 requiredECCbits = signatureKeyStrength; |
|
795 |
|
796 ec_curve = |
|
797 ssl3_GetCurveWithECKeyStrength( |
|
798 ssl3_GetSupportedECCurveMask(NULL), |
|
799 requiredECCbits); |
|
800 rv = ssl3_ECName2Params(NULL, ec_curve, &ecParams); |
|
801 if (rv == SECFailure) { |
|
802 break; |
|
803 } |
|
804 pecParams = &ecParams; |
|
805 } |
|
806 |
|
807 if (testecdhe) { |
|
808 /* generate server's ephemeral keys */ |
|
809 keapriv = SECKEY_CreateECPrivateKey(pecParams, &keapub, NULL); |
|
810 if (!keapriv || !keapub) { |
|
811 if (keapriv) |
|
812 SECKEY_DestroyPrivateKey(keapriv); |
|
813 if (keapub) |
|
814 SECKEY_DestroyPublicKey(keapub); |
|
815 PORT_SetError(SEC_ERROR_KEYGEN_FAIL); |
|
816 rv = SECFailure; |
|
817 break; |
|
818 } |
|
819 } else { |
|
820 /* TLS_ECDH_ECDSA */ |
|
821 keapub = srvPubkey; |
|
822 keapriv = srvPrivkey; |
|
823 pecParams = &srvPubkey->u.ec.DEREncodedParams; |
|
824 } |
|
825 |
|
826 /* perform client side ops */ |
|
827 /* generate a pair of ephemeral keys using server's parms */ |
|
828 cpriv = SECKEY_CreateECPrivateKey(pecParams, &cpub, NULL); |
|
829 if (!cpriv || !cpub) { |
|
830 if (testecdhe) { |
|
831 SECKEY_DestroyPrivateKey(keapriv); |
|
832 SECKEY_DestroyPublicKey(keapub); |
|
833 } |
|
834 PORT_SetError(SEC_ERROR_KEYGEN_FAIL); |
|
835 rv = SECFailure; |
|
836 break; |
|
837 } |
|
838 /* now do the server side */ |
|
839 /* determine the PMS using client's public value */ |
|
840 target = isTLS ? CKM_TLS_MASTER_KEY_DERIVE_DH |
|
841 : CKM_SSL3_MASTER_KEY_DERIVE_DH; |
|
842 pms = PK11_PubDeriveWithKDF(keapriv, cpub, PR_FALSE, NULL, NULL, |
|
843 CKM_ECDH1_DERIVE, |
|
844 target, |
|
845 CKA_DERIVE, 0, CKD_NULL, NULL, NULL); |
|
846 rv = ssl_canExtractMS(pms, isTLS, PR_TRUE, pcanbypass); |
|
847 SECKEY_DestroyPrivateKey(cpriv); |
|
848 SECKEY_DestroyPublicKey(cpub); |
|
849 if (testecdhe) { |
|
850 SECKEY_DestroyPrivateKey(keapriv); |
|
851 SECKEY_DestroyPublicKey(keapub); |
|
852 } |
|
853 if (rv == SECSuccess && *pcanbypass == PR_FALSE) |
|
854 goto done; |
|
855 break; |
|
856 } |
|
857 /* Check for NULL to avoid double free. */ |
|
858 if (ecParams.data != NULL) { |
|
859 PORT_Free(ecParams.data); |
|
860 ecParams.data = NULL; |
|
861 } |
|
862 #endif /* NSS_DISABLE_ECC */ |
|
863 if (pms) |
|
864 PK11_FreeSymKey(pms); |
|
865 } |
|
866 |
|
867 /* *pcanbypass has been set */ |
|
868 rv = SECSuccess; |
|
869 |
|
870 done: |
|
871 if (pms) |
|
872 PK11_FreeSymKey(pms); |
|
873 |
|
874 /* Check for NULL to avoid double free. |
|
875 * SECItem_FreeItem sets data NULL in secitem.c#265 |
|
876 */ |
|
877 if (enc_pms.data != NULL) { |
|
878 SECITEM_FreeItem(&enc_pms, PR_FALSE); |
|
879 } |
|
880 #ifndef NSS_DISABLE_ECC |
|
881 if (ecParams.data != NULL) { |
|
882 PORT_Free(ecParams.data); |
|
883 ecParams.data = NULL; |
|
884 } |
|
885 #endif /* NSS_DISABLE_ECC */ |
|
886 |
|
887 if (srvPubkey) { |
|
888 SECKEY_DestroyPublicKey(srvPubkey); |
|
889 srvPubkey = NULL; |
|
890 } |
|
891 |
|
892 |
|
893 return rv; |
|
894 #endif /* NO_PKCS11_BYPASS */ |
|
895 } |
|
896 |