In particular the NSS_USE_ALG_IN_CERT_SIGNATURE flag can be specified to allow a
specific curve for certificate verification.
---
 lib/certhigh/certvfy.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 63 insertions(+), 2 deletions(-)

diff --git a/lib/certhigh/certvfy.c b/lib/certhigh/certvfy.c
index 3141163..7618822 100644
--- a/lib/certhigh/certvfy.c
+++ b/lib/certhigh/certvfy.c
@@ -34,6 +34,62 @@ CERT_CertTimesValid(CERTCertificate *c)
     return (valid == secCertTimeValid) ? SECSuccess : SECFailure;
 }
 
+static SECOidTag
+params2ecTag(const SECKEYECParams * params)
+{
+    SECItem oid = { siBuffer, NULL, 0};
+    SECOidData *oidData = NULL;
+
+    /* 
+     * params->data needs to contain the ASN encoding of an object ID (OID)
+     * representing a named curve. Here, we strip away everything
+     * before the actual OID and use the OID to look up a named curve.
+     */
+    if (params->data[0] != SEC_ASN1_OBJECT_ID) return 0;
+    oid.len = params->len - 2;
+    oid.data = params->data + 2;
+    if ((oidData = SECOID_FindOID(&oid)) == NULL) return 0;
+
+    return oidData->offset;
+}
+
+SECStatus CheckECDSACurves(const SECAlgorithmID *sigAlgorithm, const 
SECKEYPublicKey *key)
+{
+SECOidTag sigAlg;
+SECOidTag curve;
+PRUint32 policyFlags = 0;
+
+    sigAlg = SECOID_GetAlgorithmTag(sigAlgorithm);
+
+    switch(sigAlg) {
+        case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
+       case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE:
+       case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE:
+       case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE:
+       case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE:
+           if (key->keyType != ecKey) {
+               PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
+               return SECFailure;
+           }
+
+            curve = params2ecTag(&key->u.ec.DEREncodedParams);
+           if (curve != 0) {
+               if (NSS_GetAlgorithmPolicy(curve, &policyFlags) == SECFailure ||
+                   !(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) {
+                   PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
+                   return SECFailure;
+               } else {
+                   return SECSuccess;
+                }
+            } else {
+               PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
+               return SECFailure;
+           }
+       default:
+           return SECSuccess;
+    }
+}
+
 /*
  * verify the signature of a signed data object with the given DER publickey
  */
@@ -50,7 +106,6 @@ CERT_VerifySignedDataWithPublicKey(const CERTSignedData *sd,
        PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
        return SECFailure;
     }
-
     /* check the signature */
     sig = sd->signature;
     /* convert sig->len from bit counts to byte count. */
@@ -61,11 +116,17 @@ CERT_VerifySignedDataWithPublicKey(const CERTSignedData 
*sd,
     if (rv == SECSuccess) {
         /* Are we honoring signatures for this algorithm?  */
        PRUint32 policyFlags = 0;
+       rv = CheckECDSACurves(&sd->signatureAlgorithm, pubKey);
+       if (rv != SECSuccess) {
+           PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
+           return SECFailure;
+       }
+
        rv = NSS_GetAlgorithmPolicy(hashAlg, &policyFlags);
        if (rv == SECSuccess && 
            !(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) {
            PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
-           rv = SECFailure;
+           return SECFailure;
        }
     }
     return rv;
-- 
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