OLD | NEW |
| (Empty) |
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ | |
2 /* | |
3 * SSL3 Protocol | |
4 * | |
5 * This Source Code Form is subject to the terms of the Mozilla Public | |
6 * License, v. 2.0. If a copy of the MPL was not distributed with this | |
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |
8 | |
9 /* ECC code moved here from ssl3con.c */ | |
10 | |
11 #include "nss.h" | |
12 #include "cert.h" | |
13 #include "ssl.h" | |
14 #include "cryptohi.h" /* for DSAU_ stuff */ | |
15 #include "keyhi.h" | |
16 #include "secder.h" | |
17 #include "secitem.h" | |
18 | |
19 #include "sslimpl.h" | |
20 #include "sslproto.h" | |
21 #include "sslerr.h" | |
22 #include "prtime.h" | |
23 #include "prinrval.h" | |
24 #include "prerror.h" | |
25 #include "pratom.h" | |
26 #include "prthread.h" | |
27 #include "prinit.h" | |
28 | |
29 #include "pk11func.h" | |
30 #include "secmod.h" | |
31 | |
32 #include <stdio.h> | |
33 | |
34 #ifndef NSS_DISABLE_ECC | |
35 | |
36 #ifndef PK11_SETATTRS | |
37 #define PK11_SETATTRS(x, id, v, l) \ | |
38 (x)->type = (id); \ | |
39 (x)->pValue = (v); \ | |
40 (x)->ulValueLen = (l); | |
41 #endif | |
42 | |
43 #define SSL_GET_SERVER_PUBLIC_KEY(sock, type)
\ | |
44 (ss->serverCerts[type].serverKeyPair ? ss->serverCerts[type].serverKeyPair->
pubKey \ | |
45 : NULL) | |
46 | |
47 #define SSL_IS_CURVE_NEGOTIATED(curvemsk, curveName) \ | |
48 ((curveName > ec_noName) && \ | |
49 (curveName < ec_pastLastName) && \ | |
50 ((1UL << curveName) & curvemsk) != 0) | |
51 | |
52 static SECStatus ssl3_CreateECDHEphemeralKeys(sslSocket *ss, ECName ec_curve); | |
53 | |
54 #define supportedCurve(x) (((x) > ec_noName) && ((x) < ec_pastLastName)) | |
55 | |
56 /* Table containing OID tags for elliptic curves named in the | |
57 * ECC-TLS IETF draft. | |
58 */ | |
59 static const SECOidTag ecName2OIDTag[] = { | |
60 0, | |
61 SEC_OID_SECG_EC_SECT163K1, /* 1 */ | |
62 SEC_OID_SECG_EC_SECT163R1, /* 2 */ | |
63 SEC_OID_SECG_EC_SECT163R2, /* 3 */ | |
64 SEC_OID_SECG_EC_SECT193R1, /* 4 */ | |
65 SEC_OID_SECG_EC_SECT193R2, /* 5 */ | |
66 SEC_OID_SECG_EC_SECT233K1, /* 6 */ | |
67 SEC_OID_SECG_EC_SECT233R1, /* 7 */ | |
68 SEC_OID_SECG_EC_SECT239K1, /* 8 */ | |
69 SEC_OID_SECG_EC_SECT283K1, /* 9 */ | |
70 SEC_OID_SECG_EC_SECT283R1, /* 10 */ | |
71 SEC_OID_SECG_EC_SECT409K1, /* 11 */ | |
72 SEC_OID_SECG_EC_SECT409R1, /* 12 */ | |
73 SEC_OID_SECG_EC_SECT571K1, /* 13 */ | |
74 SEC_OID_SECG_EC_SECT571R1, /* 14 */ | |
75 SEC_OID_SECG_EC_SECP160K1, /* 15 */ | |
76 SEC_OID_SECG_EC_SECP160R1, /* 16 */ | |
77 SEC_OID_SECG_EC_SECP160R2, /* 17 */ | |
78 SEC_OID_SECG_EC_SECP192K1, /* 18 */ | |
79 SEC_OID_SECG_EC_SECP192R1, /* 19 */ | |
80 SEC_OID_SECG_EC_SECP224K1, /* 20 */ | |
81 SEC_OID_SECG_EC_SECP224R1, /* 21 */ | |
82 SEC_OID_SECG_EC_SECP256K1, /* 22 */ | |
83 SEC_OID_SECG_EC_SECP256R1, /* 23 */ | |
84 SEC_OID_SECG_EC_SECP384R1, /* 24 */ | |
85 SEC_OID_SECG_EC_SECP521R1, /* 25 */ | |
86 }; | |
87 | |
88 static const PRUint16 curve2bits[] = { | |
89 0, /* ec_noName = 0, */ | |
90 163, /* ec_sect163k1 = 1, */ | |
91 163, /* ec_sect163r1 = 2, */ | |
92 163, /* ec_sect163r2 = 3, */ | |
93 193, /* ec_sect193r1 = 4, */ | |
94 193, /* ec_sect193r2 = 5, */ | |
95 233, /* ec_sect233k1 = 6, */ | |
96 233, /* ec_sect233r1 = 7, */ | |
97 239, /* ec_sect239k1 = 8, */ | |
98 283, /* ec_sect283k1 = 9, */ | |
99 283, /* ec_sect283r1 = 10, */ | |
100 409, /* ec_sect409k1 = 11, */ | |
101 409, /* ec_sect409r1 = 12, */ | |
102 571, /* ec_sect571k1 = 13, */ | |
103 571, /* ec_sect571r1 = 14, */ | |
104 160, /* ec_secp160k1 = 15, */ | |
105 160, /* ec_secp160r1 = 16, */ | |
106 160, /* ec_secp160r2 = 17, */ | |
107 192, /* ec_secp192k1 = 18, */ | |
108 192, /* ec_secp192r1 = 19, */ | |
109 224, /* ec_secp224k1 = 20, */ | |
110 224, /* ec_secp224r1 = 21, */ | |
111 256, /* ec_secp256k1 = 22, */ | |
112 256, /* ec_secp256r1 = 23, */ | |
113 384, /* ec_secp384r1 = 24, */ | |
114 521, /* ec_secp521r1 = 25, */ | |
115 65535 /* ec_pastLastName */ | |
116 }; | |
117 | |
118 typedef struct Bits2CurveStr { | |
119 PRUint16 bits; | |
120 ECName curve; | |
121 } Bits2Curve; | |
122 | |
123 static const Bits2Curve bits2curve[] = { | |
124 { 192, ec_secp192r1 /* = 19, fast */ }, | |
125 { 160, ec_secp160r2 /* = 17, fast */ }, | |
126 { 160, ec_secp160k1 /* = 15, */ }, | |
127 { 160, ec_secp160r1 /* = 16, */ }, | |
128 { 163, ec_sect163k1 /* = 1, */ }, | |
129 { 163, ec_sect163r1 /* = 2, */ }, | |
130 { 163, ec_sect163r2 /* = 3, */ }, | |
131 { 192, ec_secp192k1 /* = 18, */ }, | |
132 { 193, ec_sect193r1 /* = 4, */ }, | |
133 { 193, ec_sect193r2 /* = 5, */ }, | |
134 { 224, ec_secp224r1 /* = 21, fast */ }, | |
135 { 224, ec_secp224k1 /* = 20, */ }, | |
136 { 233, ec_sect233k1 /* = 6, */ }, | |
137 { 233, ec_sect233r1 /* = 7, */ }, | |
138 { 239, ec_sect239k1 /* = 8, */ }, | |
139 { 256, ec_secp256r1 /* = 23, fast */ }, | |
140 { 256, ec_secp256k1 /* = 22, */ }, | |
141 { 283, ec_sect283k1 /* = 9, */ }, | |
142 { 283, ec_sect283r1 /* = 10, */ }, | |
143 { 384, ec_secp384r1 /* = 24, fast */ }, | |
144 { 409, ec_sect409k1 /* = 11, */ }, | |
145 { 409, ec_sect409r1 /* = 12, */ }, | |
146 { 521, ec_secp521r1 /* = 25, fast */ }, | |
147 { 571, ec_sect571k1 /* = 13, */ }, | |
148 { 571, ec_sect571r1 /* = 14, */ }, | |
149 { 65535, ec_noName } | |
150 }; | |
151 | |
152 typedef struct ECDHEKeyPairStr { | |
153 ssl3KeyPair *pair; | |
154 int error; /* error code of the call-once function */ | |
155 PRCallOnceType once; | |
156 } ECDHEKeyPair; | |
157 | |
158 /* arrays of ECDHE KeyPairs */ | |
159 static ECDHEKeyPair gECDHEKeyPairs[ec_pastLastName]; | |
160 | |
161 SECStatus | |
162 ssl3_ECName2Params(PLArenaPool *arena, ECName curve, SECKEYECParams *params) | |
163 { | |
164 SECOidData *oidData = NULL; | |
165 PRUint32 policyFlags = 0; | |
166 | |
167 if ((curve <= ec_noName) || (curve >= ec_pastLastName) || | |
168 ((oidData = SECOID_FindOIDByTag(ecName2OIDTag[curve])) == NULL)) { | |
169 PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); | |
170 return SECFailure; | |
171 } | |
172 | |
173 if ((NSS_GetAlgorithmPolicy(ecName2OIDTag[curve], &policyFlags) == | |
174 SECSuccess) && | |
175 !(policyFlags & NSS_USE_ALG_IN_SSL_KX)) { | |
176 PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); | |
177 return SECFailure; | |
178 } | |
179 | |
180 SECITEM_AllocItem(arena, params, (2 + oidData->oid.len)); | |
181 /* | |
182 * params->data needs to contain the ASN encoding of an object ID (OID) | |
183 * representing the named curve. The actual OID is in | |
184 * oidData->oid.data so we simply prepend 0x06 and OID length | |
185 */ | |
186 params->data[0] = SEC_ASN1_OBJECT_ID; | |
187 params->data[1] = oidData->oid.len; | |
188 memcpy(params->data + 2, oidData->oid.data, oidData->oid.len); | |
189 | |
190 return SECSuccess; | |
191 } | |
192 | |
193 ECName | |
194 ssl3_PubKey2ECName(SECKEYPublicKey *pubKey) | |
195 { | |
196 SECItem oid = { siBuffer, NULL, 0 }; | |
197 SECOidData *oidData = NULL; | |
198 PRUint32 policyFlags = 0; | |
199 ECName i; | |
200 SECKEYECParams *params; | |
201 | |
202 if (pubKey->keyType != ecKey) { | |
203 PORT_Assert(0); | |
204 return ec_noName; | |
205 } | |
206 | |
207 params = &pubKey->u.ec.DEREncodedParams; | |
208 | |
209 /* | |
210 * params->data needs to contain the ASN encoding of an object ID (OID) | |
211 * representing a named curve. Here, we strip away everything | |
212 * before the actual OID and use the OID to look up a named curve. | |
213 */ | |
214 if (params->data[0] != SEC_ASN1_OBJECT_ID) | |
215 return ec_noName; | |
216 oid.len = params->len - 2; | |
217 oid.data = params->data + 2; | |
218 if ((oidData = SECOID_FindOID(&oid)) == NULL) | |
219 return ec_noName; | |
220 if ((NSS_GetAlgorithmPolicy(oidData->offset, &policyFlags) == | |
221 SECSuccess) && | |
222 !(policyFlags & NSS_USE_ALG_IN_SSL_KX)) { | |
223 return ec_noName; | |
224 } | |
225 for (i = ec_noName + 1; i < ec_pastLastName; i++) { | |
226 if (ecName2OIDTag[i] == oidData->offset) | |
227 return i; | |
228 } | |
229 | |
230 return ec_noName; | |
231 } | |
232 | |
233 /* Caller must set hiLevel error code. */ | |
234 static SECStatus | |
235 ssl3_ComputeECDHKeyHash(SSLHashType hashAlg, | |
236 SECItem ec_params, SECItem server_ecpoint, | |
237 SSL3Random *client_rand, SSL3Random *server_rand, | |
238 SSL3Hashes *hashes, PRBool bypassPKCS11) | |
239 { | |
240 PRUint8 *hashBuf; | |
241 PRUint8 *pBuf; | |
242 SECStatus rv = SECSuccess; | |
243 unsigned int bufLen; | |
244 /* | |
245 * XXX For now, we only support named curves (the appropriate | |
246 * checks are made before this method is called) so ec_params | |
247 * takes up only two bytes. ECPoint needs to fit in 256 bytes | |
248 * (because the spec says the length must fit in one byte) | |
249 */ | |
250 PRUint8 buf[2 * SSL3_RANDOM_LENGTH + 2 + 1 + 256]; | |
251 | |
252 bufLen = 2 * SSL3_RANDOM_LENGTH + ec_params.len + 1 + server_ecpoint.len; | |
253 if (bufLen <= sizeof buf) { | |
254 hashBuf = buf; | |
255 } else { | |
256 hashBuf = PORT_Alloc(bufLen); | |
257 if (!hashBuf) { | |
258 return SECFailure; | |
259 } | |
260 } | |
261 | |
262 memcpy(hashBuf, client_rand, SSL3_RANDOM_LENGTH); | |
263 pBuf = hashBuf + SSL3_RANDOM_LENGTH; | |
264 memcpy(pBuf, server_rand, SSL3_RANDOM_LENGTH); | |
265 pBuf += SSL3_RANDOM_LENGTH; | |
266 memcpy(pBuf, ec_params.data, ec_params.len); | |
267 pBuf += ec_params.len; | |
268 pBuf[0] = (PRUint8)(server_ecpoint.len); | |
269 pBuf += 1; | |
270 memcpy(pBuf, server_ecpoint.data, server_ecpoint.len); | |
271 pBuf += server_ecpoint.len; | |
272 PORT_Assert((unsigned int)(pBuf - hashBuf) == bufLen); | |
273 | |
274 rv = ssl3_ComputeCommonKeyHash(hashAlg, hashBuf, bufLen, hashes, | |
275 bypassPKCS11); | |
276 | |
277 PRINT_BUF(95, (NULL, "ECDHkey hash: ", hashBuf, bufLen)); | |
278 PRINT_BUF(95, (NULL, "ECDHkey hash: MD5 result", | |
279 hashes->u.s.md5, MD5_LENGTH)); | |
280 PRINT_BUF(95, (NULL, "ECDHkey hash: SHA1 result", | |
281 hashes->u.s.sha, SHA1_LENGTH)); | |
282 | |
283 if (hashBuf != buf) | |
284 PORT_Free(hashBuf); | |
285 return rv; | |
286 } | |
287 | |
288 /* Called from ssl3_SendClientKeyExchange(). */ | |
289 SECStatus | |
290 ssl3_SendECDHClientKeyExchange(sslSocket *ss, SECKEYPublicKey *svrPubKey) | |
291 { | |
292 PK11SymKey *pms = NULL; | |
293 SECStatus rv = SECFailure; | |
294 PRBool isTLS, isTLS12; | |
295 CK_MECHANISM_TYPE target; | |
296 SECKEYPublicKey *pubKey = NULL; /* Ephemeral ECDH key */ | |
297 SECKEYPrivateKey *privKey = NULL; /* Ephemeral ECDH key */ | |
298 | |
299 PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); | |
300 PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); | |
301 | |
302 isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0); | |
303 isTLS12 = (PRBool)(ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2); | |
304 | |
305 /* Generate ephemeral EC keypair */ | |
306 if (svrPubKey->keyType != ecKey) { | |
307 PORT_SetError(SEC_ERROR_BAD_KEY); | |
308 goto loser; | |
309 } | |
310 /* XXX SHOULD CALL ssl3_CreateECDHEphemeralKeys here, instead! */ | |
311 privKey = SECKEY_CreateECPrivateKey(&svrPubKey->u.ec.DEREncodedParams, | |
312 &pubKey, ss->pkcs11PinArg); | |
313 if (!privKey || !pubKey) { | |
314 ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL); | |
315 rv = SECFailure; | |
316 goto loser; | |
317 } | |
318 PRINT_BUF(50, (ss, "ECDH public value:", | |
319 pubKey->u.ec.publicValue.data, | |
320 pubKey->u.ec.publicValue.len)); | |
321 | |
322 if (isTLS12) { | |
323 target = CKM_TLS12_MASTER_KEY_DERIVE_DH; | |
324 } else if (isTLS) { | |
325 target = CKM_TLS_MASTER_KEY_DERIVE_DH; | |
326 } else { | |
327 target = CKM_SSL3_MASTER_KEY_DERIVE_DH; | |
328 } | |
329 | |
330 /* Determine the PMS */ | |
331 pms = PK11_PubDeriveWithKDF(privKey, svrPubKey, PR_FALSE, NULL, NULL, | |
332 CKM_ECDH1_DERIVE, target, CKA_DERIVE, 0, | |
333 CKD_NULL, NULL, NULL); | |
334 | |
335 if (pms == NULL) { | |
336 SSL3AlertDescription desc = illegal_parameter; | |
337 (void)SSL3_SendAlert(ss, alert_fatal, desc); | |
338 ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); | |
339 goto loser; | |
340 } | |
341 | |
342 SECKEY_DestroyPrivateKey(privKey); | |
343 privKey = NULL; | |
344 | |
345 rv = ssl3_AppendHandshakeHeader(ss, client_key_exchange, | |
346 pubKey->u.ec.publicValue.len + 1); | |
347 if (rv != SECSuccess) { | |
348 goto loser; /* err set by ssl3_AppendHandshake* */ | |
349 } | |
350 | |
351 rv = ssl3_AppendHandshakeVariable(ss, | |
352 pubKey->u.ec.publicValue.data, | |
353 pubKey->u.ec.publicValue.len, 1); | |
354 SECKEY_DestroyPublicKey(pubKey); | |
355 pubKey = NULL; | |
356 | |
357 if (rv != SECSuccess) { | |
358 goto loser; /* err set by ssl3_AppendHandshake* */ | |
359 } | |
360 | |
361 rv = ssl3_InitPendingCipherSpec(ss, pms); | |
362 PK11_FreeSymKey(pms); | |
363 pms = NULL; | |
364 | |
365 if (rv != SECSuccess) { | |
366 ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); | |
367 goto loser; | |
368 } | |
369 | |
370 rv = SECSuccess; | |
371 | |
372 loser: | |
373 if (pms) | |
374 PK11_FreeSymKey(pms); | |
375 if (privKey) | |
376 SECKEY_DestroyPrivateKey(privKey); | |
377 if (pubKey) | |
378 SECKEY_DestroyPublicKey(pubKey); | |
379 return rv; | |
380 } | |
381 | |
382 ECName | |
383 tls13_GroupForECDHEKeyShare(ssl3KeyPair *pair) | |
384 { | |
385 return ssl3_PubKey2ECName(pair->pubKey); | |
386 } | |
387 | |
388 /* This function returns the size of the key_exchange field in | |
389 * the KeyShareEntry structure. */ | |
390 unsigned int | |
391 tls13_SizeOfECDHEKeyShareKEX(ssl3KeyPair *pair) | |
392 { | |
393 return 1 + /* Length */ | |
394 pair->pubKey->u.ec.publicValue.len; | |
395 } | |
396 | |
397 /* This function encodes the key_exchange field in | |
398 * the KeyShareEntry structure. */ | |
399 SECStatus | |
400 tls13_EncodeECDHEKeyShareKEX(sslSocket *ss, ssl3KeyPair *pair) | |
401 { | |
402 const SECItem *publicValue; | |
403 | |
404 PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); | |
405 PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); | |
406 | |
407 publicValue = &pair->pubKey->u.ec.publicValue; | |
408 | |
409 return ssl3_AppendHandshakeVariable(ss, publicValue->data, | |
410 publicValue->len, 1); | |
411 } | |
412 | |
413 /* | |
414 ** Called from ssl3_HandleClientKeyExchange() | |
415 */ | |
416 SECStatus | |
417 ssl3_HandleECDHClientKeyExchange(sslSocket *ss, SSL3Opaque *b, | |
418 PRUint32 length, | |
419 SECKEYPublicKey *srvrPubKey, | |
420 SECKEYPrivateKey *srvrPrivKey) | |
421 { | |
422 PK11SymKey *pms; | |
423 SECStatus rv; | |
424 SECKEYPublicKey clntPubKey; | |
425 CK_MECHANISM_TYPE target; | |
426 PRBool isTLS, isTLS12; | |
427 | |
428 PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss)); | |
429 PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); | |
430 | |
431 clntPubKey.keyType = ecKey; | |
432 clntPubKey.u.ec.DEREncodedParams.len = | |
433 srvrPubKey->u.ec.DEREncodedParams.len; | |
434 clntPubKey.u.ec.DEREncodedParams.data = | |
435 srvrPubKey->u.ec.DEREncodedParams.data; | |
436 | |
437 rv = ssl3_ConsumeHandshakeVariable(ss, &clntPubKey.u.ec.publicValue, | |
438 1, &b, &length); | |
439 if (rv != SECSuccess) { | |
440 SEND_ALERT | |
441 return SECFailure; /* XXX Who sets the error code?? */ | |
442 } | |
443 | |
444 isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0); | |
445 isTLS12 = (PRBool)(ss->ssl3.prSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2); | |
446 | |
447 if (isTLS12) { | |
448 target = CKM_TLS12_MASTER_KEY_DERIVE_DH; | |
449 } else if (isTLS) { | |
450 target = CKM_TLS_MASTER_KEY_DERIVE_DH; | |
451 } else { | |
452 target = CKM_SSL3_MASTER_KEY_DERIVE_DH; | |
453 } | |
454 | |
455 /* Determine the PMS */ | |
456 pms = PK11_PubDeriveWithKDF(srvrPrivKey, &clntPubKey, PR_FALSE, NULL, NULL, | |
457 CKM_ECDH1_DERIVE, target, CKA_DERIVE, 0, | |
458 CKD_NULL, NULL, NULL); | |
459 | |
460 if (pms == NULL) { | |
461 /* last gasp. */ | |
462 ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); | |
463 return SECFailure; | |
464 } | |
465 | |
466 rv = ssl3_InitPendingCipherSpec(ss, pms); | |
467 PK11_FreeSymKey(pms); | |
468 if (rv != SECSuccess) { | |
469 SEND_ALERT | |
470 return SECFailure; /* error code set by ssl3_InitPendingCipherSpec */ | |
471 } | |
472 return SECSuccess; | |
473 } | |
474 | |
475 /* | |
476 ** Take an encoded key share and make a public key out of it. | |
477 ** returns NULL on error. | |
478 */ | |
479 SECKEYPublicKey * | |
480 tls13_ImportECDHKeyShare(sslSocket *ss, SSL3Opaque *b, | |
481 PRUint32 length, ECName curve) | |
482 { | |
483 PLArenaPool *arena = NULL; | |
484 SECKEYPublicKey *peerKey = NULL; | |
485 SECStatus rv; | |
486 SECItem ecPoint = { siBuffer, NULL, 0 }; | |
487 | |
488 PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss)); | |
489 PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); | |
490 | |
491 rv = ssl3_ConsumeHandshakeVariable(ss, &ecPoint, 1, &b, &length); | |
492 if (rv != SECSuccess) { | |
493 tls13_FatalError(ss, SSL_ERROR_RX_MALFORMED_ECDHE_KEY_SHARE, | |
494 illegal_parameter); | |
495 return NULL; | |
496 } | |
497 if (length || !ecPoint.len) { | |
498 tls13_FatalError(ss, SSL_ERROR_RX_MALFORMED_ECDHE_KEY_SHARE, | |
499 illegal_parameter); | |
500 return NULL; | |
501 } | |
502 | |
503 /* Fail if the ec point uses compressed representation */ | |
504 if (ecPoint.data[0] != EC_POINT_FORM_UNCOMPRESSED) { | |
505 tls13_FatalError(ss, SEC_ERROR_UNSUPPORTED_EC_POINT_FORM, | |
506 illegal_parameter); | |
507 return NULL; | |
508 } | |
509 | |
510 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | |
511 if (arena == NULL) { | |
512 goto no_memory; | |
513 } | |
514 | |
515 peerKey = PORT_ArenaZNew(arena, SECKEYPublicKey); | |
516 if (peerKey == NULL) { | |
517 goto no_memory; | |
518 } | |
519 | |
520 peerKey->arena = arena; | |
521 peerKey->keyType = ecKey; | |
522 /* Set up the encoded params */ | |
523 rv = ssl3_ECName2Params(arena, curve, &peerKey->u.ec.DEREncodedParams); | |
524 if (rv != SECSuccess) { | |
525 goto no_memory; | |
526 } | |
527 | |
528 /* copy publicValue in peerKey */ | |
529 if (SECITEM_CopyItem(arena, &peerKey->u.ec.publicValue, &ecPoint) != | |
530 SECSuccess) { | |
531 goto no_memory; | |
532 } | |
533 peerKey->pkcs11Slot = NULL; | |
534 peerKey->pkcs11ID = CK_INVALID_HANDLE; | |
535 | |
536 return peerKey; | |
537 | |
538 no_memory: /* no-memory error has already been set. */ | |
539 PORT_FreeArena(arena, PR_FALSE); | |
540 ssl_MapLowLevelError(SSL_ERROR_RX_MALFORMED_ECDHE_KEY_SHARE); | |
541 return NULL; | |
542 } | |
543 | |
544 PK11SymKey * | |
545 tls13_ComputeECDHSharedKey(sslSocket *ss, | |
546 SECKEYPrivateKey *myPrivKey, | |
547 SECKEYPublicKey *peerKey) | |
548 { | |
549 PK11SymKey *shared; | |
550 | |
551 /* Determine the PMS */ | |
552 shared = PK11_PubDeriveWithKDF(myPrivKey, peerKey, PR_FALSE, NULL, NULL, | |
553 CKM_ECDH1_DERIVE, | |
554 tls13_GetHkdfMechanism(ss), CKA_DERIVE, 0, | |
555 CKD_NULL, NULL, NULL); | |
556 | |
557 if (!shared) { | |
558 ssl_MapLowLevelError(SSL_ERROR_KEY_EXCHANGE_FAILURE); | |
559 return NULL; | |
560 } | |
561 | |
562 return shared; | |
563 } | |
564 | |
565 ECName | |
566 ssl3_GetCurveWithECKeyStrength(PRUint32 curvemsk, int requiredECCbits) | |
567 { | |
568 int i; | |
569 | |
570 for (i = 0; bits2curve[i].curve != ec_noName; i++) { | |
571 if (bits2curve[i].bits < requiredECCbits) | |
572 continue; | |
573 if (SSL_IS_CURVE_NEGOTIATED(curvemsk, bits2curve[i].curve)) { | |
574 return bits2curve[i].curve; | |
575 } | |
576 } | |
577 PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP); | |
578 return ec_noName; | |
579 } | |
580 | |
581 /* find the "weakest link". Get strength of signature key and of sym key. | |
582 * choose curve for the weakest of those two. | |
583 */ | |
584 ECName | |
585 ssl3_GetCurveNameForServerSocket(sslSocket *ss) | |
586 { | |
587 SECKEYPublicKey *svrPublicKey = NULL; | |
588 ECName ec_curve = ec_noName; | |
589 int signatureKeyStrength = 521; | |
590 int requiredECCbits = ss->sec.secretKeyBits * 2; | |
591 | |
592 if (ss->ssl3.hs.kea_def->kea == kea_ecdhe_ecdsa) { | |
593 svrPublicKey = SSL_GET_SERVER_PUBLIC_KEY(ss, kt_ecdh); | |
594 if (svrPublicKey) | |
595 ec_curve = ssl3_PubKey2ECName(svrPublicKey); | |
596 if (!SSL_IS_CURVE_NEGOTIATED(ss->ssl3.hs.negotiatedECCurves, ec_curve))
{ | |
597 PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP); | |
598 return ec_noName; | |
599 } | |
600 signatureKeyStrength = curve2bits[ec_curve]; | |
601 } else { | |
602 /* RSA is our signing cert */ | |
603 int serverKeyStrengthInBits; | |
604 | |
605 svrPublicKey = SSL_GET_SERVER_PUBLIC_KEY(ss, kt_rsa); | |
606 if (!svrPublicKey) { | |
607 PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP); | |
608 return ec_noName; | |
609 } | |
610 | |
611 /* currently strength in bytes */ | |
612 serverKeyStrengthInBits = svrPublicKey->u.rsa.modulus.len; | |
613 if (svrPublicKey->u.rsa.modulus.data[0] == 0) { | |
614 serverKeyStrengthInBits--; | |
615 } | |
616 /* convert to strength in bits */ | |
617 serverKeyStrengthInBits *= BPB; | |
618 | |
619 signatureKeyStrength = | |
620 SSL_RSASTRENGTH_TO_ECSTRENGTH(serverKeyStrengthInBits); | |
621 } | |
622 if (requiredECCbits > signatureKeyStrength) | |
623 requiredECCbits = signatureKeyStrength; | |
624 | |
625 return ssl3_GetCurveWithECKeyStrength(ss->ssl3.hs.negotiatedECCurves, | |
626 requiredECCbits); | |
627 } | |
628 | |
629 /* function to clear out the lists */ | |
630 static SECStatus | |
631 ssl3_ShutdownECDHECurves(void *appData, void *nssData) | |
632 { | |
633 int i; | |
634 ECDHEKeyPair *keyPair = &gECDHEKeyPairs[0]; | |
635 | |
636 for (i = 0; i < ec_pastLastName; i++, keyPair++) { | |
637 if (keyPair->pair) { | |
638 ssl3_FreeKeyPair(keyPair->pair); | |
639 } | |
640 } | |
641 memset(gECDHEKeyPairs, 0, sizeof gECDHEKeyPairs); | |
642 return SECSuccess; | |
643 } | |
644 | |
645 static PRStatus | |
646 ssl3_ECRegister(void) | |
647 { | |
648 SECStatus rv; | |
649 rv = NSS_RegisterShutdown(ssl3_ShutdownECDHECurves, gECDHEKeyPairs); | |
650 if (rv != SECSuccess) { | |
651 gECDHEKeyPairs[ec_noName].error = PORT_GetError(); | |
652 } | |
653 return (PRStatus)rv; | |
654 } | |
655 | |
656 /* Create an ECDHE key pair for a given curve */ | |
657 SECStatus | |
658 ssl3_CreateECDHEphemeralKeyPair(ECName ec_curve, ssl3KeyPair **keyPair) | |
659 { | |
660 SECKEYPrivateKey *privKey = NULL; | |
661 SECKEYPublicKey *pubKey = NULL; | |
662 SECKEYECParams ecParams = { siBuffer, NULL, 0 }; | |
663 | |
664 if (ssl3_ECName2Params(NULL, ec_curve, &ecParams) != SECSuccess) { | |
665 return SECFailure; | |
666 } | |
667 privKey = SECKEY_CreateECPrivateKey(&ecParams, &pubKey, NULL); | |
668 SECITEM_FreeItem(&ecParams, PR_FALSE); | |
669 | |
670 if (!privKey || !pubKey || !(*keyPair = ssl3_NewKeyPair(privKey, pubKey))) { | |
671 if (privKey) { | |
672 SECKEY_DestroyPrivateKey(privKey); | |
673 } | |
674 if (pubKey) { | |
675 SECKEY_DestroyPublicKey(pubKey); | |
676 } | |
677 ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL); | |
678 return SECFailure; | |
679 } | |
680 | |
681 return SECSuccess; | |
682 } | |
683 | |
684 /* CallOnce function, called once for each named curve. */ | |
685 static PRStatus | |
686 ssl3_CreateECDHEphemeralKeyPairOnce(void *arg) | |
687 { | |
688 ECName ec_curve = (ECName)arg; | |
689 ssl3KeyPair *keyPair = NULL; | |
690 | |
691 PORT_Assert(gECDHEKeyPairs[ec_curve].pair == NULL); | |
692 | |
693 /* ok, no one has generated a global key for this curve yet, do so */ | |
694 if (ssl3_CreateECDHEphemeralKeyPair(ec_curve, &keyPair) != SECSuccess) { | |
695 gECDHEKeyPairs[ec_curve].error = PORT_GetError(); | |
696 return PR_FAILURE; | |
697 } | |
698 | |
699 gECDHEKeyPairs[ec_curve].pair = keyPair; | |
700 return PR_SUCCESS; | |
701 } | |
702 | |
703 /* | |
704 * Creates the ephemeral public and private ECDH keys used by | |
705 * server in ECDHE_RSA and ECDHE_ECDSA handshakes. | |
706 * For now, the elliptic curve is chosen to be the same | |
707 * strength as the signing certificate (ECC or RSA). | |
708 * We need an API to specify the curve. This won't be a real | |
709 * issue until we further develop server-side support for ECC | |
710 * cipher suites. | |
711 */ | |
712 static SECStatus | |
713 ssl3_CreateECDHEphemeralKeys(sslSocket *ss, ECName ec_curve) | |
714 { | |
715 ssl3KeyPair *keyPair = NULL; | |
716 | |
717 /* if there's no global key for this curve, make one. */ | |
718 if (gECDHEKeyPairs[ec_curve].pair == NULL) { | |
719 PRStatus status; | |
720 | |
721 status = PR_CallOnce(&gECDHEKeyPairs[ec_noName].once, ssl3_ECRegister); | |
722 if (status != PR_SUCCESS) { | |
723 PORT_SetError(gECDHEKeyPairs[ec_noName].error); | |
724 return SECFailure; | |
725 } | |
726 status = PR_CallOnceWithArg(&gECDHEKeyPairs[ec_curve].once, | |
727 ssl3_CreateECDHEphemeralKeyPairOnce, | |
728 (void *)ec_curve); | |
729 if (status != PR_SUCCESS) { | |
730 PORT_SetError(gECDHEKeyPairs[ec_curve].error); | |
731 return SECFailure; | |
732 } | |
733 } | |
734 | |
735 keyPair = gECDHEKeyPairs[ec_curve].pair; | |
736 PORT_Assert(keyPair != NULL); | |
737 if (!keyPair) | |
738 return SECFailure; | |
739 ss->ephemeralECDHKeyPair = ssl3_GetKeyPairRef(keyPair); | |
740 | |
741 return SECSuccess; | |
742 } | |
743 | |
744 SECStatus | |
745 ssl3_HandleECDHServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length) | |
746 { | |
747 PLArenaPool *arena = NULL; | |
748 SECKEYPublicKey *peerKey = NULL; | |
749 PRBool isTLS, isTLS12; | |
750 SECStatus rv; | |
751 int errCode = SSL_ERROR_RX_MALFORMED_SERVER_KEY_EXCH; | |
752 SSL3AlertDescription desc = illegal_parameter; | |
753 SSL3Hashes hashes; | |
754 SECItem signature = { siBuffer, NULL, 0 }; | |
755 | |
756 SECItem ec_params = { siBuffer, NULL, 0 }; | |
757 SECItem ec_point = { siBuffer, NULL, 0 }; | |
758 unsigned char paramBuf[3]; /* only for curve_type == named_curve */ | |
759 SSLSignatureAndHashAlg sigAndHash; | |
760 | |
761 sigAndHash.hashAlg = ssl_hash_none; | |
762 | |
763 isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0); | |
764 isTLS12 = (PRBool)(ss->ssl3.prSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2); | |
765 | |
766 /* XXX This works only for named curves, revisit this when | |
767 * we support generic curves. | |
768 */ | |
769 ec_params.len = sizeof paramBuf; | |
770 ec_params.data = paramBuf; | |
771 rv = ssl3_ConsumeHandshake(ss, ec_params.data, ec_params.len, &b, &length); | |
772 if (rv != SECSuccess) { | |
773 goto loser; /* malformed. */ | |
774 } | |
775 | |
776 /* Fail if the curve is not a named curve */ | |
777 if ((ec_params.data[0] != ec_type_named) || | |
778 (ec_params.data[1] != 0) || | |
779 !supportedCurve(ec_params.data[2])) { | |
780 errCode = SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE; | |
781 desc = handshake_failure; | |
782 goto alert_loser; | |
783 } | |
784 | |
785 rv = ssl3_ConsumeHandshakeVariable(ss, &ec_point, 1, &b, &length); | |
786 if (rv != SECSuccess) { | |
787 goto loser; /* malformed. */ | |
788 } | |
789 /* Fail if the ec point uses compressed representation */ | |
790 if (ec_point.data[0] != EC_POINT_FORM_UNCOMPRESSED) { | |
791 errCode = SEC_ERROR_UNSUPPORTED_EC_POINT_FORM; | |
792 desc = handshake_failure; | |
793 goto alert_loser; | |
794 } | |
795 | |
796 if (isTLS12) { | |
797 rv = ssl3_ConsumeSignatureAndHashAlgorithm(ss, &b, &length, | |
798 &sigAndHash); | |
799 if (rv != SECSuccess) { | |
800 goto loser; /* malformed or unsupported. */ | |
801 } | |
802 rv = ssl3_CheckSignatureAndHashAlgorithmConsistency( | |
803 ss, &sigAndHash, ss->sec.peerCert); | |
804 if (rv != SECSuccess) { | |
805 goto loser; | |
806 } | |
807 } | |
808 | |
809 rv = ssl3_ConsumeHandshakeVariable(ss, &signature, 2, &b, &length); | |
810 if (rv != SECSuccess) { | |
811 goto loser; /* malformed. */ | |
812 } | |
813 | |
814 if (length != 0) { | |
815 if (isTLS) | |
816 desc = decode_error; | |
817 goto alert_loser; /* malformed. */ | |
818 } | |
819 | |
820 PRINT_BUF(60, (NULL, "Server EC params", ec_params.data, | |
821 ec_params.len)); | |
822 PRINT_BUF(60, (NULL, "Server EC point", ec_point.data, ec_point.len)); | |
823 | |
824 /* failures after this point are not malformed handshakes. */ | |
825 /* TLS: send decrypt_error if signature failed. */ | |
826 desc = isTLS ? decrypt_error : handshake_failure; | |
827 | |
828 /* | |
829 * check to make sure the hash is signed by right guy | |
830 */ | |
831 rv = ssl3_ComputeECDHKeyHash(sigAndHash.hashAlg, ec_params, ec_point, | |
832 &ss->ssl3.hs.client_random, | |
833 &ss->ssl3.hs.server_random, | |
834 &hashes, ss->opt.bypassPKCS11); | |
835 | |
836 if (rv != SECSuccess) { | |
837 errCode = | |
838 ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE); | |
839 goto alert_loser; | |
840 } | |
841 rv = ssl3_VerifySignedHashes(&hashes, ss->sec.peerCert, &signature, | |
842 isTLS, ss->pkcs11PinArg); | |
843 if (rv != SECSuccess) { | |
844 errCode = | |
845 ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE); | |
846 goto alert_loser; | |
847 } | |
848 | |
849 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | |
850 if (arena == NULL) { | |
851 goto no_memory; | |
852 } | |
853 | |
854 peerKey = PORT_ArenaZNew(arena, SECKEYPublicKey); | |
855 if (peerKey == NULL) { | |
856 goto no_memory; | |
857 } | |
858 | |
859 peerKey->arena = arena; | |
860 peerKey->keyType = ecKey; | |
861 | |
862 /* set up EC parameters in peerKey */ | |
863 if (ssl3_ECName2Params(arena, ec_params.data[2], | |
864 &peerKey->u.ec.DEREncodedParams) != | |
865 SECSuccess) { | |
866 /* we should never get here since we already | |
867 * checked that we are dealing with a supported curve | |
868 */ | |
869 errCode = SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE; | |
870 goto alert_loser; | |
871 } | |
872 | |
873 /* copy publicValue in peerKey */ | |
874 if (SECITEM_CopyItem(arena, &peerKey->u.ec.publicValue, &ec_point)) { | |
875 goto no_memory; | |
876 } | |
877 peerKey->pkcs11Slot = NULL; | |
878 peerKey->pkcs11ID = CK_INVALID_HANDLE; | |
879 | |
880 ss->sec.peerKey = peerKey; | |
881 ss->ssl3.hs.ws = wait_cert_request; | |
882 | |
883 return SECSuccess; | |
884 | |
885 alert_loser: | |
886 (void)SSL3_SendAlert(ss, alert_fatal, desc); | |
887 loser: | |
888 if (arena) { | |
889 PORT_FreeArena(arena, PR_FALSE); | |
890 } | |
891 PORT_SetError(errCode); | |
892 return SECFailure; | |
893 | |
894 no_memory: /* no-memory error has already been set. */ | |
895 if (arena) { | |
896 PORT_FreeArena(arena, PR_FALSE); | |
897 } | |
898 ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE); | |
899 return SECFailure; | |
900 } | |
901 | |
902 SECStatus | |
903 ssl3_SendECDHServerKeyExchange( | |
904 sslSocket *ss, | |
905 const SSLSignatureAndHashAlg *sigAndHash) | |
906 { | |
907 const ssl3KEADef *kea_def = ss->ssl3.hs.kea_def; | |
908 SECStatus rv = SECFailure; | |
909 int length; | |
910 PRBool isTLS, isTLS12; | |
911 SECItem signed_hash = { siBuffer, NULL, 0 }; | |
912 SSL3Hashes hashes; | |
913 | |
914 SECKEYPublicKey *ecdhePub; | |
915 SECItem ec_params = { siBuffer, NULL, 0 }; | |
916 unsigned char paramBuf[3]; | |
917 ECName curve; | |
918 SSL3KEAType certIndex; | |
919 | |
920 /* Generate ephemeral ECDH key pair and send the public key */ | |
921 curve = ssl3_GetCurveNameForServerSocket(ss); | |
922 if (curve == ec_noName) { | |
923 goto loser; | |
924 } | |
925 | |
926 if (ss->opt.reuseServerECDHEKey) { | |
927 rv = ssl3_CreateECDHEphemeralKeys(ss, curve); | |
928 } else { | |
929 rv = ssl3_CreateECDHEphemeralKeyPair(curve, &ss->ephemeralECDHKeyPair); | |
930 } | |
931 if (rv != SECSuccess) { | |
932 goto loser; | |
933 } | |
934 | |
935 ecdhePub = ss->ephemeralECDHKeyPair->pubKey; | |
936 PORT_Assert(ecdhePub != NULL); | |
937 if (!ecdhePub) { | |
938 PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE); | |
939 return SECFailure; | |
940 } | |
941 | |
942 ec_params.len = sizeof paramBuf; | |
943 ec_params.data = paramBuf; | |
944 curve = ssl3_PubKey2ECName(ecdhePub); | |
945 if (curve != ec_noName) { | |
946 ec_params.data[0] = ec_type_named; | |
947 ec_params.data[1] = 0x00; | |
948 ec_params.data[2] = curve; | |
949 } else { | |
950 PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); | |
951 goto loser; | |
952 } | |
953 | |
954 rv = ssl3_ComputeECDHKeyHash(sigAndHash->hashAlg, | |
955 ec_params, | |
956 ecdhePub->u.ec.publicValue, | |
957 &ss->ssl3.hs.client_random, | |
958 &ss->ssl3.hs.server_random, | |
959 &hashes, ss->opt.bypassPKCS11); | |
960 if (rv != SECSuccess) { | |
961 ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE); | |
962 goto loser; | |
963 } | |
964 | |
965 isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0); | |
966 isTLS12 = (PRBool)(ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2); | |
967 | |
968 /* XXX SSLKEAType isn't really a good choice for | |
969 * indexing certificates but that's all we have | |
970 * for now. | |
971 */ | |
972 if (kea_def->kea == kea_ecdhe_rsa) | |
973 certIndex = kt_rsa; | |
974 else /* kea_def->kea == kea_ecdhe_ecdsa */ | |
975 certIndex = kt_ecdh; | |
976 | |
977 rv = ssl3_SignHashes(&hashes, ss->serverCerts[certIndex].SERVERKEY, | |
978 &signed_hash, isTLS); | |
979 if (rv != SECSuccess) { | |
980 goto loser; /* ssl3_SignHashes has set err. */ | |
981 } | |
982 if (signed_hash.data == NULL) { | |
983 /* how can this happen and rv == SECSuccess ?? */ | |
984 PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE); | |
985 goto loser; | |
986 } | |
987 | |
988 length = ec_params.len + | |
989 1 + ecdhePub->u.ec.publicValue.len + | |
990 (isTLS12 ? 2 : 0) + 2 + signed_hash.len; | |
991 | |
992 rv = ssl3_AppendHandshakeHeader(ss, server_key_exchange, length); | |
993 if (rv != SECSuccess) { | |
994 goto loser; /* err set by AppendHandshake. */ | |
995 } | |
996 | |
997 rv = ssl3_AppendHandshake(ss, ec_params.data, ec_params.len); | |
998 if (rv != SECSuccess) { | |
999 goto loser; /* err set by AppendHandshake. */ | |
1000 } | |
1001 | |
1002 rv = ssl3_AppendHandshakeVariable(ss, ecdhePub->u.ec.publicValue.data, | |
1003 ecdhePub->u.ec.publicValue.len, 1); | |
1004 if (rv != SECSuccess) { | |
1005 goto loser; /* err set by AppendHandshake. */ | |
1006 } | |
1007 | |
1008 if (isTLS12) { | |
1009 rv = ssl3_AppendSignatureAndHashAlgorithm(ss, sigAndHash); | |
1010 if (rv != SECSuccess) { | |
1011 goto loser; /* err set by AppendHandshake. */ | |
1012 } | |
1013 } | |
1014 | |
1015 rv = ssl3_AppendHandshakeVariable(ss, signed_hash.data, | |
1016 signed_hash.len, 2); | |
1017 if (rv != SECSuccess) { | |
1018 goto loser; /* err set by AppendHandshake. */ | |
1019 } | |
1020 | |
1021 PORT_Free(signed_hash.data); | |
1022 return SECSuccess; | |
1023 | |
1024 loser: | |
1025 if (signed_hash.data != NULL) | |
1026 PORT_Free(signed_hash.data); | |
1027 return SECFailure; | |
1028 } | |
1029 | |
1030 /* Lists of ECC cipher suites for searching and disabling. */ | |
1031 | |
1032 static const ssl3CipherSuite ecdh_suites[] = { | |
1033 TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, | |
1034 TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, | |
1035 TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, | |
1036 TLS_ECDH_ECDSA_WITH_NULL_SHA, | |
1037 TLS_ECDH_ECDSA_WITH_RC4_128_SHA, | |
1038 TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, | |
1039 TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, | |
1040 TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, | |
1041 TLS_ECDH_RSA_WITH_NULL_SHA, | |
1042 TLS_ECDH_RSA_WITH_RC4_128_SHA, | |
1043 0 /* end of list marker */ | |
1044 }; | |
1045 | |
1046 static const ssl3CipherSuite ecdh_ecdsa_suites[] = { | |
1047 TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, | |
1048 TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, | |
1049 TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, | |
1050 TLS_ECDH_ECDSA_WITH_NULL_SHA, | |
1051 TLS_ECDH_ECDSA_WITH_RC4_128_SHA, | |
1052 0 /* end of list marker */ | |
1053 }; | |
1054 | |
1055 static const ssl3CipherSuite ecdh_rsa_suites[] = { | |
1056 TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, | |
1057 TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, | |
1058 TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, | |
1059 TLS_ECDH_RSA_WITH_NULL_SHA, | |
1060 TLS_ECDH_RSA_WITH_RC4_128_SHA, | |
1061 0 /* end of list marker */ | |
1062 }; | |
1063 | |
1064 static const ssl3CipherSuite ecdhe_ecdsa_suites[] = { | |
1065 TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, | |
1066 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, | |
1067 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, | |
1068 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, | |
1069 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, | |
1070 TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, | |
1071 TLS_ECDHE_ECDSA_WITH_NULL_SHA, | |
1072 TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, | |
1073 0 /* end of list marker */ | |
1074 }; | |
1075 | |
1076 static const ssl3CipherSuite ecdhe_rsa_suites[] = { | |
1077 TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, | |
1078 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, | |
1079 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, | |
1080 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, | |
1081 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, | |
1082 TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, | |
1083 TLS_ECDHE_RSA_WITH_NULL_SHA, | |
1084 TLS_ECDHE_RSA_WITH_RC4_128_SHA, | |
1085 0 /* end of list marker */ | |
1086 }; | |
1087 | |
1088 /* List of all ECC cipher suites */ | |
1089 static const ssl3CipherSuite ecSuites[] = { | |
1090 TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, | |
1091 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, | |
1092 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, | |
1093 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, | |
1094 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, | |
1095 TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, | |
1096 TLS_ECDHE_ECDSA_WITH_NULL_SHA, | |
1097 TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, | |
1098 TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, | |
1099 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, | |
1100 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, | |
1101 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, | |
1102 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, | |
1103 TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, | |
1104 TLS_ECDHE_RSA_WITH_NULL_SHA, | |
1105 TLS_ECDHE_RSA_WITH_RC4_128_SHA, | |
1106 TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, | |
1107 TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, | |
1108 TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, | |
1109 TLS_ECDH_ECDSA_WITH_NULL_SHA, | |
1110 TLS_ECDH_ECDSA_WITH_RC4_128_SHA, | |
1111 TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, | |
1112 TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, | |
1113 TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, | |
1114 TLS_ECDH_RSA_WITH_NULL_SHA, | |
1115 TLS_ECDH_RSA_WITH_RC4_128_SHA, | |
1116 0 /* end of list marker */ | |
1117 }; | |
1118 | |
1119 /* On this socket, Disable the ECC cipher suites in the argument's list */ | |
1120 SECStatus | |
1121 ssl3_DisableECCSuites(sslSocket *ss, const ssl3CipherSuite *suite) | |
1122 { | |
1123 if (!suite) | |
1124 suite = ecSuites; | |
1125 for (; *suite; ++suite) { | |
1126 PORT_CheckSuccess(ssl3_CipherPrefSet(ss, *suite, PR_FALSE)); | |
1127 } | |
1128 return SECSuccess; | |
1129 } | |
1130 | |
1131 /* Look at the server certs configured on this socket, and disable any | |
1132 * ECC cipher suites that are not supported by those certs. | |
1133 */ | |
1134 void | |
1135 ssl3_FilterECCipherSuitesByServerCerts(sslSocket *ss) | |
1136 { | |
1137 CERTCertificate *svrCert; | |
1138 | |
1139 svrCert = ss->serverCerts[kt_rsa].serverCert; | |
1140 if (!svrCert) { | |
1141 ssl3_DisableECCSuites(ss, ecdhe_rsa_suites); | |
1142 } | |
1143 | |
1144 svrCert = ss->serverCerts[kt_ecdh].serverCert; | |
1145 if (!svrCert) { | |
1146 ssl3_DisableECCSuites(ss, ecdh_suites); | |
1147 ssl3_DisableECCSuites(ss, ecdhe_ecdsa_suites); | |
1148 } else { | |
1149 SECOidTag sigTag = SECOID_GetAlgorithmTag(&svrCert->signature); | |
1150 | |
1151 switch (sigTag) { | |
1152 case SEC_OID_PKCS1_RSA_ENCRYPTION: | |
1153 case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION: | |
1154 case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION: | |
1155 case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION: | |
1156 case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION: | |
1157 case SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION: | |
1158 case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION: | |
1159 case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION: | |
1160 case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION: | |
1161 ssl3_DisableECCSuites(ss, ecdh_ecdsa_suites); | |
1162 break; | |
1163 case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE: | |
1164 case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE: | |
1165 case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE: | |
1166 case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE: | |
1167 case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE: | |
1168 case SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST: | |
1169 case SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST: | |
1170 ssl3_DisableECCSuites(ss, ecdh_rsa_suites); | |
1171 break; | |
1172 default: | |
1173 ssl3_DisableECCSuites(ss, ecdh_suites); | |
1174 break; | |
1175 } | |
1176 } | |
1177 } | |
1178 | |
1179 /* Ask: is ANY ECC cipher suite enabled on this socket? */ | |
1180 /* Order(N^2). Yuk. Also, this ignores export policy. */ | |
1181 PRBool | |
1182 ssl3_IsECCEnabled(sslSocket *ss) | |
1183 { | |
1184 const ssl3CipherSuite *suite; | |
1185 PK11SlotInfo *slot; | |
1186 | |
1187 /* make sure we can do ECC */ | |
1188 slot = PK11_GetBestSlot(CKM_ECDH1_DERIVE, ss->pkcs11PinArg); | |
1189 if (!slot) { | |
1190 return PR_FALSE; | |
1191 } | |
1192 PK11_FreeSlot(slot); | |
1193 | |
1194 /* make sure an ECC cipher is enabled */ | |
1195 for (suite = ecSuites; *suite; ++suite) { | |
1196 PRBool enabled = PR_FALSE; | |
1197 SECStatus rv = ssl3_CipherPrefGet(ss, *suite, &enabled); | |
1198 | |
1199 PORT_Assert(rv == SECSuccess); /* else is coding error */ | |
1200 if (rv == SECSuccess && enabled) | |
1201 return PR_TRUE; | |
1202 } | |
1203 return PR_FALSE; | |
1204 } | |
1205 | |
1206 #define BE(n) 0, n | |
1207 | |
1208 /* Prefabricated TLS client hello extension, Elliptic Curves List, | |
1209 * offers only 3 curves, the Suite B curves, 23-25 | |
1210 */ | |
1211 static const PRUint8 suiteBECList[] = { | |
1212 23, 24, 25 | |
1213 }; | |
1214 | |
1215 /* Prefabricated TLS client hello extension, Elliptic Curves List, | |
1216 * offers curves 1-25. | |
1217 */ | |
1218 /* clang-format off */ | |
1219 static const PRUint8 tlsECList[] = { | |
1220 1, 2, 3, 4, 5, 6, 7, 8, | |
1221 9, 10, 11, 12, 13, 14, 15, 16, | |
1222 17, 18, 19, 20, 21, 22, 23, 24, | |
1223 25 | |
1224 }; | |
1225 /* clang-format on */ | |
1226 | |
1227 static const PRUint8 ecPtFmt[6] = { | |
1228 BE(11), /* Extension type */ | |
1229 BE(2), /* octets that follow */ | |
1230 1, /* octets that follow */ | |
1231 0 /* uncompressed type only */ | |
1232 }; | |
1233 | |
1234 /* This function already presumes we can do ECC, ssl3_IsECCEnabled must be | |
1235 * called before this function. It looks to see if we have a token which | |
1236 * is capable of doing smaller than SuiteB curves. If the token can, we | |
1237 * presume the token can do the whole SSL suite of curves. If it can't we | |
1238 * presume the token that allowed ECC to be enabled can only do suite B | |
1239 * curves. */ | |
1240 static PRBool | |
1241 ssl3_SuiteBOnly(sslSocket *ss) | |
1242 { | |
1243 /* See if we can support small curves (like 163). If not, assume we can | |
1244 * only support Suite-B curves (P-256, P-384, P-521). */ | |
1245 PK11SlotInfo *slot = | |
1246 PK11_GetBestSlotWithAttributes(CKM_ECDH1_DERIVE, 0, 163, | |
1247 ss ? ss->pkcs11PinArg : NULL); | |
1248 | |
1249 if (!slot) { | |
1250 /* nope, presume we can only do suite B */ | |
1251 return PR_TRUE; | |
1252 } | |
1253 /* we can, presume we can do all curves */ | |
1254 PK11_FreeSlot(slot); | |
1255 return PR_FALSE; | |
1256 } | |
1257 | |
1258 #define APPEND_CURVE(CURVE_ID) \ | |
1259 if ((NSS_GetAlgorithmPolicy(ecName2OIDTag[CURVE_ID], &policy) == \ | |
1260 SECFailure) || \ | |
1261 (policy & NSS_USE_ALG_IN_SSL_KX)) { \ | |
1262 enabledCurves[pos++] = 0; \ | |
1263 enabledCurves[pos++] = CURVE_ID; \ | |
1264 } | |
1265 | |
1266 /* Send our "canned" (precompiled) Supported Elliptic Curves extension, | |
1267 * which says that we support all TLS-defined named curves. | |
1268 */ | |
1269 PRInt32 | |
1270 ssl3_SendSupportedCurvesXtn( | |
1271 sslSocket *ss, | |
1272 PRBool append, | |
1273 PRUint32 maxBytes) | |
1274 { | |
1275 unsigned char enabledCurves[64]; | |
1276 PRUint32 policy; | |
1277 PRInt32 extension_length; | |
1278 PRInt32 ecListSize = 0; | |
1279 unsigned int pos = 0; | |
1280 unsigned int i; | |
1281 | |
1282 if (!ss || !ssl3_IsECCEnabled(ss)) | |
1283 return 0; | |
1284 | |
1285 PORT_Assert(sizeof(enabledCurves) > sizeof(tlsECList) * 2); | |
1286 if (ssl3_SuiteBOnly(ss)) { | |
1287 for (i = 0; i < sizeof(suiteBECList); i++) { | |
1288 APPEND_CURVE(suiteBECList[i]); | |
1289 } | |
1290 ecListSize = pos; | |
1291 } else { | |
1292 for (i = 0; i < sizeof(tlsECList); i++) { | |
1293 APPEND_CURVE(tlsECList[i]); | |
1294 } | |
1295 ecListSize = pos; | |
1296 } | |
1297 extension_length = | |
1298 2 /* extension type */ + | |
1299 2 /* extension length */ + | |
1300 2 /* elliptic curves length */ + | |
1301 ecListSize; | |
1302 | |
1303 if (maxBytes < (PRUint32)extension_length) { | |
1304 return 0; | |
1305 } | |
1306 | |
1307 if (append) { | |
1308 SECStatus rv; | |
1309 rv = ssl3_AppendHandshakeNumber(ss, ssl_elliptic_curves_xtn, 2); | |
1310 if (rv != SECSuccess) | |
1311 return -1; | |
1312 rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2); | |
1313 if (rv != SECSuccess) | |
1314 return -1; | |
1315 rv = ssl3_AppendHandshakeVariable(ss, enabledCurves, ecListSize, 2); | |
1316 if (rv != SECSuccess) | |
1317 return -1; | |
1318 if (!ss->sec.isServer) { | |
1319 TLSExtensionData *xtnData = &ss->xtnData; | |
1320 xtnData->advertised[xtnData->numAdvertised++] = | |
1321 ssl_elliptic_curves_xtn; | |
1322 } | |
1323 } | |
1324 return extension_length; | |
1325 } | |
1326 | |
1327 PRUint32 | |
1328 ssl3_GetSupportedECCurveMask(sslSocket *ss) | |
1329 { | |
1330 int i; | |
1331 PRUint32 curves = 0; | |
1332 PRUint32 policyFlags = 0; | |
1333 | |
1334 PORT_Assert(ec_pastLastName < sizeof(PRUint32) * 8); | |
1335 | |
1336 if (ssl3_SuiteBOnly(ss)) { | |
1337 curves = SSL3_SUITE_B_SUPPORTED_CURVES_MASK; | |
1338 } else { | |
1339 curves = SSL3_ALL_SUPPORTED_CURVES_MASK; | |
1340 } | |
1341 | |
1342 for (i = ec_noName + 1; i < ec_pastLastName; i++) { | |
1343 PRUint32 curve_bit = (1U << i); | |
1344 if ((curves & curve_bit) && | |
1345 (NSS_GetAlgorithmPolicy(ecName2OIDTag[i], &policyFlags) == | |
1346 SECSuccess) && | |
1347 !(policyFlags & NSS_USE_ALG_IN_SSL_KX)) { | |
1348 curves &= ~curve_bit; | |
1349 } | |
1350 } | |
1351 return curves; | |
1352 } | |
1353 | |
1354 /* Send our "canned" (precompiled) Supported Point Formats extension, | |
1355 * which says that we only support uncompressed points. | |
1356 */ | |
1357 PRInt32 | |
1358 ssl3_SendSupportedPointFormatsXtn( | |
1359 sslSocket *ss, | |
1360 PRBool append, | |
1361 PRUint32 maxBytes) | |
1362 { | |
1363 if (!ss || !ssl3_IsECCEnabled(ss)) | |
1364 return 0; | |
1365 if (append && maxBytes >= (sizeof ecPtFmt)) { | |
1366 SECStatus rv = ssl3_AppendHandshake(ss, ecPtFmt, (sizeof ecPtFmt)); | |
1367 if (rv != SECSuccess) | |
1368 return -1; | |
1369 if (!ss->sec.isServer) { | |
1370 TLSExtensionData *xtnData = &ss->xtnData; | |
1371 xtnData->advertised[xtnData->numAdvertised++] = | |
1372 ssl_ec_point_formats_xtn; | |
1373 } | |
1374 } | |
1375 return (sizeof ecPtFmt); | |
1376 } | |
1377 | |
1378 /* Just make sure that the remote client supports uncompressed points, | |
1379 * Since that is all we support. Disable ECC cipher suites if it doesn't. | |
1380 */ | |
1381 SECStatus | |
1382 ssl3_HandleSupportedPointFormatsXtn(sslSocket *ss, PRUint16 ex_type, | |
1383 SECItem *data) | |
1384 { | |
1385 int i; | |
1386 | |
1387 if (data->len < 2 || data->len > 255 || !data->data || | |
1388 data->len != (unsigned int)data->data[0] + 1) { | |
1389 return ssl3_DecodeError(ss); | |
1390 } | |
1391 for (i = data->len; --i > 0;) { | |
1392 if (data->data[i] == 0) { | |
1393 /* indicate that we should send a reply */ | |
1394 SECStatus rv; | |
1395 rv = ssl3_RegisterServerHelloExtensionSender(ss, ex_type, | |
1396 &ssl3_SendSupportedPoin
tFormatsXtn); | |
1397 return rv; | |
1398 } | |
1399 } | |
1400 | |
1401 /* evil client doesn't support uncompressed */ | |
1402 ssl3_DisableECCSuites(ss, ecSuites); | |
1403 return SECSuccess; | |
1404 } | |
1405 | |
1406 #define SSL3_GET_SERVER_PUBLICKEY(sock, type)
\ | |
1407 (ss->serverCerts[type].serverKeyPair ? ss->serverCerts[type].serverKeyPair->
pubKey \ | |
1408 : NULL) | |
1409 | |
1410 /* Extract the TLS curve name for the public key in our EC server cert. */ | |
1411 ECName | |
1412 ssl3_GetSvrCertCurveName(sslSocket *ss) | |
1413 { | |
1414 SECKEYPublicKey *srvPublicKey; | |
1415 ECName ec_curve = ec_noName; | |
1416 | |
1417 srvPublicKey = SSL3_GET_SERVER_PUBLICKEY(ss, kt_ecdh); | |
1418 if (srvPublicKey) { | |
1419 ec_curve = ssl3_PubKey2ECName(srvPublicKey); | |
1420 } | |
1421 return ec_curve; | |
1422 } | |
1423 | |
1424 /* Ensure that the curve in our server cert is one of the ones supported | |
1425 * by the remote client, and disable all ECC cipher suites if not. | |
1426 */ | |
1427 SECStatus | |
1428 ssl3_HandleSupportedCurvesXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data) | |
1429 { | |
1430 PRInt32 list_len; | |
1431 PRUint32 peerCurves = 0; | |
1432 PRUint32 mutualCurves = 0; | |
1433 PRUint16 svrCertCurveName; | |
1434 | |
1435 if (!data->data || data->len < 4) { | |
1436 (void)ssl3_DecodeError(ss); | |
1437 return SECFailure; | |
1438 } | |
1439 | |
1440 /* get the length of elliptic_curve_list */ | |
1441 list_len = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len); | |
1442 if (list_len < 0 || data->len != list_len || (data->len % 2) != 0) { | |
1443 (void)ssl3_DecodeError(ss); | |
1444 return SECFailure; | |
1445 } | |
1446 /* build bit vector of peer's supported curve names */ | |
1447 while (data->len) { | |
1448 PRInt32 curve_name = | |
1449 ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len); | |
1450 if (curve_name < 0) { | |
1451 return SECFailure; /* fatal alert already sent */ | |
1452 } | |
1453 if (curve_name > ec_noName && curve_name < ec_pastLastName) { | |
1454 peerCurves |= (1U << curve_name); | |
1455 } | |
1456 } | |
1457 /* What curves do we support in common? */ | |
1458 mutualCurves = ss->ssl3.hs.negotiatedECCurves &= peerCurves; | |
1459 if (!mutualCurves) { | |
1460 /* no mutually supported EC Curves, disable ECC */ | |
1461 ssl3_DisableECCSuites(ss, ecSuites); | |
1462 return SECSuccess; | |
1463 } | |
1464 | |
1465 /* if our ECC cert doesn't use one of these supported curves, | |
1466 * disable ECC cipher suites that require an ECC cert. | |
1467 */ | |
1468 svrCertCurveName = ssl3_GetSvrCertCurveName(ss); | |
1469 if (svrCertCurveName != ec_noName && | |
1470 (mutualCurves & (1U << svrCertCurveName)) != 0) { | |
1471 return SECSuccess; | |
1472 } | |
1473 /* Our EC cert doesn't contain a mutually supported curve. | |
1474 * Disable all ECC cipher suites that require an EC cert | |
1475 */ | |
1476 ssl3_DisableECCSuites(ss, ecdh_ecdsa_suites); | |
1477 ssl3_DisableECCSuites(ss, ecdhe_ecdsa_suites); | |
1478 return SECSuccess; | |
1479 } | |
1480 | |
1481 #endif /* NSS_DISABLE_ECC */ | |
OLD | NEW |