From 1cf558d156412630f59eb360719f65a45cebc293 Mon Sep 17 00:00:00 2001 From: Matthew Harmsen Date: Mon, 22 Jan 2018 16:19:14 -0700 Subject: [PATCH] Resolves: mbz #1409867,589158,386351 - Mozilla Bugzilla #1409867 - org.mozilla.jss.pkix.cms.SignerInfo incorrectly producing signatures (especially for EC) (cfu,dstutzman) - Mozilla Bugzilla #589158 - Add Sun's standard algorithm names for all ECC signature types (cfu,dstutzman) - Mozilla Bugzilla #386351 - SignerInfo class inserts wrong version # into the resulting structure (cfu,dstutzman) --- jss-fix-SignerInfo-version.patch | 44 ++++ jss-signature-correction.patch | 306 ++++++++++++++++++++++ jss-standardize-ECC-algorithm-names.patch | 41 +++ jss.spec | 16 +- 4 files changed, 406 insertions(+), 1 deletion(-) create mode 100644 jss-fix-SignerInfo-version.patch create mode 100644 jss-signature-correction.patch create mode 100644 jss-standardize-ECC-algorithm-names.patch diff --git a/jss-fix-SignerInfo-version.patch b/jss-fix-SignerInfo-version.patch new file mode 100644 index 0000000..e76e393 --- /dev/null +++ b/jss-fix-SignerInfo-version.patch @@ -0,0 +1,44 @@ +# HG changeset patch +# User David Stutzman +# Date 1516144092 28800 +# Tue Jan 16 15:08:12 2018 -0800 +# Node ID 1d858c6d4626b625bb671426e6899d98c2f5bb2e +# Parent 8746a3fc74785e2fd12f86d08a6886ed9160620e +Bug# 386351 SignerInfo version, r=cfu + +This patch fixes versioning of SignerInfo to match CMS spec. + +cfu for dstutzman + +diff --git a/org/mozilla/jss/pkix/cms/SignerInfo.java b/org/mozilla/jss/pkix/cms/SignerInfo.java +--- a/org/mozilla/jss/pkix/cms/SignerInfo.java ++++ b/org/mozilla/jss/pkix/cms/SignerInfo.java +@@ -52,9 +52,6 @@ + private OCTET_STRING encryptedDigest; + private SET unsignedAttributes; // [1] OPTIONAL + +- // we only do CMS in RFC 2630 +- private static final INTEGER VERSION = new INTEGER(3); +- + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + // Accessor methods +@@ -198,8 +195,17 @@ + CryptoManager.NotInitializedException, SignatureException, + TokenException + { +- version = VERSION; ++ if (signerIdentifier == null) { ++ throw new IllegalArgumentException("SignerIdentifier may not be null"); ++ } + this.signerIdentifier = signerIdentifier; ++ if (SignerIdentifier.ISSUER_AND_SERIALNUMBER.equals(this.signerIdentifier.getType())) { ++ this.version = new INTEGER(1); ++ } else if (SignerIdentifier.SUBJECT_KEY_IDENTIFIER.equals(this.signerIdentifier.getType())) { ++ this.version = new INTEGER(3); ++ } else { ++ throw new IllegalArgumentException("Unexpected SignerIdentifier type"); ++ } + this.digestAlgorithm = + new AlgorithmIdentifier(signingAlg.getDigestAlg().toOID(),null); + diff --git a/jss-signature-correction.patch b/jss-signature-correction.patch new file mode 100644 index 0000000..1746083 --- /dev/null +++ b/jss-signature-correction.patch @@ -0,0 +1,306 @@ +# HG changeset patch +# User David Stutzman +# Date 1515711524 28800 +# Thu Jan 11 14:58:44 2018 -0800 +# Node ID 9e2db7eee6652330723d935c2b900b9b09b1ab9d +# Parent ca2c2fcfaf207f87c3c69e493f2b30fd0a088e95 +Bug 1409867 - additional fix from dstutzman: allow signatures to be created correctly. + +cfu for dstutzman + +diff --git a/org/mozilla/jss/pkix/cms/SignerInfo.java b/org/mozilla/jss/pkix/cms/SignerInfo.java +--- a/org/mozilla/jss/pkix/cms/SignerInfo.java ++++ b/org/mozilla/jss/pkix/cms/SignerInfo.java +@@ -9,14 +9,10 @@ + import org.mozilla.jss.util.Assert; + import org.mozilla.jss.pkix.primitive.*; + import org.mozilla.jss.crypto.*; +-import java.util.Vector; +-import java.math.BigInteger; +-import java.io.ByteArrayInputStream; + import java.security.InvalidKeyException; + import java.security.SignatureException; + import java.security.NoSuchAlgorithmException; + import java.security.MessageDigest; +-import org.mozilla.jss.crypto.*; + import org.mozilla.jss.crypto.X509Certificate; + import org.mozilla.jss.pkix.cert.*; + import org.mozilla.jss.*; +@@ -73,14 +69,6 @@ + } + + /** +- * Low-level method to set the version. +- * It is not normally necessary to call this. Use it at your own risk. +- public void setVersion(INTEGER version) { +- this.version = version; +- } +- */ +- +- /** + * Retrieves the SignerIdentifier. + */ + public SignerIdentifier getSignerIdentifier() { +@@ -88,14 +76,6 @@ + } + + /** +- * Low-level method to set the signerIdentifier. +- * It is not normally necessary to call this. Use it at your own risk. +- public void setSignerIdentifier( SignerIdentifier iasn ) { +- this.signerIdentifier = iasn; +- } +- */ +- +- /** + * Retrieves the DigestAlgorithm used in this SignerInfo. + * + * @exception NoSuchAlgorithmException If the algorithm is not +@@ -116,14 +96,6 @@ + } + + /** +- * Low-level method to set the digest AlgorithmIdentifier. +- * It is not normally necessary to call this. Use it at your own risk. +- public void setDigestAlgorithmIdentifier(AlgorithmIdentifier algid) { +- this.digestAlgorithm = algid; +- } +- */ +- +- /** + * Retrieves the signed attributes, if they exist. + * + */ +@@ -139,14 +111,6 @@ + } + + /** +- * Low-level method to set the signedAttributes field. +- * It is not normally necessary to call this. Use it at your own risk. +- public void setSignedAttributes(SET authAttrib) { +- this.signedAttributes = authAttrib; +- } +- */ +- +- /** + * Returns the raw signature (digest encryption) algorithm used in this + * SignerInfo. + * +@@ -168,15 +132,6 @@ + } + + /** +- * Low-level method to set the digestEncryptionAlgorithm field. +- * It is not normally necessary to call this. Use it at your own risk. +- public void +- setDigestEncryptionAlgorithmIdentifier(AlgorithmIdentifier algid) { +- this.digestEncryptionAlgorithm= algid; +- } +- */ +- +- /** + * Retrieves the encrypted digest. + */ + public byte[] getEncryptedDigest() { +@@ -184,14 +139,6 @@ + } + + /** +- * Low-level method to set the encryptedDigest field. +- * It is not normally necessary to call this. Use it at your own risk. +- public void setEncryptedDigest(byte[] ed) { +- this.encryptedDigest = new OCTET_STRING(ed); +- } +- */ +- +- /** + * Retrieves the unsigned attributes, if they exist. + * + */ +@@ -206,14 +153,6 @@ + return (unsignedAttributes!=null); + } + +- /** +- * Low-level method to set the unsignedAttributes field. +- * It is not normally necessary to call this. Use it at your own risk. +- public void setUnsignedAttributes(SET unauthAttrib) { +- this.unsignedAttributes = unauthAttrib; +- } +- */ +- + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + // Constructors +@@ -221,17 +160,6 @@ + /////////////////////////////////////////////////////////////////////// + + /** +- * Low-level default constructor. All fields are initialized to null. +- * Before this SignerInfo can be processed or used in any way, all of +- * the fields except signedAttributes and +- * unsignedAttributes must be non-null. +- *

