Blame SOURCES/jss-signature-correction.patch

c89ed9
# HG changeset patch
c89ed9
# User David Stutzman<david.konrad.stutzman@us.army.mil>
c89ed9
# Date 1515711524 28800
c89ed9
#      Thu Jan 11 14:58:44 2018 -0800
c89ed9
# Node ID 9e2db7eee6652330723d935c2b900b9b09b1ab9d
c89ed9
# Parent  ca2c2fcfaf207f87c3c69e493f2b30fd0a088e95
c89ed9
Bug 1409867 - additional fix from dstutzman: allow signatures to be created correctly.
c89ed9
c89ed9
cfu for dstutzman
c89ed9
c89ed9
diff --git a/org/mozilla/jss/pkix/cms/SignerInfo.java b/org/mozilla/jss/pkix/cms/SignerInfo.java
c89ed9
--- a/org/mozilla/jss/pkix/cms/SignerInfo.java
c89ed9
+++ b/org/mozilla/jss/pkix/cms/SignerInfo.java
c89ed9
@@ -9,14 +9,10 @@
c89ed9
 import org.mozilla.jss.util.Assert;
c89ed9
 import org.mozilla.jss.pkix.primitive.*;
c89ed9
 import org.mozilla.jss.crypto.*;
c89ed9
-import java.util.Vector;
c89ed9
-import java.math.BigInteger;
c89ed9
-import java.io.ByteArrayInputStream;
c89ed9
 import java.security.InvalidKeyException;
c89ed9
 import java.security.SignatureException;
c89ed9
 import java.security.NoSuchAlgorithmException;
c89ed9
 import java.security.MessageDigest;
c89ed9
-import org.mozilla.jss.crypto.*;
c89ed9
 import org.mozilla.jss.crypto.X509Certificate;
c89ed9
 import org.mozilla.jss.pkix.cert.*;
c89ed9
 import org.mozilla.jss.*;
c89ed9
@@ -73,14 +69,6 @@
c89ed9
     }
c89ed9
 
c89ed9
     /**
c89ed9
-     * Low-level method to set the version.
c89ed9
-     * It is not normally necessary to call this.  Use it at your own risk.
c89ed9
-    public void setVersion(INTEGER version) {
c89ed9
-        this.version = version;
c89ed9
-    }
c89ed9
-     */
c89ed9
-
c89ed9
-    /**
c89ed9
      * Retrieves the SignerIdentifier.
c89ed9
      */
c89ed9
     public SignerIdentifier getSignerIdentifier() {
c89ed9
@@ -88,14 +76,6 @@
c89ed9
     }
c89ed9
 
c89ed9
     /**
c89ed9
-     * Low-level method to set the signerIdentifier.
c89ed9
-     * It is not normally necessary to call this.  Use it at your own risk.
c89ed9
-    public void setSignerIdentifier( SignerIdentifier iasn ) {
c89ed9
-        this.signerIdentifier = iasn;
c89ed9
-    }
c89ed9
-     */
c89ed9
-
c89ed9
-    /**
c89ed9
      * Retrieves the DigestAlgorithm used in this SignerInfo.
c89ed9
      *
c89ed9
      * @exception NoSuchAlgorithmException If the algorithm is not
c89ed9
@@ -116,14 +96,6 @@
c89ed9
     }
c89ed9
 
c89ed9
     /**
c89ed9
-     * Low-level method to set the digest AlgorithmIdentifier.
c89ed9
-     * It is not normally necessary to call this.  Use it at your own risk.
c89ed9
-    public void setDigestAlgorithmIdentifier(AlgorithmIdentifier algid) {
c89ed9
-        this.digestAlgorithm = algid;
c89ed9
-    }
c89ed9
-     */
c89ed9
-
c89ed9
-    /**
c89ed9
      * Retrieves the signed attributes, if they exist.
c89ed9
      *
c89ed9
      */
c89ed9
@@ -139,14 +111,6 @@
c89ed9
     }
c89ed9
 
