Bug 1057161 - NSS hangs with 100% CPU on invalid EC key. r=rrelyea
☠☠ backed out by 70ae6afde27f ☠ ☠
authorRichard Barnes <rbarnes@mozilla.com>
Tue, 16 Sep 2014 11:43:34 -0700
changeset 11250 24852c6f89ea7ed2b8f231320d9a0a03bdd706d4
parent 11249 c8358d66ca3e896b3ee06986c5054123f7c20a46
child 11251 70ae6afde27f9c977badc5271efa835c8a4ec4f0
push id478
push usermartin.thomson@gmail.com
push dateTue, 16 Sep 2014 18:47:53 +0000
reviewersrrelyea
bugs1057161
Bug 1057161 - NSS hangs with 100% CPU on invalid EC key. r=rrelyea
lib/freebl/ec.c
lib/softoken/pkcs11.c
--- a/lib/freebl/ec.c
+++ b/lib/freebl/ec.c
@@ -865,16 +865,21 @@ cleanup:
     PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
 #endif /* NSS_DISABLE_ECC */
 
     return rv;
 }
 
 /*
 ** Checks the signature on the given digest using the key provided.
+**
+** The key argument must represent a valid EC public key (a point on
+** the relevant curve).  If it is not a valid point, then the behavior
+** of this function is undefined.  In cases where a public key might
+** not be valid, use EC_ValidatePublicKey to check.
 */
 SECStatus 
 ECDSA_VerifyDigest(ECPublicKey *key, const SECItem *signature, 
                  const SECItem *digest)
 {
     SECStatus rv = SECFailure;
 #ifndef NSS_DISABLE_ECC
     mp_int r_, s_;           /* tuple (r', s') is received signature) */
--- a/lib/softoken/pkcs11.c
+++ b/lib/softoken/pkcs11.c
@@ -856,16 +856,58 @@ sftk_handleCrlObject(SFTKSession *sessio
 	sftk_freeDB(certHandle);
 	return crv;
     }
 
     return CKR_OK;
 }
 
 /*
+ * Check whether an EC public key object represents a valid point
+ */
+static SECStatus
+sftk_verifyECPublicKey(SFTKObject *object)
+{
+    SECStatus rv = SECFailure;
+    SECItem derParams = { 0 };
+    ECParams* ecParams = NULL;
+    SECItem publicValue = { 0 };
+    SFTKAttribute* params = NULL;
+    SFTKAttribute* point = NULL;
+
+    params = sftk_FindAttribute(object, CKA_EC_PARAMS);
+    point  = sftk_FindAttribute(object, CKA_EC_POINT);
+    if (!params || !point)
+        goto loser;
+
+    derParams.data = params->attrib.pValue;
+    derParams.len  = params->attrib.ulValueLen;
+    publicValue.data = point->attrib.pValue;
+    publicValue.len  = point->attrib.ulValueLen;
+
+    rv = EC_DecodeParams(&derParams, &ecParams);
+    if (rv == SECSuccess) {
+        rv = EC_ValidatePublicKey(ecParams, &publicValue);
+    }
+
+loser:
+    if (params) {
+        sftk_FreeAttribute(params);
+    }
+    if (point) {
+        sftk_FreeAttribute(point);
+    }
+    if (ecParams) {
+        PORT_FreeArena(ecParams->arena, PR_TRUE);
+    }
+    return rv;
+}
+
+
+/*
  * check the consistancy and initialize a Public Key Object 
  */
 static CK_RV
 sftk_handlePublicKeyObject(SFTKSession *session, SFTKObject *object,
 							 CK_KEY_TYPE key_type)
 {
     CK_BBOOL encrypt = CK_TRUE;
     CK_BBOOL recover = CK_TRUE;
@@ -932,16 +974,19 @@ sftk_handlePublicKeyObject(SFTKSession *
 #ifndef NSS_DISABLE_ECC
     case CKK_EC:
 	if ( !sftk_hasAttribute(object, CKA_EC_PARAMS)) {
 	    return CKR_TEMPLATE_INCOMPLETE;
 	}
 	if ( !sftk_hasAttribute(object, CKA_EC_POINT)) {
 	    return CKR_TEMPLATE_INCOMPLETE;
 	}
+	if ( sftk_verifyECPublicKey(object) != SECSuccess ) {
+	    return CKR_TEMPLATE_INCONSISTENT;
+	}
 	derive = CK_TRUE;    /* for ECDH */
 	verify = CK_TRUE;    /* for ECDSA */
 	encrypt = CK_FALSE;
 	recover = CK_FALSE;
 	wrap = CK_FALSE;
 	break;
 #endif /* NSS_DISABLE_ECC */
     default: