In particular the NSS_USE_ALG_IN_SSL_KX flag can be specified to allow a
specific curve for TLS negotiation. This will affect the advertized curves
as well.
---
lib/ssl/ssl3ecc.c | 116 ++++++++++++++++++++++++++++++++++--------------------
1 file changed, 74 insertions(+), 42 deletions(-)
diff --git a/lib/ssl/ssl3ecc.c b/lib/ssl/ssl3ecc.c
index 37743a6..3feb41c 100644
--- a/lib/ssl/ssl3ecc.c
+++ b/lib/ssl/ssl3ecc.c
@@ -161,6 +161,7 @@ SECStatus
ssl3_ECName2Params(PLArenaPool * arena, ECName curve, SECKEYECParams * params)
{
SECOidData *oidData = NULL;
+ PRUint32 policyFlags = 0;
if ((curve <= ec_noName) || (curve >= ec_pastLastName) ||
((oidData = SECOID_FindOIDByTag(ecName2OIDTag[curve])) == NULL)) {
@@ -168,6 +169,12 @@ ssl3_ECName2Params(PLArenaPool * arena, ECName curve,
SECKEYECParams * params)
return SECFailure;
}
+ if (NSS_GetAlgorithmPolicy(ecName2OIDTag[curve], &policyFlags) ==
SECFailure ||
+ !(policyFlags & NSS_USE_ALG_IN_SSL_KX)) {
+ PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
+ return SECFailure;
+ }
+
SECITEM_AllocItem(arena, params, (2 + oidData->oid.len));
/*
* params->data needs to contain the ASN encoding of an object ID (OID)
@@ -186,6 +193,7 @@ params2ecName(SECKEYECParams * params)
{
SECItem oid = { siBuffer, NULL, 0};
SECOidData *oidData = NULL;
+ PRUint32 policyFlags = 0;
ECName i;
/*
@@ -198,8 +206,12 @@ params2ecName(SECKEYECParams * params)
oid.data = params->data + 2;
if ((oidData = SECOID_FindOID(&oid)) == NULL) return ec_noName;
for (i = ec_noName + 1; i < ec_pastLastName; i++) {
- if (ecName2OIDTag[i] == oidData->offset)
- return i;
+ if (ecName2OIDTag[i] == oidData->offset) {
+ if (NSS_GetAlgorithmPolicy(oidData->offset, &policyFlags) ==
SECSuccess &&
+ (policyFlags & NSS_USE_ALG_IN_SSL_KX)) {
+ return i;
+ }
+ }
}
return ec_noName;
@@ -1034,29 +1046,6 @@ ssl3_IsECCEnabled(sslSocket * ss)
#define BE(n) 0, n
-/* Prefabricated TLS client hello extension, Elliptic Curves List,
- * offers only 3 curves, the Suite B curves, 23-25
- */
-static const PRUint8 suiteBECList[12] = {
- BE(10), /* Extension type */
- BE( 8), /* octets that follow ( 3 pairs + 1 length pair) */
- BE( 6), /* octets that follow ( 3 pairs) */
- BE(23), BE(24), BE(25)
-};
-
-/* Prefabricated TLS client hello extension, Elliptic Curves List,
- * offers curves 1-25.
- */
-static const PRUint8 tlsECList[56] = {
- BE(10), /* Extension type */
- BE(52), /* octets that follow (25 pairs + 1 length pair) */
- BE(50), /* octets that follow (25 pairs) */
- BE( 1), BE( 2), BE( 3), BE( 4), BE( 5), BE( 6), BE( 7),
- BE( 8), BE( 9), BE(10), BE(11), BE(12), BE(13), BE(14), BE(15),
- BE(16), BE(17), BE(18), BE(19), BE(20), BE(21), BE(22), BE(23),
- BE(24), BE(25)
-};
-
static const PRUint8 ecPtFmt[6] = {
BE(11), /* Extension type */
BE( 2), /* octets that follow */
@@ -1088,6 +1077,13 @@ ssl3_SuiteBOnly(sslSocket *ss)
return PR_FALSE;
}
+#define APPEND_CURVE(CURVE_ID) \
+ if (NSS_GetAlgorithmPolicy(ecName2OIDTag[CURVE_ID], &policy) == SECSuccess
&& \
+ (policy & NSS_USE_ALG_IN_SSL_KX)) { \
+ enabledCurves[pos++] = 0; \
+ enabledCurves[pos++] = CURVE_ID; \
+ }
+
/* Send our "canned" (precompiled) Supported Elliptic Curves extension,
* which says that we support all TLS-defined named curves.
*/
@@ -1097,40 +1093,76 @@ ssl3_SendSupportedCurvesXtn(
PRBool append,
PRUint32 maxBytes)
{
- PRInt32 ecListSize = 0;
- const PRUint8 *ecList = NULL;
+ unsigned char enabledCurves[64];
+ PRUint32 policy;
+ unsigned pos = 0;
+ PRInt32 extension_length;
+ unsigned i;
if (!ss || !ssl3_IsECCEnabled(ss))
return 0;
if (ssl3_SuiteBOnly(ss)) {
- ecListSize = sizeof suiteBECList;
- ecList = suiteBECList;
+ APPEND_CURVE(23);
+ APPEND_CURVE(24);
+ APPEND_CURVE(25);
} else {
- ecListSize = sizeof tlsECList;
- ecList = tlsECList;
+ for (i=1;i<=25;i++) {
+ APPEND_CURVE(i);
+ }
}
-
- if (append && maxBytes >= ecListSize) {
- SECStatus rv = ssl3_AppendHandshake(ss, ecList, ecListSize);
+
+ extension_length =
+ 2 /* extension type */ +
+ 2 /* extension length */ +
+ 2 /* elliptic curves length */ +
+ pos;
+
+ if (append && maxBytes >= extension_length) {
+ SECStatus rv;
+ rv = ssl3_AppendHandshakeNumber(ss, ssl_elliptic_curves_xtn, 2);
if (rv != SECSuccess)
- return -1;
- if (!ss->sec.isServer) {
- TLSExtensionData *xtnData = &ss->xtnData;
- xtnData->advertised[xtnData->numAdvertised++] =
+ goto loser;
+ rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2);
+ if (rv != SECSuccess)
+ goto loser;
+ rv = ssl3_AppendHandshakeVariable(ss, enabledCurves,
+ pos, 2);
+ if (rv != SECSuccess)
+ goto loser;
+ ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
ssl_elliptic_curves_xtn;
- }
+ } else if (maxBytes < extension_length) {
+ PORT_Assert(0);
+ return 0;
}
- return ecListSize;
+
+ return extension_length;
+loser:
+ return -1;
}
PRUint32
ssl3_GetSupportedECCurveMask(sslSocket *ss)
{
+ unsigned i;
+ PRUint32 curves = 0;
+ PRUint32 policyFlags = 0;
+
+ PORT_Assert(ec_pastLastName <= 31);
+ for (i = ec_noName + 1; i < ec_pastLastName; i++) {
+ if (NSS_GetAlgorithmPolicy(ecName2OIDTag[i], &policyFlags) ==
SECFailure ||
+ !(policyFlags & NSS_USE_ALG_IN_SSL_KX)) {
+ continue;
+ }
+ curves |= (1U << i);
+ }
+
if (ssl3_SuiteBOnly(ss)) {
- return SSL3_SUITE_B_SUPPORTED_CURVES_MASK;
+ return (curves & SSL3_SUITE_B_SUPPORTED_CURVES_MASK);
}
- return SSL3_ALL_SUPPORTED_CURVES_MASK;
+
+ return curves;
}
/* Send our "canned" (precompiled) Supported Point Formats extension,
--
1.9.0
--
dev-tech-crypto mailing list
[email protected]
https://lists.mozilla.org/listinfo/dev-tech-crypto