c89ed9
     /**
c89ed9
-     * Low-level method to set the signedAttributes field.
c89ed9
-     * It is not normally necessary to call this.  Use it at your own risk.
c89ed9
-    public void setSignedAttributes(SET authAttrib) {
c89ed9
-        this.signedAttributes = authAttrib;
c89ed9
-    }
c89ed9
-     */
c89ed9
-
c89ed9
-    /**
c89ed9
      * Returns the raw signature (digest encryption) algorithm used in this
c89ed9
      * SignerInfo.
c89ed9
      *
c89ed9
@@ -168,15 +132,6 @@
c89ed9
     }
c89ed9
 
c89ed9
     /**
c89ed9
-     * Low-level method to set the digestEncryptionAlgorithm field.
c89ed9
-     * It is not normally necessary to call this.  Use it at your own risk.
c89ed9
-    public void
c89ed9
-    setDigestEncryptionAlgorithmIdentifier(AlgorithmIdentifier algid) {
c89ed9
-        this.digestEncryptionAlgorithm= algid;
c89ed9
-    }
c89ed9
-     */
c89ed9
-
c89ed9
-    /**
c89ed9
      * Retrieves the encrypted digest.
c89ed9
      */
c89ed9
     public byte[] getEncryptedDigest() {
c89ed9
@@ -184,14 +139,6 @@
c89ed9
     }
c89ed9
 
c89ed9
     /**
c89ed9
-     * Low-level method to set the encryptedDigest field.
c89ed9
-     * It is not normally necessary to call this.  Use it at your own risk.
c89ed9
-    public void setEncryptedDigest(byte[] ed) {
c89ed9
-        this.encryptedDigest = new OCTET_STRING(ed);
c89ed9
-    }
c89ed9
-     */
c89ed9
-
c89ed9
-    /**
c89ed9
      * Retrieves the unsigned attributes, if they exist.
c89ed9
      *
c89ed9
      */
c89ed9
@@ -206,14 +153,6 @@
c89ed9
         return (unsignedAttributes!=null);
c89ed9
     }
c89ed9
 
c89ed9
-    /**
c89ed9
-     * Low-level method to set the unsignedAttributes field.
c89ed9
-     * It is not normally necessary to call this.  Use it at your own risk.
c89ed9
-    public void setUnsignedAttributes(SET unauthAttrib) {
c89ed9
-        this.unsignedAttributes = unauthAttrib;
c89ed9
-    }
c89ed9
-     */
c89ed9
-
c89ed9
     ///////////////////////////////////////////////////////////////////////
c89ed9
     ///////////////////////////////////////////////////////////////////////
c89ed9
     // Constructors
c89ed9
@@ -221,17 +160,6 @@
c89ed9
     ///////////////////////////////////////////////////////////////////////
c89ed9
 
