OLD | NEW |
| (Empty) |
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 #ifdef NSS_ENABLE_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 (SSL_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 SSL_RSA_EXPORT_WITH_RC4_40_MD5: | |
651 case SSL_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, pwAr
g); | |
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 #ifdef NSS_ENABLE_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_ENABLE_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 #ifdef NSS_ENABLE_ECC | |
881 if (ecParams.data != NULL) { | |
882 PORT_Free(ecParams.data); | |
883 ecParams.data = NULL; | |
884 } | |
885 #endif /* NSS_ENABLE_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 | |
OLD | NEW |