Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(64)

Side by Side Diff: net/third_party/nss/ssl/ssl3ecc.c

Issue 394003: Linux: enable building with a local version of libssl. (Closed)
Patch Set: ... Created 11 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/third_party/nss/ssl/ssl3con.c ('k') | net/third_party/nss/ssl/ssl3ext.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * SSL3 Protocol
3 *
4 * ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 *
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
11 *
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
15 * License.
16 *
17 * The Original Code is the Netscape security libraries.
18 *
19 * The Initial Developer of the Original Code is
20 * Netscape Communications Corporation.
21 * Portions created by the Initial Developer are Copyright (C) 1994-2000
22 * the Initial Developer. All Rights Reserved.
23 *
24 * Contributor(s):
25 * Dr Vipul Gupta <vipul.gupta@sun.com> and
26 * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
27 *
28 * Alternatively, the contents of this file may be used under the terms of
29 * either the GNU General Public License Version 2 or later (the "GPL"), or
30 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
31 * in which case the provisions of the GPL or the LGPL are applicable instead
32 * of those above. If you wish to allow use of your version of this file only
33 * under the terms of either the GPL or the LGPL, and not to allow others to
34 * use your version of this file under the terms of the MPL, indicate your
35 * decision by deleting the provisions above and replace them with the notice
36 * and other provisions required by the GPL or the LGPL. If you do not delete
37 * the provisions above, a recipient may use your version of this file under
38 * the terms of any one of the MPL, the GPL or the LGPL.
39 *
40 * ***** END LICENSE BLOCK ***** */
41
42 /* ECC code moved here from ssl3con.c */
43 /* $Id: ssl3ecc.c,v 1.22 2008/03/10 00:01:28 wtc%google.com Exp $ */
44
45 #include "nss.h"
46 #include "cert.h"
47 #include "ssl.h"
48 #include "cryptohi.h" /* for DSAU_ stuff */
49 #include "keyhi.h"
50 #include "secder.h"
51 #include "secitem.h"
52
53 #include "sslimpl.h"
54 #include "sslproto.h"
55 #include "sslerr.h"
56 #include "prtime.h"
57 #include "prinrval.h"
58 #include "prerror.h"
59 #include "pratom.h"
60 #include "prthread.h"
61 #include "prinit.h"
62
63 #include "pk11func.h"
64 #include "secmod.h"
65 #include "ec.h"
66 #include "blapi.h"
67
68 #include <stdio.h>
69
70 #ifdef NSS_ENABLE_ECC
71
72 #ifndef PK11_SETATTRS
73 #define PK11_SETATTRS(x,id,v,l) (x)->type = (id); \
74 (x)->pValue=(v); (x)->ulValueLen = (l);
75 #endif
76
77 #define SSL_GET_SERVER_PUBLIC_KEY(sock, type) \
78 (ss->serverCerts[type].serverKeyPair ? \
79 ss->serverCerts[type].serverKeyPair->pubKey : NULL)
80
81 #define SSL_IS_CURVE_NEGOTIATED(curvemsk, curveName) \
82 ((curveName > ec_noName) && \
83 (curveName < ec_pastLastName) && \
84 ((1UL << curveName) & curvemsk) != 0)
85
86
87
88 static SECStatus ssl3_CreateECDHEphemeralKeys(sslSocket *ss, ECName ec_curve);
89
90 #define supportedCurve(x) (((x) > ec_noName) && ((x) < ec_pastLastName))
91
92 /* Table containing OID tags for elliptic curves named in the
93 * ECC-TLS IETF draft.
94 */
95 static const SECOidTag ecName2OIDTag[] = {
96 0,
97 SEC_OID_SECG_EC_SECT163K1, /* 1 */
98 SEC_OID_SECG_EC_SECT163R1, /* 2 */
99 SEC_OID_SECG_EC_SECT163R2, /* 3 */
100 SEC_OID_SECG_EC_SECT193R1, /* 4 */
101 SEC_OID_SECG_EC_SECT193R2, /* 5 */
102 SEC_OID_SECG_EC_SECT233K1, /* 6 */
103 SEC_OID_SECG_EC_SECT233R1, /* 7 */
104 SEC_OID_SECG_EC_SECT239K1, /* 8 */
105 SEC_OID_SECG_EC_SECT283K1, /* 9 */
106 SEC_OID_SECG_EC_SECT283R1, /* 10 */
107 SEC_OID_SECG_EC_SECT409K1, /* 11 */
108 SEC_OID_SECG_EC_SECT409R1, /* 12 */
109 SEC_OID_SECG_EC_SECT571K1, /* 13 */
110 SEC_OID_SECG_EC_SECT571R1, /* 14 */
111 SEC_OID_SECG_EC_SECP160K1, /* 15 */
112 SEC_OID_SECG_EC_SECP160R1, /* 16 */
113 SEC_OID_SECG_EC_SECP160R2, /* 17 */
114 SEC_OID_SECG_EC_SECP192K1, /* 18 */
115 SEC_OID_SECG_EC_SECP192R1, /* 19 */
116 SEC_OID_SECG_EC_SECP224K1, /* 20 */
117 SEC_OID_SECG_EC_SECP224R1, /* 21 */
118 SEC_OID_SECG_EC_SECP256K1, /* 22 */
119 SEC_OID_SECG_EC_SECP256R1, /* 23 */
120 SEC_OID_SECG_EC_SECP384R1, /* 24 */
121 SEC_OID_SECG_EC_SECP521R1, /* 25 */
122 };
123
124 static const PRUint16 curve2bits[] = {
125 0, /* ec_noName = 0, */
126 163, /* ec_sect163k1 = 1, */
127 163, /* ec_sect163r1 = 2, */
128 163, /* ec_sect163r2 = 3, */
129 193, /* ec_sect193r1 = 4, */
130 193, /* ec_sect193r2 = 5, */
131 233, /* ec_sect233k1 = 6, */
132 233, /* ec_sect233r1 = 7, */
133 239, /* ec_sect239k1 = 8, */
134 283, /* ec_sect283k1 = 9, */
135 283, /* ec_sect283r1 = 10, */
136 409, /* ec_sect409k1 = 11, */
137 409, /* ec_sect409r1 = 12, */
138 571, /* ec_sect571k1 = 13, */
139 571, /* ec_sect571r1 = 14, */
140 160, /* ec_secp160k1 = 15, */
141 160, /* ec_secp160r1 = 16, */
142 160, /* ec_secp160r2 = 17, */
143 192, /* ec_secp192k1 = 18, */
144 192, /* ec_secp192r1 = 19, */
145 224, /* ec_secp224k1 = 20, */
146 224, /* ec_secp224r1 = 21, */
147 256, /* ec_secp256k1 = 22, */
148 256, /* ec_secp256r1 = 23, */
149 384, /* ec_secp384r1 = 24, */
150 521, /* ec_secp521r1 = 25, */
151 65535 /* ec_pastLastName */
152 };
153
154 typedef struct Bits2CurveStr {
155 PRUint16 bits;
156 ECName curve;
157 } Bits2Curve;
158
159 static const Bits2Curve bits2curve [] = {
160 { 192, ec_secp192r1 /* = 19, fast */ },
161 { 160, ec_secp160r2 /* = 17, fast */ },
162 { 160, ec_secp160k1 /* = 15, */ },
163 { 160, ec_secp160r1 /* = 16, */ },
164 { 163, ec_sect163k1 /* = 1, */ },
165 { 163, ec_sect163r1 /* = 2, */ },
166 { 163, ec_sect163r2 /* = 3, */ },
167 { 192, ec_secp192k1 /* = 18, */ },
168 { 193, ec_sect193r1 /* = 4, */ },
169 { 193, ec_sect193r2 /* = 5, */ },
170 { 224, ec_secp224r1 /* = 21, fast */ },
171 { 224, ec_secp224k1 /* = 20, */ },
172 { 233, ec_sect233k1 /* = 6, */ },
173 { 233, ec_sect233r1 /* = 7, */ },
174 { 239, ec_sect239k1 /* = 8, */ },
175 { 256, ec_secp256r1 /* = 23, fast */ },
176 { 256, ec_secp256k1 /* = 22, */ },
177 { 283, ec_sect283k1 /* = 9, */ },
178 { 283, ec_sect283r1 /* = 10, */ },
179 { 384, ec_secp384r1 /* = 24, fast */ },
180 { 409, ec_sect409k1 /* = 11, */ },
181 { 409, ec_sect409r1 /* = 12, */ },
182 { 521, ec_secp521r1 /* = 25, fast */ },
183 { 571, ec_sect571k1 /* = 13, */ },
184 { 571, ec_sect571r1 /* = 14, */ },
185 { 65535, ec_noName }
186 };
187
188 typedef struct ECDHEKeyPairStr {
189 ssl3KeyPair * pair;
190 int error; /* error code of the call-once function */
191 PRCallOnceType once;
192 } ECDHEKeyPair;
193
194 /* arrays of ECDHE KeyPairs */
195 static ECDHEKeyPair gECDHEKeyPairs[ec_pastLastName];
196
197 SECStatus
198 ssl3_ECName2Params(PRArenaPool * arena, ECName curve, SECKEYECParams * params)
199 {
200 SECOidData *oidData = NULL;
201
202 if ((curve <= ec_noName) || (curve >= ec_pastLastName) ||
203 ((oidData = SECOID_FindOIDByTag(ecName2OIDTag[curve])) == NULL)) {
204 PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
205 return SECFailure;
206 }
207
208 SECITEM_AllocItem(arena, params, (2 + oidData->oid.len));
209 /*
210 * params->data needs to contain the ASN encoding of an object ID (OID)
211 * representing the named curve. The actual OID is in
212 * oidData->oid.data so we simply prepend 0x06 and OID length
213 */
214 params->data[0] = SEC_ASN1_OBJECT_ID;
215 params->data[1] = oidData->oid.len;
216 memcpy(params->data + 2, oidData->oid.data, oidData->oid.len);
217
218 return SECSuccess;
219 }
220
221 static ECName
222 params2ecName(SECKEYECParams * params)
223 {
224 SECItem oid = { siBuffer, NULL, 0};
225 SECOidData *oidData = NULL;
226 ECName i;
227
228 /*
229 * params->data needs to contain the ASN encoding of an object ID (OID)
230 * representing a named curve. Here, we strip away everything
231 * before the actual OID and use the OID to look up a named curve.
232 */
233 if (params->data[0] != SEC_ASN1_OBJECT_ID) return ec_noName;
234 oid.len = params->len - 2;
235 oid.data = params->data + 2;
236 if ((oidData = SECOID_FindOID(&oid)) == NULL) return ec_noName;
237 for (i = ec_noName + 1; i < ec_pastLastName; i++) {
238 if (ecName2OIDTag[i] == oidData->offset)
239 return i;
240 }
241
242 return ec_noName;
243 }
244
245 /* Caller must set hiLevel error code. */
246 static SECStatus
247 ssl3_ComputeECDHKeyHash(SECItem ec_params, SECItem server_ecpoint,
248 SSL3Random *client_rand, SSL3Random *server_rand,
249 SSL3Hashes *hashes, PRBool bypassPKCS11)
250 {
251 PRUint8 * hashBuf;
252 PRUint8 * pBuf;
253 SECStatus rv = SECSuccess;
254 unsigned int bufLen;
255 /*
256 * XXX For now, we only support named curves (the appropriate
257 * checks are made before this method is called) so ec_params
258 * takes up only two bytes. ECPoint needs to fit in 256 bytes
259 * (because the spec says the length must fit in one byte)
260 */
261 PRUint8 buf[2*SSL3_RANDOM_LENGTH + 2 + 1 + 256];
262
263 bufLen = 2*SSL3_RANDOM_LENGTH + ec_params.len + 1 + server_ecpoint.len;
264 if (bufLen <= sizeof buf) {
265 hashBuf = buf;
266 } else {
267 hashBuf = PORT_Alloc(bufLen);
268 if (!hashBuf) {
269 return SECFailure;
270 }
271 }
272
273 memcpy(hashBuf, client_rand, SSL3_RANDOM_LENGTH);
274 pBuf = hashBuf + SSL3_RANDOM_LENGTH;
275 memcpy(pBuf, server_rand, SSL3_RANDOM_LENGTH);
276 pBuf += SSL3_RANDOM_LENGTH;
277 memcpy(pBuf, ec_params.data, ec_params.len);
278 pBuf += ec_params.len;
279 pBuf[0] = (PRUint8)(server_ecpoint.len);
280 pBuf += 1;
281 memcpy(pBuf, server_ecpoint.data, server_ecpoint.len);
282 pBuf += server_ecpoint.len;
283 PORT_Assert((unsigned int)(pBuf - hashBuf) == bufLen);
284
285 rv = ssl3_ComputeCommonKeyHash(hashBuf, bufLen, hashes, bypassPKCS11);
286
287 PRINT_BUF(95, (NULL, "ECDHkey hash: ", hashBuf, bufLen));
288 PRINT_BUF(95, (NULL, "ECDHkey hash: MD5 result", hashes->md5, MD5_LENGTH));
289 PRINT_BUF(95, (NULL, "ECDHkey hash: SHA1 result", hashes->sha, SHA1_LENGTH)) ;
290
291 if (hashBuf != buf && hashBuf != NULL)
292 PORT_Free(hashBuf);
293 return rv;
294 }
295
296
297 /* Called from ssl3_SendClientKeyExchange(). */
298 SECStatus
299 ssl3_SendECDHClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey)
300 {
301 PK11SymKey * pms = NULL;
302 SECStatus rv = SECFailure;
303 PRBool isTLS;
304 CK_MECHANISM_TYPE target;
305 SECKEYPublicKey *pubKey = NULL; /* Ephemeral ECDH key */
306 SECKEYPrivateKey *privKey = NULL; /* Ephemeral ECDH key */
307
308 PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
309 PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
310
311 isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
312
313 /* Generate ephemeral EC keypair */
314 if (svrPubKey->keyType != ecKey) {
315 PORT_SetError(SEC_ERROR_BAD_KEY);
316 goto loser;
317 }
318 /* XXX SHOULD CALL ssl3_CreateECDHEphemeralKeys here, instead! */
319 privKey = SECKEY_CreateECPrivateKey(&svrPubKey->u.ec.DEREncodedParams,
320 &pubKey, NULL);
321 if (!privKey || !pubKey) {
322 ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
323 rv = SECFailure;
324 goto loser;
325 }
326 PRINT_BUF(50, (ss, "ECDH public value:",
327 pubKey->u.ec.publicValue.data,
328 pubKey->u.ec.publicValue.len));
329
330 if (isTLS) target = CKM_TLS_MASTER_KEY_DERIVE_DH;
331 else target = CKM_SSL3_MASTER_KEY_DERIVE_DH;
332
333 /* Determine the PMS */
334 pms = PK11_PubDeriveWithKDF(privKey, svrPubKey, PR_FALSE, NULL, NULL,
335 CKM_ECDH1_DERIVE, target, CKA_DERIVE, 0,
336 CKD_NULL, NULL, NULL);
337
338 if (pms == NULL) {
339 SSL3AlertDescription desc = illegal_parameter;
340 (void)SSL3_SendAlert(ss, alert_fatal, desc);
341 ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
342 goto loser;
343 }
344
345 SECKEY_DestroyPrivateKey(privKey);
346 privKey = NULL;
347
348 rv = ssl3_InitPendingCipherSpec(ss, pms);
349 PK11_FreeSymKey(pms); pms = NULL;
350
351 if (rv != SECSuccess) {
352 ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
353 goto loser;
354 }
355
356 rv = ssl3_AppendHandshakeHeader(ss, client_key_exchange,
357 pubKey->u.ec.publicValue.len + 1);
358 if (rv != SECSuccess) {
359 goto loser; /* err set by ssl3_AppendHandshake* */
360 }
361
362 rv = ssl3_AppendHandshakeVariable(ss,
363 pubKey->u.ec.publicValue.data,
364 pubKey->u.ec.publicValue.len, 1);
365 SECKEY_DestroyPublicKey(pubKey);
366 pubKey = NULL;
367
368 if (rv != SECSuccess) {
369 goto loser; /* err set by ssl3_AppendHandshake* */
370 }
371
372 rv = SECSuccess;
373
374 loser:
375 if(pms) PK11_FreeSymKey(pms);
376 if(privKey) SECKEY_DestroyPrivateKey(privKey);
377 if(pubKey) SECKEY_DestroyPublicKey(pubKey);
378 return rv;
379 }
380
381
382 /*
383 ** Called from ssl3_HandleClientKeyExchange()
384 */
385 SECStatus
386 ssl3_HandleECDHClientKeyExchange(sslSocket *ss, SSL3Opaque *b,
387 PRUint32 length,
388 SECKEYPublicKey *srvrPubKey,
389 SECKEYPrivateKey *srvrPrivKey)
390 {
391 PK11SymKey * pms;
392 SECStatus rv;
393 SECKEYPublicKey clntPubKey;
394 CK_MECHANISM_TYPE target;
395 PRBool isTLS;
396
397 PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
398 PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
399
400 clntPubKey.keyType = ecKey;
401 clntPubKey.u.ec.DEREncodedParams.len =
402 srvrPubKey->u.ec.DEREncodedParams.len;
403 clntPubKey.u.ec.DEREncodedParams.data =
404 srvrPubKey->u.ec.DEREncodedParams.data;
405
406 rv = ssl3_ConsumeHandshakeVariable(ss, &clntPubKey.u.ec.publicValue,
407 1, &b, &length);
408 if (rv != SECSuccess) {
409 SEND_ALERT
410 return SECFailure; /* XXX Who sets the error code?? */
411 }
412
413 isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);
414
415 if (isTLS) target = CKM_TLS_MASTER_KEY_DERIVE_DH;
416 else target = CKM_SSL3_MASTER_KEY_DERIVE_DH;
417
418 /* Determine the PMS */
419 pms = PK11_PubDeriveWithKDF(srvrPrivKey, &clntPubKey, PR_FALSE, NULL, NULL,
420 CKM_ECDH1_DERIVE, target, CKA_DERIVE, 0,
421 CKD_NULL, NULL, NULL);
422
423 if (pms == NULL) {
424 /* last gasp. */
425 ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
426 return SECFailure;
427 }
428
429 rv = ssl3_InitPendingCipherSpec(ss, pms);
430 PK11_FreeSymKey(pms);
431 if (rv != SECSuccess) {
432 SEND_ALERT
433 return SECFailure; /* error code set by ssl3_InitPendingCipherSpec */
434 }
435 return SECSuccess;
436 }
437
438 ECName
439 ssl3_GetCurveWithECKeyStrength(PRUint32 curvemsk, int requiredECCbits)
440 {
441 int i;
442
443 for ( i = 0; bits2curve[i].curve != ec_noName; i++) {
444 if (bits2curve[i].bits < requiredECCbits)
445 continue;
446 if (SSL_IS_CURVE_NEGOTIATED(curvemsk, bits2curve[i].curve)) {
447 return bits2curve[i].curve;
448 }
449 }
450 PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
451 return ec_noName;
452 }
453
454 /* find the "weakest link". Get strength of signature key and of sym key.
455 * choose curve for the weakest of those two.
456 */
457 ECName
458 ssl3_GetCurveNameForServerSocket(sslSocket *ss)
459 {
460 SECKEYPublicKey * svrPublicKey = NULL;
461 ECName ec_curve = ec_noName;
462 int signatureKeyStrength = 521;
463 int requiredECCbits = ss->sec.secretKeyBits * 2;
464
465 if (ss->ssl3.hs.kea_def->kea == kea_ecdhe_ecdsa) {
466 svrPublicKey = SSL_GET_SERVER_PUBLIC_KEY(ss, kt_ecdh);
467 if (svrPublicKey)
468 ec_curve = params2ecName(&svrPublicKey->u.ec.DEREncodedParams);
469 if (!SSL_IS_CURVE_NEGOTIATED(ss->ssl3.hs.negotiatedECCurves, ec_curve)) {
470 PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
471 return ec_noName;
472 }
473 signatureKeyStrength = curve2bits[ ec_curve ];
474 } else {
475 /* RSA is our signing cert */
476 int serverKeyStrengthInBits;
477
478 svrPublicKey = SSL_GET_SERVER_PUBLIC_KEY(ss, kt_rsa);
479 if (!svrPublicKey) {
480 PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
481 return ec_noName;
482 }
483
484 /* currently strength in bytes */
485 serverKeyStrengthInBits = svrPublicKey->u.rsa.modulus.len;
486 if (svrPublicKey->u.rsa.modulus.data[0] == 0) {
487 serverKeyStrengthInBits--;
488 }
489 /* convert to strength in bits */
490 serverKeyStrengthInBits *= BPB;
491
492 signatureKeyStrength =
493 SSL_RSASTRENGTH_TO_ECSTRENGTH(serverKeyStrengthInBits);
494 }
495 if ( requiredECCbits > signatureKeyStrength )
496 requiredECCbits = signatureKeyStrength;
497
498 return ssl3_GetCurveWithECKeyStrength(ss->ssl3.hs.negotiatedECCurves,
499 requiredECCbits);
500 }
501
502 /* function to clear out the lists */
503 static SECStatus
504 ssl3_ShutdownECDHECurves(void *appData, void *nssData)
505 {
506 int i;
507 ECDHEKeyPair *keyPair = &gECDHEKeyPairs[0];
508
509 for (i=0; i < ec_pastLastName; i++, keyPair++) {
510 if (keyPair->pair) {
511 ssl3_FreeKeyPair(keyPair->pair);
512 }
513 }
514 memset(gECDHEKeyPairs, 0, sizeof gECDHEKeyPairs);
515 return SECSuccess;
516 }
517
518 static PRStatus
519 ssl3_ECRegister(void)
520 {
521 SECStatus rv;
522 rv = NSS_RegisterShutdown(ssl3_ShutdownECDHECurves, gECDHEKeyPairs);
523 if (rv != SECSuccess) {
524 gECDHEKeyPairs[ec_noName].error = PORT_GetError();
525 }
526 return (PRStatus)rv;
527 }
528
529 /* CallOnce function, called once for each named curve. */
530 static PRStatus
531 ssl3_CreateECDHEphemeralKeyPair(void * arg)
532 {
533 SECKEYPrivateKey * privKey = NULL;
534 SECKEYPublicKey * pubKey = NULL;
535 ssl3KeyPair * keyPair = NULL;
536 ECName ec_curve = (ECName)arg;
537 SECKEYECParams ecParams = { siBuffer, NULL, 0 };
538
539 PORT_Assert(gECDHEKeyPairs[ec_curve].pair == NULL);
540
541 /* ok, no one has generated a global key for this curve yet, do so */
542 if (ssl3_ECName2Params(NULL, ec_curve, &ecParams) != SECSuccess) {
543 gECDHEKeyPairs[ec_curve].error = PORT_GetError();
544 return PR_FAILURE;
545 }
546
547 privKey = SECKEY_CreateECPrivateKey(&ecParams, &pubKey, NULL);
548 SECITEM_FreeItem(&ecParams, PR_FALSE);
549
550 if (!privKey || !pubKey || !(keyPair = ssl3_NewKeyPair(privKey, pubKey))) {
551 if (privKey) {
552 SECKEY_DestroyPrivateKey(privKey);
553 }
554 if (pubKey) {
555 SECKEY_DestroyPublicKey(pubKey);
556 }
557 ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
558 gECDHEKeyPairs[ec_curve].error = PORT_GetError();
559 return PR_FAILURE;
560 }
561
562 gECDHEKeyPairs[ec_curve].pair = keyPair;
563 return PR_SUCCESS;
564 }
565
566 /*
567 * Creates the ephemeral public and private ECDH keys used by
568 * server in ECDHE_RSA and ECDHE_ECDSA handshakes.
569 * For now, the elliptic curve is chosen to be the same
570 * strength as the signing certificate (ECC or RSA).
571 * We need an API to specify the curve. This won't be a real
572 * issue until we further develop server-side support for ECC
573 * cipher suites.
574 */
575 static SECStatus
576 ssl3_CreateECDHEphemeralKeys(sslSocket *ss, ECName ec_curve)
577 {
578 ssl3KeyPair * keyPair = NULL;
579
580 /* if there's no global key for this curve, make one. */
581 if (gECDHEKeyPairs[ec_curve].pair == NULL) {
582 PRStatus status;
583
584 status = PR_CallOnce(&gECDHEKeyPairs[ec_noName].once, ssl3_ECRegister);
585 if (status != PR_SUCCESS) {
586 PORT_SetError(gECDHEKeyPairs[ec_noName].error);
587 return SECFailure;
588 }
589 status = PR_CallOnceWithArg(&gECDHEKeyPairs[ec_curve].once,
590 ssl3_CreateECDHEphemeralKeyPair,
591 (void *)ec_curve);
592 if (status != PR_SUCCESS) {
593 PORT_SetError(gECDHEKeyPairs[ec_curve].error);
594 return SECFailure;
595 }
596 }
597
598 keyPair = gECDHEKeyPairs[ec_curve].pair;
599 PORT_Assert(keyPair != NULL);
600 if (!keyPair)
601 return SECFailure;
602 ss->ephemeralECDHKeyPair = ssl3_GetKeyPairRef(keyPair);
603
604 return SECSuccess;
605 }
606
607 SECStatus
608 ssl3_HandleECDHServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
609 {
610 PRArenaPool * arena = NULL;
611 SECKEYPublicKey *peerKey = NULL;
612 PRBool isTLS;
613 SECStatus rv;
614 int errCode = SSL_ERROR_RX_MALFORMED_SERVER_KEY_EXCH;
615 SSL3AlertDescription desc = illegal_parameter;
616 SSL3Hashes hashes;
617 SECItem signature = {siBuffer, NULL, 0};
618
619 SECItem ec_params = {siBuffer, NULL, 0};
620 SECItem ec_point = {siBuffer, NULL, 0};
621 unsigned char paramBuf[3]; /* only for curve_type == named_curve */
622
623 isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);
624
625 /* XXX This works only for named curves, revisit this when
626 * we support generic curves.
627 */
628 ec_params.len = sizeof paramBuf;
629 ec_params.data = paramBuf;
630 rv = ssl3_ConsumeHandshake(ss, ec_params.data, ec_params.len, &b, &length);
631 if (rv != SECSuccess) {
632 goto loser; /* malformed. */
633 }
634
635 /* Fail if the curve is not a named curve */
636 if ((ec_params.data[0] != ec_type_named) ||
637 (ec_params.data[1] != 0) ||
638 !supportedCurve(ec_params.data[2])) {
639 errCode = SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE;
640 desc = handshake_failure;
641 goto alert_loser;
642 }
643
644 rv = ssl3_ConsumeHandshakeVariable(ss, &ec_point, 1, &b, &length);
645 if (rv != SECSuccess) {
646 goto loser; /* malformed. */
647 }
648 /* Fail if the ec point uses compressed representation */
649 if (ec_point.data[0] != EC_POINT_FORM_UNCOMPRESSED) {
650 errCode = SEC_ERROR_UNSUPPORTED_EC_POINT_FORM;
651 desc = handshake_failure;
652 goto alert_loser;
653 }
654
655 rv = ssl3_ConsumeHandshakeVariable(ss, &signature, 2, &b, &length);
656 if (rv != SECSuccess) {
657 goto loser; /* malformed. */
658 }
659
660 if (length != 0) {
661 if (isTLS)
662 desc = decode_error;
663 goto alert_loser; /* malformed. */
664 }
665
666 PRINT_BUF(60, (NULL, "Server EC params", ec_params.data,
667 ec_params.len));
668 PRINT_BUF(60, (NULL, "Server EC point", ec_point.data, ec_point.len));
669
670 /* failures after this point are not malformed handshakes. */
671 /* TLS: send decrypt_error if signature failed. */
672 desc = isTLS ? decrypt_error : handshake_failure;
673
674 /*
675 * check to make sure the hash is signed by right guy
676 */
677 rv = ssl3_ComputeECDHKeyHash(ec_params, ec_point,
678 &ss->ssl3.hs.client_random,
679 &ss->ssl3.hs.server_random,
680 &hashes, ss->opt.bypassPKCS11);
681
682 if (rv != SECSuccess) {
683 errCode =
684 ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
685 goto alert_loser;
686 }
687 rv = ssl3_VerifySignedHashes(&hashes, ss->sec.peerCert, &signature,
688 isTLS, ss->pkcs11PinArg);
689 if (rv != SECSuccess) {
690 errCode =
691 ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
692 goto alert_loser;
693 }
694
695 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
696 if (arena == NULL) {
697 goto no_memory;
698 }
699
700 ss->sec.peerKey = peerKey = PORT_ArenaZNew(arena, SECKEYPublicKey);
701 if (peerKey == NULL) {
702 goto no_memory;
703 }
704
705 peerKey->arena = arena;
706 peerKey->keyType = ecKey;
707
708 /* set up EC parameters in peerKey */
709 if (ssl3_ECName2Params(arena, ec_params.data[2],
710 &peerKey->u.ec.DEREncodedParams) != SECSuccess) {
711 /* we should never get here since we already
712 * checked that we are dealing with a supported curve
713 */
714 errCode = SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE;
715 goto alert_loser;
716 }
717
718 /* copy publicValue in peerKey */
719 if (SECITEM_CopyItem(arena, &peerKey->u.ec.publicValue, &ec_point))
720 {
721 PORT_FreeArena(arena, PR_FALSE);
722 goto no_memory;
723 }
724 peerKey->pkcs11Slot = NULL;
725 peerKey->pkcs11ID = CK_INVALID_HANDLE;
726
727 ss->sec.peerKey = peerKey;
728 ss->ssl3.hs.ws = wait_cert_request;
729
730 return SECSuccess;
731
732 alert_loser:
733 (void)SSL3_SendAlert(ss, alert_fatal, desc);
734 loser:
735 PORT_SetError( errCode );
736 return SECFailure;
737
738 no_memory: /* no-memory error has already been set. */
739 ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
740 return SECFailure;
741 }
742
743 SECStatus
744 ssl3_SendECDHServerKeyExchange(sslSocket *ss)
745 {
746 const ssl3KEADef * kea_def = ss->ssl3.hs.kea_def;
747 SECStatus rv = SECFailure;
748 int length;
749 PRBool isTLS;
750 SECItem signed_hash = {siBuffer, NULL, 0};
751 SSL3Hashes hashes;
752
753 SECKEYPublicKey * ecdhePub;
754 SECItem ec_params = {siBuffer, NULL, 0};
755 unsigned char paramBuf[3];
756 ECName curve;
757 SSL3KEAType certIndex;
758
759
760 /* Generate ephemeral ECDH key pair and send the public key */
761 curve = ssl3_GetCurveNameForServerSocket(ss);
762 if (curve == ec_noName) {
763 goto loser;
764 }
765 rv = ssl3_CreateECDHEphemeralKeys(ss, curve);
766 if (rv != SECSuccess) {
767 goto loser; /* err set by AppendHandshake. */
768 }
769 ecdhePub = ss->ephemeralECDHKeyPair->pubKey;
770 PORT_Assert(ecdhePub != NULL);
771 if (!ecdhePub) {
772 PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
773 return SECFailure;
774 }
775
776 ec_params.len = sizeof paramBuf;
777 ec_params.data = paramBuf;
778 curve = params2ecName(&ecdhePub->u.ec.DEREncodedParams);
779 if (curve != ec_noName) {
780 ec_params.data[0] = ec_type_named;
781 ec_params.data[1] = 0x00;
782 ec_params.data[2] = curve;
783 } else {
784 PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
785 goto loser;
786 }
787
788 rv = ssl3_ComputeECDHKeyHash(ec_params, ecdhePub->u.ec.publicValue,
789 &ss->ssl3.hs.client_random,
790 &ss->ssl3.hs.server_random,
791 &hashes, ss->opt.bypassPKCS11);
792 if (rv != SECSuccess) {
793 ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
794 goto loser;
795 }
796
797 isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
798
799 /* XXX SSLKEAType isn't really a good choice for
800 * indexing certificates but that's all we have
801 * for now.
802 */
803 if (kea_def->kea == kea_ecdhe_rsa)
804 certIndex = kt_rsa;
805 else /* kea_def->kea == kea_ecdhe_ecdsa */
806 certIndex = kt_ecdh;
807
808 rv = ssl3_SignHashes(&hashes, ss->serverCerts[certIndex].SERVERKEY,
809 &signed_hash, isTLS);
810 if (rv != SECSuccess) {
811 goto loser; /* ssl3_SignHashes has set err. */
812 }
813 if (signed_hash.data == NULL) {
814 /* how can this happen and rv == SECSuccess ?? */
815 PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
816 goto loser;
817 }
818
819 length = ec_params.len +
820 1 + ecdhePub->u.ec.publicValue.len +
821 2 + signed_hash.len;
822
823 rv = ssl3_AppendHandshakeHeader(ss, server_key_exchange, length);
824 if (rv != SECSuccess) {
825 goto loser; /* err set by AppendHandshake. */
826 }
827
828 rv = ssl3_AppendHandshake(ss, ec_params.data, ec_params.len);
829 if (rv != SECSuccess) {
830 goto loser; /* err set by AppendHandshake. */
831 }
832
833 rv = ssl3_AppendHandshakeVariable(ss, ecdhePub->u.ec.publicValue.data,
834 ecdhePub->u.ec.publicValue.len, 1);
835 if (rv != SECSuccess) {
836 goto loser; /* err set by AppendHandshake. */
837 }
838
839 rv = ssl3_AppendHandshakeVariable(ss, signed_hash.data,
840 signed_hash.len, 2);
841 if (rv != SECSuccess) {
842 goto loser; /* err set by AppendHandshake. */
843 }
844
845 PORT_Free(signed_hash.data);
846 return SECSuccess;
847
848 loser:
849 if (signed_hash.data != NULL)
850 PORT_Free(signed_hash.data);
851 return SECFailure;
852 }
853
854 /* Lists of ECC cipher suites for searching and disabling. */
855
856 static const ssl3CipherSuite ecdh_suites[] = {
857 TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
858 TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
859 TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
860 TLS_ECDH_ECDSA_WITH_NULL_SHA,
861 TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
862 TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
863 TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
864 TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
865 TLS_ECDH_RSA_WITH_NULL_SHA,
866 TLS_ECDH_RSA_WITH_RC4_128_SHA,
867 0 /* end of list marker */
868 };
869
870 static const ssl3CipherSuite ecdh_ecdsa_suites[] = {
871 TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
872 TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
873 TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
874 TLS_ECDH_ECDSA_WITH_NULL_SHA,
875 TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
876 0 /* end of list marker */
877 };
878
879 static const ssl3CipherSuite ecdh_rsa_suites[] = {
880 TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
881 TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
882 TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
883 TLS_ECDH_RSA_WITH_NULL_SHA,
884 TLS_ECDH_RSA_WITH_RC4_128_SHA,
885 0 /* end of list marker */
886 };
887
888 static const ssl3CipherSuite ecdhe_ecdsa_suites[] = {
889 TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
890 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
891 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
892 TLS_ECDHE_ECDSA_WITH_NULL_SHA,
893 TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
894 0 /* end of list marker */
895 };
896
897 static const ssl3CipherSuite ecdhe_rsa_suites[] = {
898 TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
899 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
900 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
901 TLS_ECDHE_RSA_WITH_NULL_SHA,
902 TLS_ECDHE_RSA_WITH_RC4_128_SHA,
903 0 /* end of list marker */
904 };
905
906 /* List of all ECC cipher suites */
907 static const ssl3CipherSuite ecSuites[] = {
908 TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
909 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
910 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
911 TLS_ECDHE_ECDSA_WITH_NULL_SHA,
912 TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
913 TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
914 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
915 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
916 TLS_ECDHE_RSA_WITH_NULL_SHA,
917 TLS_ECDHE_RSA_WITH_RC4_128_SHA,
918 TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
919 TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
920 TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
921 TLS_ECDH_ECDSA_WITH_NULL_SHA,
922 TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
923 TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
924 TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
925 TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
926 TLS_ECDH_RSA_WITH_NULL_SHA,
927 TLS_ECDH_RSA_WITH_RC4_128_SHA,
928 0 /* end of list marker */
929 };
930
931 /* On this socket, Disable the ECC cipher suites in the argument's list */
932 SECStatus
933 ssl3_DisableECCSuites(sslSocket * ss, const ssl3CipherSuite * suite)
934 {
935 if (!suite)
936 suite = ecSuites;
937 for (; *suite; ++suite) {
938 SECStatus rv = ssl3_CipherPrefSet(ss, *suite, PR_FALSE);
939
940 PORT_Assert(rv == SECSuccess); /* else is coding error */
941 }
942 return SECSuccess;
943 }
944
945 /* Look at the server certs configured on this socket, and disable any
946 * ECC cipher suites that are not supported by those certs.
947 */
948 void
949 ssl3_FilterECCipherSuitesByServerCerts(sslSocket * ss)
950 {
951 CERTCertificate * svrCert;
952
953 svrCert = ss->serverCerts[kt_rsa].serverCert;
954 if (!svrCert) {
955 ssl3_DisableECCSuites(ss, ecdhe_rsa_suites);
956 }
957
958 svrCert = ss->serverCerts[kt_ecdh].serverCert;
959 if (!svrCert) {
960 ssl3_DisableECCSuites(ss, ecdh_suites);
961 ssl3_DisableECCSuites(ss, ecdhe_ecdsa_suites);
962 } else {
963 SECOidTag sigTag = SECOID_GetAlgorithmTag(&svrCert->signature);
964
965 switch (sigTag) {
966 case SEC_OID_PKCS1_RSA_ENCRYPTION:
967 case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
968 case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION:
969 case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
970 case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
971 case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
972 case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
973 case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
974 ssl3_DisableECCSuites(ss, ecdh_ecdsa_suites);
975 break;
976 case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
977 case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE:
978 case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE:
979 case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE:
980 case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE:
981 case SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST:
982 case SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST:
983 ssl3_DisableECCSuites(ss, ecdh_rsa_suites);
984 break;
985 default:
986 ssl3_DisableECCSuites(ss, ecdh_suites);
987 break;
988 }
989 }
990 }
991
992 /* Ask: is ANY ECC cipher suite enabled on this socket? */
993 /* Order(N^2). Yuk. Also, this ignores export policy. */
994 PRBool
995 ssl3_IsECCEnabled(sslSocket * ss)
996 {
997 const ssl3CipherSuite * suite;
998
999 for (suite = ecSuites; *suite; ++suite) {
1000 PRBool enabled = PR_FALSE;
1001 SECStatus rv = ssl3_CipherPrefGet(ss, *suite, &enabled);
1002
1003 PORT_Assert(rv == SECSuccess); /* else is coding error */
1004 if (rv == SECSuccess && enabled)
1005 return PR_TRUE;
1006 }
1007 return PR_FALSE;
1008 }
1009
1010 #define BE(n) 0, n
1011
1012 #ifndef NSS_ECC_MORE_THAN_SUITE_B
1013 /* Prefabricated TLS client hello extension, Elliptic Curves List,
1014 * offers only 3 curves, the Suite B curves, 23-25
1015 */
1016 static const PRUint8 EClist[12] = {
1017 BE(10), /* Extension type */
1018 BE( 8), /* octets that follow ( 3 pairs + 1 length pair) */
1019 BE( 6), /* octets that follow ( 3 pairs) */
1020 BE(23), BE(24), BE(25)
1021 };
1022 #else
1023 /* Prefabricated TLS client hello extension, Elliptic Curves List,
1024 * offers curves 1-25.
1025 */
1026 static const PRUint8 EClist[56] = {
1027 BE(10), /* Extension type */
1028 BE(52), /* octets that follow (25 pairs + 1 length pair) */
1029 BE(50), /* octets that follow (25 pairs) */
1030 BE( 1), BE( 2), BE( 3), BE( 4), BE( 5), BE( 6), BE( 7),
1031 BE( 8), BE( 9), BE(10), BE(11), BE(12), BE(13), BE(14), BE(15),
1032 BE(16), BE(17), BE(18), BE(19), BE(20), BE(21), BE(22), BE(23),
1033 BE(24), BE(25)
1034 };
1035 #endif
1036
1037 static const PRUint8 ECPtFmt[6] = {
1038 BE(11), /* Extension type */
1039 BE( 2), /* octets that follow */
1040 1, /* octets that follow */
1041 0 /* uncompressed type only */
1042 };
1043
1044 /* Send our "canned" (precompiled) Supported Elliptic Curves extension,
1045 * which says that we support all TLS-defined named curves.
1046 */
1047 PRInt32
1048 ssl3_SendSupportedCurvesXtn(
1049 sslSocket * ss,
1050 PRBool append,
1051 PRUint32 maxBytes)
1052 {
1053 if (!ss || !ssl3_IsECCEnabled(ss))
1054 return 0;
1055 if (append && maxBytes >= (sizeof EClist)) {
1056 SECStatus rv = ssl3_AppendHandshake(ss, EClist, (sizeof EClist));
1057 if (rv != SECSuccess)
1058 return -1;
1059 if (!ss->sec.isServer) {
1060 TLSExtensionData *xtnData = &ss->xtnData;
1061 xtnData->advertised[xtnData->numAdvertised++] =
1062 elliptic_curves_xtn;
1063 }
1064 }
1065 return (sizeof EClist);
1066 }
1067
1068 /* Send our "canned" (precompiled) Supported Point Formats extension,
1069 * which says that we only support uncompressed points.
1070 */
1071 PRInt32
1072 ssl3_SendSupportedPointFormatsXtn(
1073 sslSocket * ss,
1074 PRBool append,
1075 PRUint32 maxBytes)
1076 {
1077 if (!ss || !ssl3_IsECCEnabled(ss))
1078 return 0;
1079 if (append && maxBytes >= (sizeof ECPtFmt)) {
1080 SECStatus rv = ssl3_AppendHandshake(ss, ECPtFmt, (sizeof ECPtFmt));
1081 if (rv != SECSuccess)
1082 return -1;
1083 if (!ss->sec.isServer) {
1084 TLSExtensionData *xtnData = &ss->xtnData;
1085 xtnData->advertised[xtnData->numAdvertised++] =
1086 ec_point_formats_xtn;
1087 }
1088 }
1089 return (sizeof ECPtFmt);
1090 }
1091
1092 /* Just make sure that the remote client supports uncompressed points,
1093 * Since that is all we support. Disable ECC cipher suites if it doesn't.
1094 */
1095 SECStatus
1096 ssl3_HandleSupportedPointFormatsXtn(sslSocket *ss, PRUint16 ex_type,
1097 SECItem *data)
1098 {
1099 int i;
1100
1101 if (data->len < 2 || data->len > 255 || !data->data ||
1102 data->len != (unsigned int)data->data[0] + 1) {
1103 /* malformed */
1104 goto loser;
1105 }
1106 for (i = data->len; --i > 0; ) {
1107 if (data->data[i] == 0) {
1108 /* indicate that we should send a reply */
1109 SECStatus rv;
1110 rv = ssl3_RegisterServerHelloExtensionSender(ss, ex_type,
1111 &ssl3_SendSupportedPointFormatsXtn);
1112 return rv;
1113 }
1114 }
1115 loser:
1116 /* evil client doesn't support uncompressed */
1117 ssl3_DisableECCSuites(ss, ecSuites);
1118 return SECFailure;
1119 }
1120
1121
1122 #define SSL3_GET_SERVER_PUBLICKEY(sock, type) \
1123 (ss->serverCerts[type].serverKeyPair ? \
1124 ss->serverCerts[type].serverKeyPair->pubKey : NULL)
1125
1126 /* Extract the TLS curve name for the public key in our EC server cert. */
1127 ECName ssl3_GetSvrCertCurveName(sslSocket *ss)
1128 {
1129 SECKEYPublicKey *srvPublicKey;
1130 ECName ec_curve = ec_noName;
1131
1132 srvPublicKey = SSL3_GET_SERVER_PUBLICKEY(ss, kt_ecdh);
1133 if (srvPublicKey) {
1134 ec_curve = params2ecName(&srvPublicKey->u.ec.DEREncodedParams);
1135 }
1136 return ec_curve;
1137 }
1138
1139 /* Ensure that the curve in our server cert is one of the ones suppored
1140 * by the remote client, and disable all ECC cipher suites if not.
1141 */
1142 SECStatus
1143 ssl3_HandleSupportedCurvesXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
1144 {
1145 PRInt32 list_len;
1146 PRUint32 peerCurves = 0;
1147 PRUint32 mutualCurves = 0;
1148 PRUint16 svrCertCurveName;
1149
1150 if (!data->data || data->len < 4 || data->len > 65535)
1151 goto loser;
1152 /* get the length of elliptic_curve_list */
1153 list_len = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len);
1154 if (list_len < 0 || data->len != list_len || (data->len % 2) != 0) {
1155 /* malformed */
1156 goto loser;
1157 }
1158 /* build bit vector of peer's supported curve names */
1159 while (data->len) {
1160 PRInt32 curve_name =
1161 ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len);
1162 if (curve_name > ec_noName && curve_name < ec_pastLastName) {
1163 peerCurves |= (1U << curve_name);
1164 }
1165 }
1166 /* What curves do we support in common? */
1167 mutualCurves = ss->ssl3.hs.negotiatedECCurves &= peerCurves;
1168 if (!mutualCurves) { /* no mutually supported EC Curves */
1169 goto loser;
1170 }
1171
1172 /* if our ECC cert doesn't use one of these supported curves,
1173 * disable ECC cipher suites that require an ECC cert.
1174 */
1175 svrCertCurveName = ssl3_GetSvrCertCurveName(ss);
1176 if (svrCertCurveName != ec_noName &&
1177 (mutualCurves & (1U << svrCertCurveName)) != 0) {
1178 return SECSuccess;
1179 }
1180 /* Our EC cert doesn't contain a mutually supported curve.
1181 * Disable all ECC cipher suites that require an EC cert
1182 */
1183 ssl3_DisableECCSuites(ss, ecdh_ecdsa_suites);
1184 ssl3_DisableECCSuites(ss, ecdhe_ecdsa_suites);
1185 return SECFailure;
1186
1187 loser:
1188 /* no common curve supported */
1189 ssl3_DisableECCSuites(ss, ecSuites);
1190 return SECFailure;
1191 }
1192
1193 #endif /* NSS_ENABLE_ECC */
OLDNEW
« no previous file with comments | « net/third_party/nss/ssl/ssl3con.c ('k') | net/third_party/nss/ssl/ssl3ext.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698