c89ed9
     /**
c89ed9
-     * Low-level default constructor.  All fields are initialized to null.
c89ed9
-     * Before this SignerInfo can be processed or used in any way, all of
c89ed9
-     * the fields except signedAttributes and
c89ed9
-     * unsignedAttributes must be non-null.
c89ed9
-     * 

It is not normally necessary to call this constructor.Use it at

c89ed9
-     * your own risk.
c89ed9
-    public SignerInfo() {
c89ed9
-    }
c89ed9
-     */
c89ed9
-
c89ed9
-    /**
c89ed9
      * A constructor for creating a new SignerInfo from scratch.
c89ed9
      *
c89ed9
      * @param signerIdentifier The signerIdentifier of the
c89ed9
@@ -303,36 +231,32 @@
c89ed9
         //////////////////////////////////////////////////
c89ed9
 
c89ed9
         // compute the digest
c89ed9
-        byte[] digest=null;
c89ed9
-        DigestAlgorithm digestAlg = signingAlg.getDigestAlg();
c89ed9
-        if( signedAttributes == null ) {
c89ed9
+        CryptoToken token = signingKey.getOwningToken();
c89ed9
+        Signature sig;
c89ed9
+        byte[] toBeSigned = null;
c89ed9
+        if (signedAttributes == null) {
c89ed9
             // just use the message digest of the content
c89ed9
-            digest = messageDigest;
c89ed9
+            if (signingAlg.getRawAlg() == SignatureAlgorithm.RSASignature) {
c89ed9
+                SEQUENCE digestInfo = createDigestInfo(messageDigest, false);
c89ed9
+                toBeSigned = ASN1Util.encode(digestInfo);
c89ed9
+            } else {
c89ed9
+                toBeSigned = messageDigest;
c89ed9
+            }
c89ed9
+            sig = token.getSignatureContext(signingAlg.getRawAlg()); //data is already digested
c89ed9
         } else {
c89ed9
-            // digest the contents octets of the signed attributes
c89ed9
-            byte[] enc = ASN1Util.encode(signedAttributes);
c89ed9
-            MessageDigest md =
c89ed9
-                        MessageDigest.getInstance(digestAlg.toString());
c89ed9
-            digest = md.digest( enc );
c89ed9
-        }
c89ed9
-
c89ed9
-        byte[] toBeSigned;
c89ed9
-        if( signingAlg.getRawAlg() == SignatureAlgorithm.RSASignature ) {
c89ed9
-            // put the digest in a DigestInfo
c89ed9
-            SEQUENCE digestInfo = new SEQUENCE();
c89ed9
-            AlgorithmIdentifier digestAlgId =
c89ed9
-                    new AlgorithmIdentifier( digestAlg.toOID(),null );
c89ed9
-            digestInfo.addElement( digestAlgId );
c89ed9
-            digestInfo.addElement( new OCTET_STRING( digest ) );
c89ed9
-            toBeSigned = ASN1Util.encode(digestInfo);
c89ed9
-        } else {
c89ed9
-            toBeSigned = digest;
c89ed9
+            byte[] encoding = ASN1Util.encode(signedAttributes);
c89ed9
+            if (signingAlg.getRawAlg() == SignatureAlgorithm.RSASignature) {
c89ed9
+                // put the digest in a DigestInfo
c89ed9
+                SEQUENCE digestInfo = createDigestInfo(encoding, true);
c89ed9
+                toBeSigned = ASN1Util.encode(digestInfo);
c89ed9
+                sig = token.getSignatureContext(SignatureAlgorithm.RSASignature);
c89ed9
+            } else {
c89ed9
+                toBeSigned = encoding;
c89ed9
+                sig = token.getSignatureContext(signingAlg);
c89ed9
+            }
c89ed9
         }
c89ed9
         
c89ed9
         // encrypt the DER-encoded DigestInfo with the private key
c89ed9
-        CryptoToken token = signingKey.getOwningToken();
c89ed9
-        Signature sig;
c89ed9
-        sig = token.getSignatureContext( signingAlg );
c89ed9
         sig.initSign(signingKey);
c89ed9
         sig.update(toBeSigned);
c89ed9
         encryptedDigest = new OCTET_STRING(sig.sign());
c89ed9
@@ -494,21 +418,20 @@
c89ed9
                 digestEncryptionAlgorithm.getOID()
c89ed9
             );
c89ed9
 
c89ed9
+        CryptoToken token = CryptoManager.getInstance()
c89ed9
+                .getInternalCryptoToken();
c89ed9
+        Signature sig;
c89ed9
         byte[] toBeVerified;
c89ed9
-        if( sigAlg.getRawAlg() == SignatureAlgorithm.RSASignature ) {
c89ed9
+        if (sigAlg.getRawAlg() == SignatureAlgorithm.RSASignature) {
c89ed9
             // create DigestInfo structure
c89ed9
-            SEQUENCE digestInfo = new SEQUENCE();
c89ed9
-            digestInfo.addElement(
c89ed9
-                new AlgorithmIdentifier(digestAlgorithm.getOID(), null) );
c89ed9
-            digestInfo.addElement( new OCTET_STRING(messageDigest) );
c89ed9
+            SEQUENCE digestInfo = createDigestInfo(messageDigest, false);
c89ed9
             toBeVerified = ASN1Util.encode(digestInfo);
c89ed9
+            sig = token.getSignatureContext(sigAlg.getRawAlg());
c89ed9
         } else {
c89ed9
             toBeVerified = messageDigest;
c89ed9
+            sig = token.getSignatureContext(sigAlg);
c89ed9
         }
c89ed9
-
c89ed9
-        CryptoToken token = CryptoManager.getInstance()
c89ed9
-                                .getInternalCryptoToken();
c89ed9
-        Signature sig = token.getSignatureContext(sigAlg);
c89ed9
+        
c89ed9
         sig.initVerify(pubkey);
c89ed9
         sig.update(toBeVerified);
c89ed9
         if( sig.verify(encryptedDigest.toByteArray()) ) {
c89ed9
@@ -671,31 +594,22 @@
c89ed9
         // Now verify the signature.
c89ed9
         CryptoToken token =
c89ed9
                     CryptoManager.getInstance().getInternalCryptoToken();
c89ed9
-        Signature sig = token.getSignatureContext( sigAlg );
c89ed9
-        sig.initVerify(pubkey);
c89ed9
+        Signature sig;
c89ed9
 
c89ed9
         // verify the contents octets of the DER encoded signed attribs
c89ed9
-        byte[] toBeDigested = ASN1Util.encode(signedAttributes);
c89ed9
-    
c89ed9
-        MessageDigest md = MessageDigest.getInstance(
c89ed9
-                DigestAlgorithm.fromOID(digestAlgorithm.getOID()).toString() );
c89ed9
-        byte[] digest = md.digest(toBeDigested);
c89ed9
-
c89ed9
+        byte[] encoding = ASN1Util.encode(signedAttributes);
c89ed9
         byte[] toBeVerified;
c89ed9
-        if( sigAlg.getRawAlg() == SignatureAlgorithm.RSASignature ) {
c89ed9
+        if (sigAlg.getRawAlg() == SignatureAlgorithm.RSASignature) {
c89ed9
             // create DigestInfo structure
c89ed9
-            SEQUENCE digestInfo = new SEQUENCE();
c89ed9
-		
c89ed9
-            AlgorithmIdentifier digestAlgId =
c89ed9
-                    new AlgorithmIdentifier( digestAlgorithm.getOID(),null );
c89ed9
-            digestInfo.addElement( digestAlgId );
c89ed9
-		
c89ed9
-            digestInfo.addElement( new OCTET_STRING(digest) );
c89ed9
+            SEQUENCE digestInfo = createDigestInfo(encoding, true);
c89ed9
             toBeVerified = ASN1Util.encode(digestInfo);
c89ed9
+            sig = token.getSignatureContext(SignatureAlgorithm.RSASignature);
c89ed9
         } else {
c89ed9
-            toBeVerified = digest;
c89ed9
+            toBeVerified = encoding;
c89ed9
+            sig = token.getSignatureContext(sigAlg);
c89ed9
         }
c89ed9
  
c89ed9
+        sig.initVerify(pubkey);
c89ed9
         sig.update( toBeVerified );
c89ed9
 
c89ed9
         if( ! sig.verify(encryptedDigest.toByteArray()) ) {
c89ed9
@@ -708,6 +622,25 @@
c89ed9
         // SUCCESSFULLY VERIFIED
c89ed9
 
c89ed9
     }
c89ed9
+        
c89ed9
+    private SEQUENCE createDigestInfo(byte[] data, boolean doDigest) throws NoSuchAlgorithmException {
c89ed9
+        if(data == null || data.length == 0){
c89ed9
+            throw new IllegalArgumentException("Data to digest must be supplied");
c89ed9
+        }
c89ed9
+        SEQUENCE digestInfo = new SEQUENCE();
c89ed9
+        digestInfo.addElement(this.digestAlgorithm);
c89ed9
+        byte[] digest;
c89ed9
+        if (doDigest) {
c89ed9
+            MessageDigest md = MessageDigest.getInstance(
c89ed9
+                    DigestAlgorithm.fromOID(this.digestAlgorithm.getOID()).toString());
c89ed9
+            digest = md.digest(data);
c89ed9
+        } else {
c89ed9
+            digest = data;
c89ed9
+        }
c89ed9
+        digestInfo.addElement(new OCTET_STRING(digest));
c89ed9
+        return digestInfo;
c89ed9
+    }
c89ed9
+
c89ed9
 
c89ed9
     /**
c89ed9
      * Compares two non-null byte arrays.  Returns true if they are identical,