Skip to content

Instantly share code, notes, and snippets.

/diff

Created November 19, 2014 13:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/077471026fa975186876 to your computer and use it in GitHub Desktop.
Save anonymous/077471026fa975186876 to your computer and use it in GitHub Desktop.
diff
#
##
# diffing platform/build
##
#
diff --git a/core/build_id.mk b/core/build_id.mk
index 73a3313..cf00cee 100644
--- a/core/build_id.mk
+++ b/core/build_id.mk
@@ -18,4 +18,4 @@
# (like "CRB01"). It must be a single word, and is
# capitalized by convention.
-export BUILD_ID=LRX21T
+export BUILD_ID=LRX21V
#
##
# diffing platform/external/chromium_org
##
#
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContents.java b/android_webview/java/src/org/chromium/android_webview/AwContents.java
index 7e64190..ec49dc0 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwContents.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java
@@ -20,6 +20,7 @@ import android.net.http.SslCertificate;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
+import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
@@ -52,6 +53,7 @@ import org.chromium.content.browser.ContentViewStatics;
import org.chromium.content.browser.LoadUrlParams;
import org.chromium.content.browser.NavigationHistory;
import org.chromium.content.browser.PageTransitionTypes;
+import org.chromium.content.browser.SmartClipProvider;
import org.chromium.content.common.CleanupReference;
import org.chromium.content_public.Referrer;
import org.chromium.content_public.browser.GestureStateListener;
@@ -77,7 +79,7 @@ import java.util.concurrent.Callable;
* continuous build & test in the open source SDK-based tree).
*/
@JNINamespace("android_webview")
-public class AwContents {
+public class AwContents implements SmartClipProvider {
private static final String TAG = "AwContents";
private static final String WEB_ARCHIVE_EXTENSION = ".mht";
@@ -2167,12 +2169,34 @@ public class AwContents {
return null;
}
+ @Override
public void extractSmartClipData(int x, int y, int width, int height) {
mContentViewCore.extractSmartClipData(x, y, width, height);
}
- public void setSmartClipDataListener(ContentViewCore.SmartClipDataListener listener) {
- mContentViewCore.setSmartClipDataListener(listener);
+ @Override
+ public void setSmartClipResultHandler(final Handler resultHandler) {
+ if (resultHandler == null) {
+ mContentViewCore.setSmartClipDataListener(null);
+ return;
+ }
+ mContentViewCore.setSmartClipDataListener(new ContentViewCore.SmartClipDataListener() {
+ public void onSmartClipDataExtracted(String text, String html, Rect clipRect) {
+ Bundle bundle = new Bundle();
+ bundle.putString("url", mContentViewCore.getWebContents().getVisibleUrl());
+ bundle.putString("title", mContentViewCore.getWebContents().getTitle());
+ bundle.putParcelable("rect", clipRect);
+ bundle.putString("text", text);
+ bundle.putString("html", html);
+ try {
+ Message msg = Message.obtain(resultHandler, 0);
+ msg.setData(bundle);
+ msg.sendToTarget();
+ } catch (Exception e) {
+ Log.e(TAG, "Error calling handler for smart clip data: ", e);
+ }
+ }
+ });
}
// --------------------------------------------------------------------------------------------
#
##
# diffing platform/frameworks/base
##
#
diff --git a/core/java/android/content/pm/Signature.java b/core/java/android/content/pm/Signature.java
index 7edf4b9..fdc54ae 100644
--- a/core/java/android/content/pm/Signature.java
+++ b/core/java/android/content/pm/Signature.java
@@ -22,12 +22,14 @@ import android.os.Parcelable;
import com.android.internal.util.ArrayUtils;
import java.io.ByteArrayInputStream;
+import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
import java.util.Arrays;
/**
@@ -252,4 +254,53 @@ public class Signature implements Parcelable {
return (a.length == b.length) && ArrayUtils.containsAll(a, b)
&& ArrayUtils.containsAll(b, a);
}
+
+ /**
+ * Test if given {@link Signature} sets are effectively equal. In rare
+ * cases, certificates can have slightly malformed encoding which causes
+ * exact-byte checks to fail.
+ * <p>
+ * To identify effective equality, we bounce the certificates through an
+ * decode/encode pass before doing the exact-byte check. To reduce attack
+ * surface area, we only allow a byte size delta of a few bytes.
+ *
+ * @throws CertificateException if the before/after length differs
+ * substantially, usually a signal of something fishy going on.
+ * @hide
+ */
+ public static boolean areEffectiveMatch(Signature[] a, Signature[] b)
+ throws CertificateException {
+ final CertificateFactory cf = CertificateFactory.getInstance("X.509");
+
+ final Signature[] aPrime = new Signature[a.length];
+ for (int i = 0; i < a.length; i++) {
+ aPrime[i] = bounce(cf, a[i]);
+ }
+ final Signature[] bPrime = new Signature[b.length];
+ for (int i = 0; i < b.length; i++) {
+ bPrime[i] = bounce(cf, b[i]);
+ }
+
+ return areExactMatch(aPrime, bPrime);
+ }
+
+ /**
+ * Bounce the given {@link Signature} through a decode/encode cycle.
+ *
+ * @throws CertificateException if the before/after length differs
+ * substantially, usually a signal of something fishy going on.
+ * @hide
+ */
+ public static Signature bounce(CertificateFactory cf, Signature s) throws CertificateException {
+ final InputStream is = new ByteArrayInputStream(s.mSignature);
+ final X509Certificate cert = (X509Certificate) cf.generateCertificate(is);
+ final Signature sPrime = new Signature(cert.getEncoded());
+
+ if (Math.abs(sPrime.mSignature.length - s.mSignature.length) > 2) {
+ throw new CertificateException("Bounced cert length looks fishy; before "
+ + s.mSignature.length + ", after " + sPrime.mSignature.length);
+ }
+
+ return sPrime;
+ }
}
diff --git a/core/tests/coretests/src/android/content/pm/SignatureTest.java b/core/tests/coretests/src/android/content/pm/SignatureTest.java
new file mode 100644
index 0000000..89d5997
--- /dev/null
+++ b/core/tests/coretests/src/android/content/pm/SignatureTest.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+import junit.framework.TestCase;
+
+public class SignatureTest extends TestCase {
+
+ /** Cert A with valid syntax */
+ private static final Signature A = new Signature("308201D33082013CA0030201020219373565373461363A31336534333439623635343A2D38303030300D06092A864886F70D01010505003017311530130603550403130C6269736F6E416E64726F6964301E170D3133303432343232323134345A170D3338303432353232323134345A3017311530130603550403130C6269736F6E416E64726F696430819F300D06092A864886F70D010101050003818D00308189028181009214CE08563B77FF3128D3A303254287301263A842D19D5D4EAF024EBEDF864F3802C215B2F3EA85432F3EFF1DB8F591B0854FA7C1C6E4A8A85132FA762CC2D12A8EBD34D8B15C241A91716577F03BB3D2AFFC24367AB1E5E03C387891E34E646E47FAD75B178C1FD077B9199B3ABA6D48E2464801F6592E98245124046E51A90203010001A317301530130603551D25040C300A06082B06010505070303300D06092A864886F70D0101050500038181000B71581EDDC20E8C18C1C140BEE72501A97E04CA12030C51D4C38767B6A9FB5155CF4858C565EF77E5E2C22687C1AAB04BBA2B81C9A73CFB8DE118B624094AAE43D8FC2D585D90839DAFA5033AF7B8C0DE27E6ADAE44C40508CE493E9C80F1F5DA9EC87ECA1844BAB12C83CC8EB5937E1BE36A42CD22086A826E00FB763CD577");
+ /** Cert A with malformed syntax */
+ private static final Signature M = new Signature("308201D43082013CA0030201020219373565373461363A31336534333439623635343A2D38303030300D06092A864886F70D01010505003017311530130603550403130C6269736F6E416E64726F6964301E170D3133303432343232323134345A170D3338303432353232323134345A3017311530130603550403130C6269736F6E416E64726F696430819F300D06092A864886F70D010101050003818D00308189028181009214CE08563B77FF3128D3A303254287301263A842D19D5D4EAF024EBEDF864F3802C215B2F3EA85432F3EFF1DB8F591B0854FA7C1C6E4A8A85132FA762CC2D12A8EBD34D8B15C241A91716577F03BB3D2AFFC24367AB1E5E03C387891E34E646E47FAD75B178C1FD077B9199B3ABA6D48E2464801F6592E98245124046E51A90203010001A317301530130603551D25040C300A06082B06010505070303300D06092A864886F70D010105050003820081000B71581EDDC20E8C18C1C140BEE72501A97E04CA12030C51D4C38767B6A9FB5155CF4858C565EF77E5E2C22687C1AAB04BBA2B81C9A73CFB8DE118B624094AAE43D8FC2D585D90839DAFA5033AF7B8C0DE27E6ADAE44C40508CE493E9C80F1F5DA9EC87ECA1844BAB12C83CC8EB5937E1BE36A42CD22086A826E00FB763CD577");
+ /** Cert B with valid syntax */
+ private static final Signature B = new Signature("308204a830820390a003020102020900a1573d0f45bea193300d06092a864886f70d0101050500308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d301e170d3131303931393138343232355a170d3339303230343138343232355a308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d30820120300d06092a864886f70d01010105000382010d00308201080282010100de1b51336afc909d8bcca5920fcdc8940578ec5c253898930e985481cfdea75ba6fc54b1f7bb492a03d98db471ab4200103a8314e60ee25fef6c8b83bc1b2b45b084874cffef148fa2001bb25c672b6beba50b7ac026b546da762ea223829a22b80ef286131f059d2c9b4ca71d54e515a8a3fd6bf5f12a2493dfc2619b337b032a7cf8bbd34b833f2b93aeab3d325549a93272093943bb59dfc0197ae4861ff514e019b73f5cf10023ad1a032adb4b9bbaeb4debecb4941d6a02381f1165e1ac884c1fca9525c5854dce2ad8ec839b8ce78442c16367efc07778a337d3ca2cdf9792ac722b95d67c345f1c00976ec372f02bfcbef0262cc512a6845e71cfea0d020103a381fc3081f9301d0603551d0e0416041478a0fc4517fb70ff52210df33c8d32290a44b2bb3081c90603551d230481c13081be801478a0fc4517fb70ff52210df33c8d32290a44b2bba1819aa48197308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d820900a1573d0f45bea193300c0603551d13040530030101ff300d06092a864886f70d01010505000382010100977302dfbf668d7c61841c9c78d2563bcda1b199e95e6275a799939981416909722713531157f3cdcfea94eea7bb79ca3ca972bd8058a36ad1919291df42d7190678d4ea47a4b9552c9dfb260e6d0d9129b44615cd641c1080580e8a990dd768c6ab500c3b964e185874e4105109d94c5bd8c405deb3cf0f7960a563bfab58169a956372167a7e2674a04c4f80015d8f7869a7a4139aecbbdca2abc294144ee01e4109f0e47a518363cf6e9bf41f7560e94bdd4a5d085234796b05c7a1389adfd489feec2a107955129d7991daa49afb3d327dc0dc4fe959789372b093a89c8dbfa41554f771c18015a6cb242a17e04d19d55d3b4664eae12caf2a11cd2b836e");
+
+ public void testExactlyEqual() throws Exception {
+ assertTrue(Signature.areExactMatch(asArray(A), asArray(A)));
+ assertTrue(Signature.areExactMatch(asArray(M), asArray(M)));
+
+ assertFalse(Signature.areExactMatch(asArray(A), asArray(B)));
+ assertFalse(Signature.areExactMatch(asArray(A), asArray(M)));
+ assertFalse(Signature.areExactMatch(asArray(M), asArray(A)));
+
+ assertTrue(Signature.areExactMatch(asArray(A, M), asArray(M, A)));
+ }
+
+ public void testEffectiveMatch() throws Exception {
+ assertTrue(Signature.areEffectiveMatch(asArray(A), asArray(A)));
+ assertTrue(Signature.areEffectiveMatch(asArray(M), asArray(M)));
+
+ assertFalse(Signature.areEffectiveMatch(asArray(A), asArray(B)));
+ assertTrue(Signature.areEffectiveMatch(asArray(A), asArray(M)));
+ assertTrue(Signature.areEffectiveMatch(asArray(M), asArray(A)));
+
+ assertTrue(Signature.areEffectiveMatch(asArray(A, M), asArray(M, A)));
+ assertTrue(Signature.areEffectiveMatch(asArray(A, B), asArray(M, B)));
+ assertFalse(Signature.areEffectiveMatch(asArray(A, M), asArray(A, B)));
+ }
+
+ private static Signature[] asArray(Signature... s) {
+ return s;
+ }
+}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index b79e157..3e1647e 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2860,6 +2860,38 @@ public class PackageManagerService extends IPackageManager.Stub {
return PackageManager.SIGNATURE_NO_MATCH;
}
+ private boolean isRecoverSignatureUpdateNeeded(PackageParser.Package scannedPkg) {
+ if (isExternal(scannedPkg)) {
+ return mSettings.isExternalDatabaseVersionOlderThan(
+ DatabaseVersion.SIGNATURE_MALFORMED_RECOVER);
+ } else {
+ return mSettings.isInternalDatabaseVersionOlderThan(
+ DatabaseVersion.SIGNATURE_MALFORMED_RECOVER);
+ }
+ }
+
+ private int compareSignaturesRecover(PackageSignatures existingSigs,
+ PackageParser.Package scannedPkg) {
+ if (!isRecoverSignatureUpdateNeeded(scannedPkg)) {
+ return PackageManager.SIGNATURE_NO_MATCH;
+ }
+
+ String msg = null;
+ try {
+ if (Signature.areEffectiveMatch(existingSigs.mSignatures, scannedPkg.mSignatures)) {
+ logCriticalInfo(Log.INFO, "Recovered effectively matching certificates for "
+ + scannedPkg.packageName);
+ return PackageManager.SIGNATURE_MATCH;
+ }
+ } catch (CertificateException e) {
+ msg = e.getMessage();
+ }
+
+ logCriticalInfo(Log.INFO,
+ "Failed to recover certificates for " + scannedPkg.packageName + ": " + msg);
+ return PackageManager.SIGNATURE_NO_MATCH;
+ }
+
@Override
public String[] getPackagesForUid(int uid) {
uid = UserHandle.getAppId(uid);
@@ -4148,7 +4180,8 @@ public class PackageManagerService extends IPackageManager.Stub {
if (ps != null
&& ps.codePath.equals(srcFile)
&& ps.timeStamp == srcFile.lastModified()
- && !isCompatSignatureUpdateNeeded(pkg)) {
+ && !isCompatSignatureUpdateNeeded(pkg)
+ && !isRecoverSignatureUpdateNeeded(pkg)) {
long mSigningKeySetId = ps.keySetData.getProperSigningKeySet();
if (ps.signatures.mSignatures != null
&& ps.signatures.mSignatures.length != 0
@@ -4423,6 +4456,10 @@ public class PackageManagerService extends IPackageManager.Stub {
== PackageManager.SIGNATURE_MATCH;
}
if (!match) {
+ match = compareSignaturesRecover(pkgSetting.signatures, pkg)
+ == PackageManager.SIGNATURE_MATCH;
+ }
+ if (!match) {
throw new PackageManagerException(INSTALL_FAILED_UPDATE_INCOMPATIBLE, "Package "
+ pkg.packageName + " signatures do not match the "
+ "previously installed version; ignoring!");
@@ -4439,6 +4476,10 @@ public class PackageManagerService extends IPackageManager.Stub {
== PackageManager.SIGNATURE_MATCH;
}
if (!match) {
+ match = compareSignaturesRecover(pkgSetting.sharedUser.signatures, pkg)
+ == PackageManager.SIGNATURE_MATCH;
+ }
+ if (!match) {
throw new PackageManagerException(INSTALL_FAILED_SHARED_USER_INCOMPATIBLE,
"Package " + pkg.packageName
+ " has no signatures that match those in shared user "
@@ -5386,6 +5427,9 @@ public class PackageManagerService extends IPackageManager.Stub {
if (!pkgSetting.keySetData.isUsingUpgradeKeySets() || pkgSetting.sharedUser != null) {
try {
verifySignaturesLP(pkgSetting, pkg);
+ // We just determined the app is signed correctly, so bring
+ // over the latest parsed certs.
+ pkgSetting.signatures.mSignatures = pkg.mSignatures;
} catch (PackageManagerException e) {
if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
throw e;
@@ -5418,7 +5462,8 @@ public class PackageManagerService extends IPackageManager.Stub {
+ pkg.packageName + " upgrade keys do not match the "
+ "previously installed version");
} else {
- // signatures may have changed as result of upgrade
+ // We just determined the app is signed correctly, so bring
+ // over the latest parsed certs.
pkgSetting.signatures.mSignatures = pkg.mSignatures;
}
}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 7de56c8..699adef 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -103,7 +103,7 @@ final class Settings {
* Note that care should be taken to make sure all database upgrades are
* idempotent.
*/
- private static final int CURRENT_DATABASE_VERSION = DatabaseVersion.SIGNATURE_END_ENTITY;
+ private static final int CURRENT_DATABASE_VERSION = DatabaseVersion.SIGNATURE_MALFORMED_RECOVER;
/**
* This class contains constants that can be referred to from upgrade code.
@@ -121,6 +121,14 @@ final class Settings {
* just the signing certificate.
*/
public static final int SIGNATURE_END_ENTITY = 2;
+
+ /**
+ * There was a window of time in
+ * {@link android.os.Build.VERSION_CODES#LOLLIPOP} where we persisted
+ * certificates after potentially mutating them. To switch back to the
+ * original untouched certificates, we need to force a collection pass.
+ */
+ public static final int SIGNATURE_MALFORMED_RECOVER = 3;
}
private static final boolean DEBUG_STOPPED = false;
#
##
# diffing platform/frameworks/webview
##
#
diff --git a/chromium/java/com/android/webview/chromium/WebViewChromium.java b/chromium/java/com/android/webview/chromium/WebViewChromium.java
index a485bd2..76a11ca 100644
--- a/chromium/java/com/android/webview/chromium/WebViewChromium.java
+++ b/chromium/java/com/android/webview/chromium/WebViewChromium.java
@@ -32,6 +32,7 @@ import android.net.http.SslCertificate;
import android.os.Build;
import android.os.Bundle;
import android.os.Looper;
+import android.os.Handler;
import android.os.Message;
import android.print.PrintDocumentAdapter;
import android.text.TextUtils;
@@ -71,6 +72,7 @@ import org.chromium.android_webview.AwSettings;
import org.chromium.android_webview.AwPrintDocumentAdapter;
import org.chromium.base.ThreadUtils;
import org.chromium.content.browser.LoadUrlParams;
+import org.chromium.content.browser.SmartClipProvider;
import org.chromium.net.NetworkChangeNotifier;
import java.io.BufferedWriter;
@@ -93,7 +95,7 @@ import java.util.Queue;
* and a small set of no-op deprecated APIs.
*/
class WebViewChromium implements WebViewProvider,
- WebViewProvider.ScrollDelegate, WebViewProvider.ViewDelegate {
+ WebViewProvider.ScrollDelegate, WebViewProvider.ViewDelegate, SmartClipProvider {
private class WebViewChromiumRunQueue {
public WebViewChromiumRunQueue() {
@@ -2246,4 +2248,19 @@ class WebViewChromium implements WebViewProvider,
return mWebViewPrivate.super_onHoverEvent(event);
}
}
+
+ // Implements SmartClipProvider
+ @Override
+ public void extractSmartClipData(int x, int y, int width, int height) {
+ checkThread();
+ mAwContents.extractSmartClipData(x, y, width, height);
+ }
+
+ // Implements SmartClipProvider
+ @Override
+ public void setSmartClipResultHandler(final Handler resultHandler) {
+ checkThread();
+ mAwContents.setSmartClipResultHandler(resultHandler);
+ }
+
}
diff --git a/chromium/proguard.flags b/chromium/proguard.flags
index 6401a8c..b19519f 100644
--- a/chromium/proguard.flags
+++ b/chromium/proguard.flags
@@ -80,6 +80,12 @@
*** startFinalizer(java.lang.Class,java.lang.Object);
}
+# Keep support framework support for SmartClip.
+-keep class com.android.webview.chromium.WebViewChromium {
+ public void extractSmartClipData(int,int,int,int);
+ public void setSmartClipResultHandler(android.os.Handler);
+}
+
# We need to explicitly keep classes and constructors referenced only in
# layout resources.
-keep class com.android.org.chromium.ui.ColorPickerAdvanced {
#
##
# diffing platform/libcore
##
#
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 d11c8dd..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
@@ -31,6 +31,7 @@ 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;
@@ -82,8 +83,10 @@ public class JarUtils {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
int i = 0;
for (org.apache.harmony.security.x509.Certificate encCert : encCerts) {
- final InputStream is = new ByteArrayInputStream(encCert.getEncoded());
- certs[i++] = (X509Certificate) cf.generateCertificate(is);
+ 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();
@@ -264,4 +267,22 @@ public class JarUtils {
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;
+ }
+ }
}
diff --git a/luni/src/main/java/org/apache/harmony/security/utils/WrappedX509Certificate.java b/luni/src/main/java/org/apache/harmony/security/utils/WrappedX509Certificate.java
new file mode 100644
index 0000000..2b09309
--- /dev/null
+++ b/luni/src/main/java/org/apache/harmony/security/utils/WrappedX509Certificate.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.security.utils;
+
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Principal;
+import java.security.PublicKey;
+import java.security.SignatureException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateNotYetValidException;
+import java.security.cert.X509Certificate;
+import java.util.Date;
+import java.util.Set;
+
+public class WrappedX509Certificate extends X509Certificate {
+ private final X509Certificate wrapped;
+
+ public WrappedX509Certificate(X509Certificate wrapped) {
+ this.wrapped = wrapped;
+ }
+
+ @Override
+ public Set<String> getCriticalExtensionOIDs() {
+ return wrapped.getCriticalExtensionOIDs();
+ }
+
+ @Override
+ public byte[] getExtensionValue(String oid) {
+ return wrapped.getExtensionValue(oid);
+ }
+
+ @Override
+ public Set<String> getNonCriticalExtensionOIDs() {
+ return wrapped.getNonCriticalExtensionOIDs();
+ }
+
+ @Override
+ public boolean hasUnsupportedCriticalExtension() {
+ return wrapped.hasUnsupportedCriticalExtension();
+ }
+
+ @Override
+ public void checkValidity() throws CertificateExpiredException,
+ CertificateNotYetValidException {
+ wrapped.checkValidity();
+ }
+
+ @Override
+ public void checkValidity(Date date) throws CertificateExpiredException,
+ CertificateNotYetValidException {
+ wrapped.checkValidity(date);
+ }
+
+ @Override
+ public int getVersion() {
+ return wrapped.getVersion();
+ }
+
+ @Override
+ public BigInteger getSerialNumber() {
+ return wrapped.getSerialNumber();
+ }
+
+ @Override
+ public Principal getIssuerDN() {
+ return wrapped.getIssuerDN();
+ }
+
+ @Override
+ public Principal getSubjectDN() {
+ return wrapped.getSubjectDN();
+ }
+
+ @Override
+ public Date getNotBefore() {
+ return wrapped.getNotBefore();
+ }
+
+ @Override
+ public Date getNotAfter() {
+ return wrapped.getNotAfter();
+ }
+
+ @Override
+ public byte[] getTBSCertificate() throws CertificateEncodingException {
+ return wrapped.getTBSCertificate();
+ }
+
+ @Override
+ public byte[] getSignature() {
+ return wrapped.getSignature();
+ }
+
+ @Override
+ public String getSigAlgName() {
+ return wrapped.getSigAlgName();
+ }
+
+ @Override
+ public String getSigAlgOID() {
+ return wrapped.getSigAlgOID();
+ }
+
+ @Override
+ public byte[] getSigAlgParams() {
+ return wrapped.getSigAlgParams();
+ }
+
+ @Override
+ public boolean[] getIssuerUniqueID() {
+ return wrapped.getIssuerUniqueID();
+ }
+
+ @Override
+ public boolean[] getSubjectUniqueID() {
+ return wrapped.getSubjectUniqueID();
+ }
+
+ @Override
+ public boolean[] getKeyUsage() {
+ return wrapped.getKeyUsage();
+ }
+
+ @Override
+ public int getBasicConstraints() {
+ return wrapped.getBasicConstraints();
+ }
+
+ @Override
+ public byte[] getEncoded() throws CertificateEncodingException {
+ return wrapped.getEncoded();
+ }
+
+ @Override
+ public void verify(PublicKey key) throws CertificateException, NoSuchAlgorithmException,
+ InvalidKeyException, NoSuchProviderException, SignatureException {
+ wrapped.verify(key);
+ }
+
+ @Override
+ public void verify(PublicKey key, String sigProvider) throws CertificateException,
+ NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException,
+ SignatureException {
+ verify(key, sigProvider);
+ }
+
+ @Override
+ public String toString() {
+ return wrapped.toString();
+ }
+
+ @Override
+ public PublicKey getPublicKey() {
+ return wrapped.getPublicKey();
+ }
+}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment