diff options
author | Kenny Root <kroot@google.com> | 2014-04-18 18:10:49 +0000 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2014-04-18 18:10:49 +0000 |
commit | 6640b107e33042d6c7445d88119c92bd020cdc22 (patch) | |
tree | b0a132593a6912b03ed42c9f9a89636967fbdbfc /luni/src | |
parent | 668ba674e07f6771139e2756022297e65f03e7d0 (diff) | |
parent | f8986a989759c43c155ae64f9a3b36f670602521 (diff) | |
download | libcore-6640b107e33042d6c7445d88119c92bd020cdc22.zip libcore-6640b107e33042d6c7445d88119c92bd020cdc22.tar.gz libcore-6640b107e33042d6c7445d88119c92bd020cdc22.tar.bz2 |
am f8986a98: Add API to check certificate chain signatures
* commit 'f8986a989759c43c155ae64f9a3b36f670602521':
Add API to check certificate chain signatures
Diffstat (limited to 'luni/src')
-rw-r--r-- | luni/src/main/java/java/util/jar/JarFile.java | 24 | ||||
-rw-r--r-- | luni/src/main/java/java/util/jar/JarVerifier.java | 18 | ||||
-rw-r--r-- | luni/src/main/java/org/apache/harmony/security/utils/JarUtils.java | 35 |
3 files changed, 66 insertions, 11 deletions
diff --git a/luni/src/main/java/java/util/jar/JarFile.java b/luni/src/main/java/java/util/jar/JarFile.java index e129e82..494f5d2 100644 --- a/luni/src/main/java/java/util/jar/JarFile.java +++ b/luni/src/main/java/java/util/jar/JarFile.java @@ -184,9 +184,19 @@ public class JarFile extends ZipFile { * If the file cannot be read. */ public JarFile(File file, boolean verify, int mode) throws IOException { + this(file, verify, mode, false); + } + + /** + * See previous constructor for other parameter definitions. + * @param chainCheck + * whether or not to check certificate chain signatures + * @hide + */ + public JarFile(File file, boolean verify, int mode, boolean chainCheck) throws IOException { super(file, mode); if (verify) { - verifier = new JarVerifier(file.getPath()); + verifier = new JarVerifier(file.getPath(), chainCheck); } readMetaEntries(); } @@ -216,9 +226,19 @@ public class JarFile extends ZipFile { * If file cannot be opened or read. */ public JarFile(String filename, boolean verify) throws IOException { + this(filename, verify, false); + } + + /** + * See previous constructor for other parameter definitions. + * @param chainCheck + * whether or not to check certificate chain signatures + * @hide + */ + public JarFile(String filename, boolean verify, boolean chainCheck) throws IOException { super(filename); if (verify) { - verifier = new JarVerifier(filename); + verifier = new JarVerifier(filename, chainCheck); } readMetaEntries(); } diff --git a/luni/src/main/java/java/util/jar/JarVerifier.java b/luni/src/main/java/java/util/jar/JarVerifier.java index ec0e088..640f13c 100644 --- a/luni/src/main/java/java/util/jar/JarVerifier.java +++ b/luni/src/main/java/java/util/jar/JarVerifier.java @@ -68,6 +68,9 @@ class JarVerifier { int mainAttributesEnd; + /** Whether or not to check certificate chain signatures. */ + private final boolean chainCheck; + /** * Stores and a hash and a message digest and verifies that massage digest * matches the hash. @@ -137,13 +140,23 @@ class JarVerifier { } /** + * Convenience constructor for backward compatibility. + */ + JarVerifier(String name) { + this(name, false); + } + + /** * Constructs and returns a new instance of {@code JarVerifier}. * * @param name * the name of the JAR file being verified. + * @param chainCheck + * whether to check the certificate chain signatures */ - JarVerifier(String name) { + JarVerifier(String name, boolean chainCheck) { jarName = name; + this.chainCheck = chainCheck; } /** @@ -288,7 +301,8 @@ class JarVerifier { try { Certificate[] signerCertChain = JarUtils.verifySignature( new ByteArrayInputStream(sfBytes), - new ByteArrayInputStream(sBlockBytes)); + new ByteArrayInputStream(sBlockBytes), + chainCheck); /* * Recursive call in loading security provider related class which * is in a signed JAR. 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 f6efb8a..4b03937 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 @@ -52,18 +52,27 @@ 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) throws IOException, GeneralSecurityException { + signatureBlock, boolean chainCheck) throws IOException, GeneralSecurityException { BerInputStream bis = new BerInputStream(signatureBlock); ContentInfo info = (ContentInfo)ContentInfo.ASN1.decode(bis); @@ -171,10 +180,11 @@ public class JarUtils { throw new SecurityException("Incorrect signature"); } - return createChain(certs[issuerSertIndex], certs); + return createChain(certs[issuerSertIndex], certs, chainCheck); } - private static X509Certificate[] createChain(X509Certificate signer, X509Certificate[] candidates) { + private static X509Certificate[] createChain(X509Certificate signer, + X509Certificate[] candidates, boolean chainCheck) { LinkedList chain = new LinkedList(); chain.add(0, signer); @@ -184,13 +194,16 @@ public class JarUtils { } Principal issuer = signer.getIssuerDN(); - X509Certificate issuerCert; + X509Certificate issuerCert = null; + X509Certificate subjectCert = signer; int count = 1; while (true) { - issuerCert = findCert(issuer, candidates); - if( issuerCert == null) { + X509Certificate newIssuerCert = findCert(issuer, candidates, subjectCert, chainCheck); + if (newIssuerCert == null) { break; } + subjectCert = issuerCert; + issuerCert = newIssuerCert; chain.add(issuerCert); count++; if (issuerCert.getSubjectDN().equals(issuerCert.getIssuerDN())) { @@ -201,9 +214,17 @@ public class JarUtils { return (X509Certificate[])chain.toArray(new X509Certificate[count]); } - private static X509Certificate findCert(Principal issuer, X509Certificate[] candidates) { + private static X509Certificate findCert(Principal issuer, X509Certificate[] candidates, + X509Certificate subjectCert, boolean chainCheck) { 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]; } } |