summaryrefslogtreecommitdiffstats
path: root/luni/src/main/java/org/apache/harmony/security/utils/JarUtils.java
diff options
context:
space:
mode:
Diffstat (limited to 'luni/src/main/java/org/apache/harmony/security/utils/JarUtils.java')
-rw-r--r--luni/src/main/java/org/apache/harmony/security/utils/JarUtils.java105
1 files changed, 54 insertions, 51 deletions
diff --git a/luni/src/main/java/org/apache/harmony/security/utils/JarUtils.java b/luni/src/main/java/org/apache/harmony/security/utils/JarUtils.java
index 135394d..e7f3596 100644
--- a/luni/src/main/java/org/apache/harmony/security/utils/JarUtils.java
+++ b/luni/src/main/java/org/apache/harmony/security/utils/JarUtils.java
@@ -21,6 +21,7 @@
*/
package org.apache.harmony.security.utils;
+import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
@@ -30,10 +31,12 @@ import java.security.NoSuchAlgorithmException;
import java.security.Principal;
import java.security.Signature;
import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
-import java.util.LinkedList;
import java.util.List;
import javax.security.auth.x500.X500Principal;
@@ -42,7 +45,6 @@ import org.apache.harmony.security.asn1.BerInputStream;
import org.apache.harmony.security.pkcs7.ContentInfo;
import org.apache.harmony.security.pkcs7.SignedData;
import org.apache.harmony.security.pkcs7.SignerInfo;
-import org.apache.harmony.security.provider.cert.X509CertImpl;
import org.apache.harmony.security.x501.AttributeTypeAndValue;
public class JarUtils {
@@ -53,27 +55,18 @@ public class JarUtils {
new int[] {1, 2, 840, 113549, 1, 9, 4};
/**
- * @see #verifySignature(InputStream, InputStream, boolean)
- */
- public static Certificate[] verifySignature(InputStream signature, InputStream signatureBlock)
- throws IOException, GeneralSecurityException {
- return verifySignature(signature, signatureBlock, false);
- }
-
- /**
* This method handle all the work with PKCS7, ASN1 encoding, signature verifying,
* and certification path building.
* See also PKCS #7: Cryptographic Message Syntax Standard:
* http://www.ietf.org/rfc/rfc2315.txt
* @param signature - the input stream of signature file to be verified
* @param signatureBlock - the input stream of corresponding signature block file
- * @param chainCheck - whether to validate certificate chain signatures
* @return array of certificates used to verify the signature file
* @throws IOException - if some errors occurs during reading from the stream
* @throws GeneralSecurityException - if signature verification process fails
*/
public static Certificate[] verifySignature(InputStream signature, InputStream
- signatureBlock, boolean chainCheck) throws IOException, GeneralSecurityException {
+ signatureBlock) throws IOException, GeneralSecurityException {
BerInputStream bis = new BerInputStream(signatureBlock);
ContentInfo info = (ContentInfo)ContentInfo.ASN1.decode(bis);
@@ -87,9 +80,13 @@ public class JarUtils {
return null;
}
X509Certificate[] certs = new X509Certificate[encCerts.size()];
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
int i = 0;
for (org.apache.harmony.security.x509.Certificate encCert : encCerts) {
- certs[i++] = new X509CertImpl(encCert);
+ final byte[] encoded = encCert.getEncoded();
+ final InputStream is = new ByteArrayInputStream(encoded);
+ certs[i++] = new VerbatimX509Certificate((X509Certificate) cf.generateCertificate(is),
+ encoded);
}
List<SignerInfo> sigInfos = signedData.getSignerInfos();
@@ -131,17 +128,16 @@ public class JarUtils {
String alg = null;
Signature sig = null;
- if (daOid != null && deaOid != null) {
- alg = daOid + "with" + deaOid;
+ if (deaOid != null) {
+ alg = deaOid;
try {
sig = Signature.getInstance(alg);
} catch (NoSuchAlgorithmException e) {
}
- // Try to convert to names instead of OID.
- if (sig == null) {
- final String deaName = sigInfo.getDigestEncryptionAlgorithmName();
- alg = daName + "with" + deaName;
+ final String deaName = sigInfo.getDigestEncryptionAlgorithmName();
+ if (sig == null && deaName != null) {
+ alg = deaName;
try {
sig = Signature.getInstance(alg);
} catch (NoSuchAlgorithmException e) {
@@ -149,19 +145,17 @@ public class JarUtils {
}
}
- /*
- * TODO figure out the case in which we'd only use digestAlgorithm and
- * add a test for it.
- */
- if (sig == null && daOid != null) {
- alg = daOid;
+ if (sig == null && daOid != null && deaOid != null) {
+ alg = daOid + "with" + deaOid;
try {
sig = Signature.getInstance(alg);
} catch (NoSuchAlgorithmException e) {
}
- if (sig == null && daName != null) {
- alg = daName;
+ // Try to convert to names instead of OID.
+ if (sig == null) {
+ final String deaName = sigInfo.getDigestEncryptionAlgorithmName();
+ alg = daName + "with" + deaName;
try {
sig = Signature.getInstance(alg);
} catch (NoSuchAlgorithmException e) {
@@ -232,54 +226,63 @@ public class JarUtils {
throw new SecurityException("Incorrect signature");
}
- return createChain(certs[issuerSertIndex], certs, chainCheck);
+ return createChain(certs[issuerSertIndex], certs);
}
- private static X509Certificate[] createChain(X509Certificate signer,
- X509Certificate[] candidates, boolean chainCheck) {
- LinkedList chain = new LinkedList();
- chain.add(0, signer);
+ private static X509Certificate[] createChain(X509Certificate signer,
+ X509Certificate[] candidates) {
+ Principal issuer = signer.getIssuerDN();
// Signer is self-signed
- if (signer.getSubjectDN().equals(signer.getIssuerDN())){
- return (X509Certificate[])chain.toArray(new X509Certificate[1]);
+ if (signer.getSubjectDN().equals(issuer)) {
+ return new X509Certificate[] { signer };
}
- Principal issuer = signer.getIssuerDN();
+ ArrayList<X509Certificate> chain = new ArrayList<X509Certificate>(candidates.length + 1);
+ chain.add(0, signer);
+
X509Certificate issuerCert;
- X509Certificate subjectCert = signer;
int count = 1;
while (true) {
- issuerCert = findCert(issuer, candidates, subjectCert, chainCheck);
- if( issuerCert == null) {
+ issuerCert = findCert(issuer, candidates);
+ if (issuerCert == null) {
break;
}
chain.add(issuerCert);
count++;
- if (issuerCert.getSubjectDN().equals(issuerCert.getIssuerDN())) {
+ issuer = issuerCert.getIssuerDN();
+ if (issuerCert.getSubjectDN().equals(issuer)) {
break;
}
- issuer = issuerCert.getIssuerDN();
- subjectCert = issuerCert;
}
- return (X509Certificate[])chain.toArray(new X509Certificate[count]);
+ return chain.toArray(new X509Certificate[count]);
}
- private static X509Certificate findCert(Principal issuer, X509Certificate[] candidates,
- X509Certificate subjectCert, boolean chainCheck) {
+ private static X509Certificate findCert(Principal issuer, X509Certificate[] candidates) {
for (int i = 0; i < candidates.length; i++) {
if (issuer.equals(candidates[i].getSubjectDN())) {
- if (chainCheck) {
- try {
- subjectCert.verify(candidates[i].getPublicKey());
- } catch (Exception e) {
- continue;
- }
- }
return candidates[i];
}
}
return null;
}
+ /**
+ * For legacy reasons we need to return exactly the original encoded
+ * certificate bytes, instead of letting the underlying implementation have
+ * a shot at re-encoding the data.
+ */
+ private static class VerbatimX509Certificate extends WrappedX509Certificate {
+ private byte[] encodedVerbatim;
+
+ public VerbatimX509Certificate(X509Certificate wrapped, byte[] encodedVerbatim) {
+ super(wrapped);
+ this.encodedVerbatim = encodedVerbatim;
+ }
+
+ @Override
+ public byte[] getEncoded() throws CertificateEncodingException {
+ return encodedVerbatim;
+ }
+ }
}