It is not normally necessary to call this constructor.Use it at +- * your own risk. +- public SignerInfo() { +- } +- */ +- +- /** + * A constructor for creating a new SignerInfo from scratch. + * + * @param signerIdentifier The signerIdentifier of the +@@ -303,36 +231,32 @@ + ////////////////////////////////////////////////// + + // compute the digest +- byte[] digest=null; +- DigestAlgorithm digestAlg = signingAlg.getDigestAlg(); +- if( signedAttributes == null ) { ++ CryptoToken token = signingKey.getOwningToken(); ++ Signature sig; ++ byte[] toBeSigned = null; ++ if (signedAttributes == null) { + // just use the message digest of the content +- digest = messageDigest; ++ if (signingAlg.getRawAlg() == SignatureAlgorithm.RSASignature) { ++ SEQUENCE digestInfo = createDigestInfo(messageDigest, false); ++ toBeSigned = ASN1Util.encode(digestInfo); ++ } else { ++ toBeSigned = messageDigest; ++ } ++ sig = token.getSignatureContext(signingAlg.getRawAlg()); //data is already digested + } else { +- // digest the contents octets of the signed attributes +- byte[] enc = ASN1Util.encode(signedAttributes); +- MessageDigest md = +- MessageDigest.getInstance(digestAlg.toString()); +- digest = md.digest( enc ); +- } +- +- byte[] toBeSigned; +- if( signingAlg.getRawAlg() == SignatureAlgorithm.RSASignature ) { +- // put the digest in a DigestInfo +- SEQUENCE digestInfo = new SEQUENCE(); +- AlgorithmIdentifier digestAlgId = +- new AlgorithmIdentifier( digestAlg.toOID(),null ); +- digestInfo.addElement( digestAlgId ); +- digestInfo.addElement( new OCTET_STRING( digest ) ); +- toBeSigned = ASN1Util.encode(digestInfo); +- } else { +- toBeSigned = digest; ++ byte[] encoding = ASN1Util.encode(signedAttributes); ++ if (signingAlg.getRawAlg() == SignatureAlgorithm.RSASignature) { ++ // put the digest in a DigestInfo ++ SEQUENCE digestInfo = createDigestInfo(encoding, true); ++ toBeSigned = ASN1Util.encode(digestInfo); ++ sig = token.getSignatureContext(SignatureAlgorithm.RSASignature); ++ } else { ++ toBeSigned = encoding; ++ sig = token.getSignatureContext(signingAlg); ++ } + } + + // encrypt the DER-encoded DigestInfo with the private key +- CryptoToken token = signingKey.getOwningToken(); +- Signature sig; +- sig = token.getSignatureContext( signingAlg ); + sig.initSign(signingKey); + sig.update(toBeSigned); + encryptedDigest = new OCTET_STRING(sig.sign()); +@@ -494,21 +418,20 @@ + digestEncryptionAlgorithm.getOID() + ); + ++ CryptoToken token = CryptoManager.getInstance() ++ .getInternalCryptoToken(); ++ Signature sig; + byte[] toBeVerified; +- if( sigAlg.getRawAlg() == SignatureAlgorithm.RSASignature ) { ++ if (sigAlg.getRawAlg() == SignatureAlgorithm.RSASignature) { + // create DigestInfo structure +- SEQUENCE digestInfo = new SEQUENCE(); +- digestInfo.addElement( +- new AlgorithmIdentifier(digestAlgorithm.getOID(), null) ); +- digestInfo.addElement( new OCTET_STRING(messageDigest) ); ++ SEQUENCE digestInfo = createDigestInfo(messageDigest, false); + toBeVerified = ASN1Util.encode(digestInfo); ++ sig = token.getSignatureContext(sigAlg.getRawAlg()); + } else { + toBeVerified = messageDigest; ++ sig = token.getSignatureContext(sigAlg); + } +- +- CryptoToken token = CryptoManager.getInstance() +- .getInternalCryptoToken(); +- Signature sig = token.getSignatureContext(sigAlg); ++ + sig.initVerify(pubkey); + sig.update(toBeVerified); + if( sig.verify(encryptedDigest.toByteArray()) ) { +@@ -671,31 +594,22 @@ + // Now verify the signature. + CryptoToken token = + CryptoManager.getInstance().getInternalCryptoToken(); +- Signature sig = token.getSignatureContext( sigAlg ); +- sig.initVerify(pubkey); ++ Signature sig; + + // verify the contents octets of the DER encoded signed attribs +- byte[] toBeDigested = ASN1Util.encode(signedAttributes); +- +- MessageDigest md = MessageDigest.getInstance( +- DigestAlgorithm.fromOID(digestAlgorithm.getOID()).toString() ); +- byte[] digest = md.digest(toBeDigested); +- ++ byte[] encoding = ASN1Util.encode(signedAttributes); + byte[] toBeVerified; +- if( sigAlg.getRawAlg() == SignatureAlgorithm.RSASignature ) { ++ if (sigAlg.getRawAlg() == SignatureAlgorithm.RSASignature) { + // create DigestInfo structure +- SEQUENCE digestInfo = new SEQUENCE(); +- +- AlgorithmIdentifier digestAlgId = +- new AlgorithmIdentifier( digestAlgorithm.getOID(),null ); +- digestInfo.addElement( digestAlgId ); +- +- digestInfo.addElement( new OCTET_STRING(digest) ); ++ SEQUENCE digestInfo = createDigestInfo(encoding, true); + toBeVerified = ASN1Util.encode(digestInfo); ++ sig = token.getSignatureContext(SignatureAlgorithm.RSASignature); + } else { +- toBeVerified = digest; ++ toBeVerified = encoding; ++ sig = token.getSignatureContext(sigAlg); + } + ++ sig.initVerify(pubkey); + sig.update( toBeVerified ); + + if( ! sig.verify(encryptedDigest.toByteArray()) ) { +@@ -708,6 +622,25 @@ + // SUCCESSFULLY VERIFIED + + } ++ ++ private SEQUENCE createDigestInfo(byte[] data, boolean doDigest) throws NoSuchAlgorithmException { ++ if(data == null || data.length == 0){ ++ throw new IllegalArgumentException("Data to digest must be supplied"); ++ } ++ SEQUENCE digestInfo = new SEQUENCE(); ++ digestInfo.addElement(this.digestAlgorithm); ++ byte[] digest; ++ if (doDigest) { ++ MessageDigest md = MessageDigest.getInstance( ++ DigestAlgorithm.fromOID(this.digestAlgorithm.getOID()).toString()); ++ digest = md.digest(data); ++ } else { ++ digest = data; ++ } ++ digestInfo.addElement(new OCTET_STRING(digest)); ++ return digestInfo; ++ } ++ + + /** + * Compares two non-null byte arrays. Returns true if they are identical, diff --git a/jss-standardize-ECC-algorithm-names.patch b/jss-standardize-ECC-algorithm-names.patch new file mode 100644 index 0000000..dc47fdb --- /dev/null +++ b/jss-standardize-ECC-algorithm-names.patch @@ -0,0 +1,41 @@ +# HG changeset patch +# User David Stutzman +# Date 1515722400 28800 +# Thu Jan 11 18:00:00 2018 -0800 +# Node ID 8746a3fc74785e2fd12f86d08a6886ed9160620e +# Parent 9e2db7eee6652330723d935c2b900b9b09b1ab9d +Bug 589158 Add support for Java Security Standard Algorithm Names for EC Signature types + +This patch adds the aliases for Java Security Standard Algorithm Names for EC Signature types. + +cfu for dstutzman (reviewed by wtc) + +diff --git a/org/mozilla/jss/JSSProvider.java b/org/mozilla/jss/JSSProvider.java +--- a/org/mozilla/jss/JSSProvider.java ++++ b/org/mozilla/jss/JSSProvider.java +@@ -79,21 +79,25 @@ + put("Alg.Alias.Signature.SHA-1/EC", "SHA1withEC"); + put("Alg.Alias.Signature.SHA/ECDSA", "SHA1withEC"); + put("Alg.Alias.Signature.SHA1/ECDSA", "SHA1withEC"); ++ put("Alg.Alias.Signature.SHA1withECDSA", "SHA1withEC"); //JCE Standard Name + + put("Signature.SHA256withEC", + "org.mozilla.jss.provider.java.security.JSSSignatureSpi$SHA256EC"); + put("Alg.Alias.Signature.SHA256/EC", "SHA256withEC"); + put("Alg.Alias.Signature.SHA-256/EC", "SHA256withEC"); ++ put("Alg.Alias.Signature.SHA256withECDSA", "SHA256withEC"); //JCE Standard Name + + put("Signature.SHA384withEC", + "org.mozilla.jss.provider.java.security.JSSSignatureSpi$SHA384EC"); + put("Alg.Alias.Signature.SHA384/EC", "SHA384withEC"); + put("Alg.Alias.Signature.SHA-384/EC", "SHA384withEC"); ++ put("Alg.Alias.Signature.SHA384withECDSA", "SHA384withEC"); //JCE Standard Name + + put("Signature.SHA512withEC", + "org.mozilla.jss.provider.java.security.JSSSignatureSpi$SHA512EC"); + put("Alg.Alias.Signature.SHA512/EC", "SHA512withEC"); + put("Alg.Alias.Signature.SHA-512/EC", "SHA512withEC"); ++ put("Alg.Alias.Signature.SHA512withECDSA", "SHA512withEC"); //JCE Standard Name + + ///////////////////////////////////////////////////////////// + // Message Digesting diff --git a/jss.spec b/jss.spec index c3e6e82..9df4c65 100644 --- a/jss.spec +++ b/jss.spec @@ -1,6 +1,6 @@ Name: jss Version: 4.4.2 -Release: 8%{?dist} +Release: 9%{?dist} Summary: Java Security Services (JSS) Group: System Environment/Libraries @@ -38,6 +38,9 @@ Patch3: jss-fix-PK11Store-getEncryptedPrivateKeyInfo-segfault.patch Patch4: jss-HMAC-unwrap-keywrap-FIPSMODE.patch Patch5: jss-SignatureAlgorithm.patch Patch6: jss-ObjectNotFoundException-message.patch +Patch7: jss-signature-correction.patch +Patch8: jss-standardize-ECC-algorithm-names.patch +Patch9: jss-fix-SignerInfo-version.patch %description Java Security Services (JSS) is a java native interface which provides a bridge @@ -61,6 +64,9 @@ pushd jss %patch4 -p1 %patch5 -p1 %patch6 -p1 +%patch7 -p1 +%patch8 -p1 +%patch9 -p1 popd %build @@ -153,6 +159,14 @@ rm -rf $RPM_BUILD_ROOT %{_javadocdir}/%{name}-%{version}/* %changelog +* Mon Jan 22 2018 Dogtag Team 4.4.2-9 +- Mozilla Bugzilla #1409867 - org.mozilla.jss.pkix.cms.SignerInfo incorrectly + producing signatures (especially for EC) (cfu,dstutzman) +- Mozilla Bugzilla #589158 - Add Sun's standard algorithm names for all ECC + signature types (cfu,dstutzman) +- Mozilla Bugzilla #386351 - SignerInfo class inserts wrong version # into + the resulting structure (cfu,dstutzman) + * Mon Jan 08 2018 Karsten Hopp - 4.4.2-8 - update build dependencies