diff options
author | Kenny Root <kroot@google.com> | 2014-11-07 14:35:33 -0800 |
---|---|---|
committer | Kenny Root <kroot@google.com> | 2014-11-10 10:04:15 -0800 |
commit | 00bf89dd858de6c7eaca555210ba429a89193722 (patch) | |
tree | 244a6e9135de55888860d0e9c83a45a785c7fe70 | |
parent | c46775d1a134eb1bf55557e33d34c732c0520660 (diff) | |
download | libcore-00bf89dd858de6c7eaca555210ba429a89193722.zip libcore-00bf89dd858de6c7eaca555210ba429a89193722.tar.gz libcore-00bf89dd858de6c7eaca555210ba429a89193722.tar.bz2 |
Switch order of digest and digest encryption algorithm
Sometimes "digest encryption algorithm" would be "RSA" which would match
a Signature provider, but its default setup would be whatever the
provider chose. This works fine with newer algorithms that have a
specific OID for their signature format (e.g., ECDSA and SHA256), but
not with algorithms that just have a generic OID for all possible uses
(e.g., RSA). Stock Android never hits this problem, because nothing
registers a "Signature.RSA" provider, but Spongycastle does so using
JarURLClassLoader after inserting Spongycastle causes a problem.
Flip the order of tries to make this work more uniformly with more JAR
and provider combinations.
(cherry picked from commit b1da6d3df5f9cce6e6d77c63599eba62edb465d6)
Bug: 17790692
Bug: https://code.google.com/p/android/issues/detail?id=68562
Change-Id: I3bb07ea25d7bf1d55fa2466b204594179ac38932
-rw-r--r-- | harmony-tests/src/test/java/org/apache/harmony/tests/java/util/jar/JarFileTest.java | 77 | ||||
-rw-r--r-- | luni/src/main/java/org/apache/harmony/security/utils/JarUtils.java | 19 |
2 files changed, 86 insertions, 10 deletions
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/jar/JarFileTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/jar/JarFileTest.java index d5d8191..f55829d 100644 --- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/jar/JarFileTest.java +++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/jar/JarFileTest.java @@ -24,7 +24,15 @@ import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.security.CodeSigner; +import java.security.InvalidKeyException; +import java.security.InvalidParameterException; import java.security.Permission; +import java.security.PrivateKey; +import java.security.Provider; +import java.security.PublicKey; +import java.security.Security; +import java.security.SignatureException; +import java.security.SignatureSpi; import java.security.cert.Certificate; import java.security.cert.X509Certificate; import java.util.Arrays; @@ -1014,4 +1022,73 @@ public class JarFileTest extends TestCase { res = jarFile.getInputStream(zipEntry).read(); assertEquals("Wrong length of empty jar entry", -1, res); } + + public void testJarFile_BadSignatureProvider_Success() throws Exception { + Security.insertProviderAt(new JarFileBadProvider(), 1); + try { + // Needs a JAR with "RSA" as digest encryption algorithm + checkSignedJar(jarName6); + } finally { + Security.removeProvider(JarFileBadProvider.NAME); + } + } + + public static class JarFileBadProvider extends Provider { + public static final String NAME = "JarFileBadProvider"; + + public JarFileBadProvider() { + super(NAME, 1.0, "Bad provider for JarFileTest"); + + put("Signature.RSA", NotReallyASignature.class.getName()); + } + + /** + * This should never be instantiated, so everything throws an exception. + */ + public static class NotReallyASignature extends SignatureSpi { + @Override + protected void engineInitVerify(PublicKey publicKey) throws InvalidKeyException { + fail("Should not call this provider"); + } + + @Override + protected void engineInitSign(PrivateKey privateKey) throws InvalidKeyException { + fail("Should not call this provider"); + } + + @Override + protected void engineUpdate(byte b) throws SignatureException { + fail("Should not call this provider"); + } + + @Override + protected void engineUpdate(byte[] b, int off, int len) throws SignatureException { + fail("Should not call this provider"); + } + + @Override + protected byte[] engineSign() throws SignatureException { + fail("Should not call this provider"); + return null; + } + + @Override + protected boolean engineVerify(byte[] sigBytes) throws SignatureException { + fail("Should not call this provider"); + return false; + } + + @Override + protected void engineSetParameter(String param, Object value) + throws InvalidParameterException { + fail("Should not call this provider"); + } + + @Override + protected Object engineGetParameter(String param) throws InvalidParameterException { + fail("Should not call this provider"); + return null; + } + } + } } 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 e7f3596..5755dc2 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 @@ -124,20 +124,21 @@ public class JarUtils { final String daOid = sigInfo.getDigestAlgorithm(); final String daName = sigInfo.getDigestAlgorithmName(); final String deaOid = sigInfo.getDigestEncryptionAlgorithm(); + final String deaName = sigInfo.getDigestEncryptionAlgorithmName(); String alg = null; Signature sig = null; - if (deaOid != null) { - alg = deaOid; + if (daOid != null && deaOid != null) { + alg = daOid + "with" + deaOid; try { sig = Signature.getInstance(alg); } catch (NoSuchAlgorithmException e) { } - final String deaName = sigInfo.getDigestEncryptionAlgorithmName(); - if (sig == null && deaName != null) { - alg = deaName; + // Try to convert to names instead of OID. + if (sig == null && daName != null && deaName != null) { + alg = daName + "with" + deaName; try { sig = Signature.getInstance(alg); } catch (NoSuchAlgorithmException e) { @@ -145,17 +146,15 @@ public class JarUtils { } } - if (sig == null && daOid != null && deaOid != null) { - alg = daOid + "with" + deaOid; + if (sig == null && 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; + alg = deaName; try { sig = Signature.getInstance(alg); } catch (NoSuchAlgorithmException e) { |