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
dev-tech-crypto@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-tech-crypto

Reply via email to