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