diff options
author | Michael Groover <mpgroover@google.com> | 2022-05-06 17:05:31 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2022-05-06 17:05:31 +0000 |
commit | 14f49463152da71c86926ec832c066ba0b8108ea (patch) | |
tree | 14c963da1fec0a62377183704ae44846928381c2 | |
parent | aa8ad504730b6b4704744a5a1aa3f0d0c53941e3 (diff) | |
parent | 495c7bb224dd39a2c2318b6e953ed12b589c5e37 (diff) | |
download | apksig-14f49463152da71c86926ec832c066ba0b8108ea.tar.gz |
Merge "Add timestamp attribute to source stamp block" into tm-dev am: 495c7bb224
Original change: https://googleplex-android-review.googlesource.com/c/platform/tools/apksig/+/18152826
Change-Id: Iaa640cd3972b326efaf6bfe6d56f263974a9a78f
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
17 files changed, 319 insertions, 1 deletions
diff --git a/src/main/java/com/android/apksig/ApkVerificationIssue.java b/src/main/java/com/android/apksig/ApkVerificationIssue.java index 2aa9d0b..fa2b7aa 100644 --- a/src/main/java/com/android/apksig/ApkVerificationIssue.java +++ b/src/main/java/com/android/apksig/ApkVerificationIssue.java @@ -116,6 +116,8 @@ public class ApkVerificationIssue { public static final int JAR_SIG_NO_SIGNATURES = 36; /** An exception was encountered when parsing the V1 / jar signer in the signature block. */ public static final int JAR_SIG_PARSE_EXCEPTION = 37; + /** The source stamp timestamp attribute has an invalid value. */ + public static final int SOURCE_STAMP_INVALID_TIMESTAMP = 38; private final int mIssueId; private final String mFormat; diff --git a/src/main/java/com/android/apksig/ApkVerifier.java b/src/main/java/com/android/apksig/ApkVerifier.java index 1613c26..fc28864 100644 --- a/src/main/java/com/android/apksig/ApkVerifier.java +++ b/src/main/java/com/android/apksig/ApkVerifier.java @@ -1767,6 +1767,8 @@ public class ApkVerifier { private final SourceStampVerificationStatus mSourceStampVerificationStatus; + private final long mTimestamp; + private SourceStampInfo(ApkSignerInfo result) { mCertificates = result.certs; mCertificateLineage = result.certificateLineage; @@ -1780,6 +1782,7 @@ public class ApkVerifier { mSourceStampVerificationStatus = SourceStampVerificationStatus.STAMP_VERIFICATION_FAILED; } + mTimestamp = result.timestamp; } SourceStampInfo(SourceStampVerificationStatus sourceStampVerificationStatus) { @@ -1788,6 +1791,7 @@ public class ApkVerifier { mErrors = Collections.emptyList(); mWarnings = Collections.emptyList(); mSourceStampVerificationStatus = sourceStampVerificationStatus; + mTimestamp = 0; } /** @@ -1827,6 +1831,14 @@ public class ApkVerifier { public SourceStampVerificationStatus getSourceStampVerificationStatus() { return mSourceStampVerificationStatus; } + + /** + * Returns the epoch timestamp in seconds representing the time this source stamp block + * was signed, or 0 if the timestamp is not available. + */ + public long getTimestampEpochSeconds() { + return mTimestamp; + } } } @@ -3000,6 +3012,16 @@ public class ApkVerifier { + "contains a proof-of-rotation record with signature(s) that did not verify."), /** + * The source stamp timestamp attribute has an invalid value (<= 0). + * <ul> + * <li>Parameter 1: The invalid timestamp value. + * </ul> + */ + SOURCE_STAMP_INVALID_TIMESTAMP( + "The source stamp" + + " timestamp attribute has an invalid value: %1$d"), + + /** * The APK could not be properly parsed due to a ZIP or APK format exception. * <ul> * <li>Parameter 1: The {@code Exception} caught when attempting to parse the APK. @@ -3295,6 +3317,8 @@ public class ApkVerifier { Issue.JAR_SIG_NO_SIGNATURES); sVerificationIssueIdToIssue.put(ApkVerificationIssue.JAR_SIG_PARSE_EXCEPTION, Issue.JAR_SIG_PARSE_EXCEPTION); + sVerificationIssueIdToIssue.put(ApkVerificationIssue.SOURCE_STAMP_INVALID_TIMESTAMP, + Issue.SOURCE_STAMP_INVALID_TIMESTAMP); } /** diff --git a/src/main/java/com/android/apksig/SourceStampVerifier.java b/src/main/java/com/android/apksig/SourceStampVerifier.java index 587cbd3..b155341 100644 --- a/src/main/java/com/android/apksig/SourceStampVerifier.java +++ b/src/main/java/com/android/apksig/SourceStampVerifier.java @@ -730,6 +730,8 @@ public class SourceStampVerifier { private final List<ApkVerificationIssue> mErrors = new ArrayList<>(); private final List<ApkVerificationIssue> mWarnings = new ArrayList<>(); + private final long mTimestamp; + /* * Since this utility is intended just to verify the source stamp, and the source stamp * currently only logs warnings to prevent failing the APK signature verification, treat @@ -744,6 +746,7 @@ public class SourceStampVerifier { mCertificateLineage = result.certificateLineage; mErrors.addAll(result.getErrors()); mWarnings.addAll(result.getWarnings()); + mTimestamp = result.timestamp; } /** @@ -794,6 +797,14 @@ public class SourceStampVerifier { public List<ApkVerificationIssue> getWarnings() { return mWarnings; } + + /** + * Returns the epoch timestamp in seconds representing the time this source stamp block + * was signed, or 0 if the timestamp is not available. + */ + public long getTimestampEpochSeconds() { + return mTimestamp; + } } } diff --git a/src/main/java/com/android/apksig/internal/apk/ApkSignerInfo.java b/src/main/java/com/android/apksig/internal/apk/ApkSignerInfo.java index e0ea365..12e54d0 100644 --- a/src/main/java/com/android/apksig/internal/apk/ApkSignerInfo.java +++ b/src/main/java/com/android/apksig/internal/apk/ApkSignerInfo.java @@ -27,6 +27,7 @@ import java.util.List; */ public class ApkSignerInfo { public int index; + public long timestamp; public List<X509Certificate> certs = new ArrayList<>(); public List<X509Certificate> certificateLineage = new ArrayList<>(); diff --git a/src/main/java/com/android/apksig/internal/apk/stamp/SourceStampConstants.java b/src/main/java/com/android/apksig/internal/apk/stamp/SourceStampConstants.java index 465fbb0..2a949ad 100644 --- a/src/main/java/com/android/apksig/internal/apk/stamp/SourceStampConstants.java +++ b/src/main/java/com/android/apksig/internal/apk/stamp/SourceStampConstants.java @@ -24,4 +24,11 @@ public class SourceStampConstants { public static final int V2_SOURCE_STAMP_BLOCK_ID = 0x6dff800d; public static final String SOURCE_STAMP_CERTIFICATE_HASH_ZIP_ENTRY_NAME = "stamp-cert-sha256"; public static final int PROOF_OF_ROTATION_ATTR_ID = 0x9d6303f7; + /** + * The source stamp timestamp attribute value is an 8-byte little-endian encoded long + * representing the epoch time in seconds when the stamp block was signed. The first 8 bytes + * of the attribute value buffer will be used to read the timestamp, and any additional buffer + * space will be ignored. + */ + public static final int STAMP_TIME_ATTR_ID = 0xe43c5946; } diff --git a/src/main/java/com/android/apksig/internal/apk/stamp/SourceStampVerifier.java b/src/main/java/com/android/apksig/internal/apk/stamp/SourceStampVerifier.java index 59fa791..aace413 100644 --- a/src/main/java/com/android/apksig/internal/apk/stamp/SourceStampVerifier.java +++ b/src/main/java/com/android/apksig/internal/apk/stamp/SourceStampVerifier.java @@ -318,6 +318,15 @@ class SourceStampVerifier { byte[] value = ByteBufferUtils.toByteArray(attribute); if (id == SourceStampConstants.PROOF_OF_ROTATION_ATTR_ID) { readStampCertificateLineage(value, sourceStampCertificate, result); + } else if (id == SourceStampConstants.STAMP_TIME_ATTR_ID) { + long timestamp = ByteBuffer.wrap(value).order( + ByteOrder.LITTLE_ENDIAN).getLong(); + if (timestamp > 0) { + result.timestamp = timestamp; + } else { + result.addWarning(ApkVerificationIssue.SOURCE_STAMP_INVALID_TIMESTAMP, + timestamp); + } } else { result.addWarning(ApkVerificationIssue.SOURCE_STAMP_UNKNOWN_ATTRIBUTE, id); } diff --git a/src/main/java/com/android/apksig/internal/apk/stamp/V2SourceStampSigner.java b/src/main/java/com/android/apksig/internal/apk/stamp/V2SourceStampSigner.java index 1c1570a..9c00a88 100644 --- a/src/main/java/com/android/apksig/internal/apk/stamp/V2SourceStampSigner.java +++ b/src/main/java/com/android/apksig/internal/apk/stamp/V2SourceStampSigner.java @@ -35,6 +35,7 @@ import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.SignatureException; import java.security.cert.CertificateEncodingException; +import java.time.Instant; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -202,6 +203,22 @@ public abstract class V2SourceStampSigner { private static Map<Integer, byte[]> generateStampAttributes(SigningCertificateLineage lineage) { HashMap<Integer, byte[]> stampAttributes = new HashMap<>(); + + // Write the current epoch time as the timestamp for the source stamp. + long timestamp = Instant.now().getEpochSecond(); + if (timestamp > 0) { + ByteBuffer attributeBuffer = ByteBuffer.allocate(8); + attributeBuffer.order(ByteOrder.LITTLE_ENDIAN); + attributeBuffer.putLong(timestamp); + stampAttributes.put(SourceStampConstants.STAMP_TIME_ATTR_ID, attributeBuffer.array()); + } else { + // The epoch time should never be <= 0, and since security decisions can potentially + // be made based on the value in the timestamp, throw an Exception to ensure the issues + // with the environment are resolved before allowing the signing. + throw new IllegalStateException( + "Received an invalid value from Instant#getTimestamp: " + timestamp); + } + if (lineage != null) { stampAttributes.put(SourceStampConstants.PROOF_OF_ROTATION_ATTR_ID, lineage.encodeSigningCertificateLineage()); diff --git a/src/test/java/com/android/apksig/ApkSignerTest.java b/src/test/java/com/android/apksig/ApkSignerTest.java index 9004d80..9740d75 100644 --- a/src/test/java/com/android/apksig/ApkSignerTest.java +++ b/src/test/java/com/android/apksig/ApkSignerTest.java @@ -51,7 +51,6 @@ import com.android.apksig.zip.ZipFormatException; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; @@ -1999,6 +1998,31 @@ public class ApkSignerTest { SECOND_RSA_2048_SIGNER_RESOURCE_NAME); } + @Test + public void testSourceStampTimestamp_signWithSourceStamp_validTimestampValue() + throws Exception { + // Source stamps should include a timestamp attribute with the epoch time the stamp block + // was signed. This test verifies a standard signing with a source stamp includes a valid + // value for the source stamp timestamp attribute. + ApkSigner.SignerConfig rsa2048SignerConfig = getDefaultSignerConfigFromResources( + FIRST_RSA_2048_SIGNER_RESOURCE_NAME); + List<ApkSigner.SignerConfig> ecP256SignerConfig = Collections.singletonList( + getDefaultSignerConfigFromResources(EC_P256_SIGNER_RESOURCE_NAME)); + + File signedApk = sign("original.apk", + new ApkSigner.Builder(ecP256SignerConfig) + .setV1SigningEnabled(true) + .setV2SigningEnabled(true) + .setV3SigningEnabled(true) + .setV4SigningEnabled(false) + .setSourceStampSignerConfig(rsa2048SignerConfig)); + ApkVerifier.Result result = verify(signedApk, null); + + assertSourceStampVerified(signedApk, result); + long timestamp = result.getSourceStampInfo().getTimestampEpochSeconds(); + assertTrue("Invalid source stamp timestamp value: " + timestamp, timestamp > 0); + } + /** * Asserts the provided {@code signedApk} contains a signature block with the expected * {@code byte[]} value and block ID as specified in the {@code expectedBlock}. diff --git a/src/test/java/com/android/apksig/ApkVerifierTest.java b/src/test/java/com/android/apksig/ApkVerifierTest.java index 31ed430..9de2b59 100644 --- a/src/test/java/com/android/apksig/ApkVerifierTest.java +++ b/src/test/java/com/android/apksig/ApkVerifierTest.java @@ -1313,6 +1313,123 @@ public class ApkVerifierTest { } @Test + public void verifySourceStamp_noTimestamp_returnsDefaultValue() throws Exception { + // A timestamp attribute was added to the source stamp, but verification of APKs that were + // generated prior to the addition of the timestamp should still complete successfully, + // returning a default value of 0 for the timestamp. + ApkVerifier.Result verificationResult = verifySourceStamp("v3-only-with-stamp.apk"); + + assertTrue(verificationResult.isSourceStampVerified()); + assertEquals( + "A value of 0 should be returned for the timestamp when the attribute is not " + + "present", + 0, verificationResult.getSourceStampInfo().getTimestampEpochSeconds()); + } + + @Test + public void verifySourceStamp_validTimestamp_returnsExpectedValue() throws Exception { + // Once an APK is signed with a source stamp that contains a valid value for the timestamp + // attribute, verification of the source stamp should result in the same value for the + // timestamp returned to the verifier. + ApkVerifier.Result verificationResult = verifySourceStamp( + "stamp-valid-timestamp-value.apk"); + + assertTrue(verificationResult.isSourceStampVerified()); + assertEquals(1644886584, verificationResult.getSourceStampInfo().getTimestampEpochSeconds()); + } + + @Test + public void verifySourceStamp_validTimestampLargerBuffer_returnsExpectedValue() + throws Exception { + // The source stamp timestamp attribute value is expected to be written to an 8 byte buffer + // as a little-endian long; while a larger buffer will not result in an error, any + // additional space after the buffer's initial 8 bytes will be ignored. This test verifies a + // valid timestamp value written to the first 8 bytes of a 16 byte buffer can still be read + // successfully. + ApkVerifier.Result verificationResult = verifySourceStamp( + "stamp-valid-timestamp-16-byte-buffer.apk"); + + assertTrue(verificationResult.isSourceStampVerified()); + assertEquals(1645126786, + verificationResult.getSourceStampInfo().getTimestampEpochSeconds()); + } + + @Test + public void verifySourceStamp_invalidTimestampValueEqualsZero_verificationFails() + throws Exception { + // If the source stamp timestamp attribute exists and is <= 0, then a warning should be + // reported to notify the caller to the invalid attribute value. This test verifies a + // a warning is reported when the timestamp attribute value is 0. + ApkVerifier.Result verificationResult = verifySourceStamp( + "stamp-invalid-timestamp-value-zero.apk"); + + assertSourceStampVerificationStatus(verificationResult, + SourceStampVerificationStatus.STAMP_VERIFICATION_FAILED); + assertSourceStampVerificationFailure(verificationResult, + Issue.SOURCE_STAMP_INVALID_TIMESTAMP); + } + + @Test + public void verifySourceStamp_invalidTimestampValueLessThanZero_verificationFails() + throws Exception { + // If the source stamp timestamp attribute exists and is <= 0, then a warning should be + // reported to notify the caller to the invalid attribute value. This test verifies a + // a warning is reported when the timestamp attribute value is < 0. + ApkVerifier.Result verificationResult = verifySourceStamp( + "stamp-invalid-timestamp-value-less-than-zero.apk"); + + assertSourceStampVerificationStatus(verificationResult, + SourceStampVerificationStatus.STAMP_VERIFICATION_FAILED); + assertSourceStampVerificationFailure(verificationResult, + Issue.SOURCE_STAMP_INVALID_TIMESTAMP); + } + + @Test + public void verifySourceStamp_invalidTimestampZeroInFirst8BytesOfBuffer_verificationFails() + throws Exception { + // The source stamp's timestamp attribute value is expected to be written to the first 8 + // bytes of the attribute's value buffer; if a larger buffer is used and the timestamp + // value is not written as a little-endian long to the first 8 bytes of the buffer, then + // an error should be reported for the timestamp attribute since the rest of the buffer will + // be ignored. + ApkVerifier.Result verificationResult = verifySourceStamp( + "stamp-timestamp-in-last-8-of-16-byte-buffer.apk"); + + assertSourceStampVerificationStatus(verificationResult, + SourceStampVerificationStatus.STAMP_VERIFICATION_FAILED); + assertSourceStampVerificationFailure(verificationResult, + Issue.SOURCE_STAMP_INVALID_TIMESTAMP); + } + + + @Test + public void verifySourceStamp_intTimestampValue_verificationFails() throws Exception { + // Since the source stamp timestamp attribute value is a long, an attribute value with + // insufficient space to hold a long value should result in a warning reported to the user. + ApkVerifier.Result verificationResult = verifySourceStamp( + "stamp-int-timestamp-value.apk"); + + assertSourceStampVerificationStatus(verificationResult, + SourceStampVerificationStatus.STAMP_VERIFICATION_FAILED); + assertSourceStampVerificationFailure(verificationResult, + Issue.SOURCE_STAMP_MALFORMED_ATTRIBUTE); + } + + @Test + public void verifySourceStamp_modifiedTimestampValue_verificationFails() throws Exception { + // The source stamp timestamp attribute is part of the block's signed data; this test + // verifies if the value of the timestamp in the stamp block is modified then verification + // of the source stamp should fail. + ApkVerifier.Result verificationResult = verifySourceStamp( + "stamp-valid-timestamp-value-modified.apk"); + + assertSourceStampVerificationStatus(verificationResult, + SourceStampVerificationStatus.STAMP_VERIFICATION_FAILED); + assertSourceStampVerificationFailure(verificationResult, + Issue.SOURCE_STAMP_DID_NOT_VERIFY); + } + + @Test public void apkVerificationIssueAdapter_verifyAllBaseIssuesMapped() throws Exception { Field[] fields = ApkVerificationIssue.class.getFields(); StringBuilder msg = new StringBuilder(); diff --git a/src/test/java/com/android/apksig/SourceStampVerifierTest.java b/src/test/java/com/android/apksig/SourceStampVerifierTest.java index f5020cc..2e54a8a 100644 --- a/src/test/java/com/android/apksig/SourceStampVerifierTest.java +++ b/src/test/java/com/android/apksig/SourceStampVerifierTest.java @@ -21,10 +21,12 @@ import static com.android.apksig.internal.apk.ApkSigningBlockUtilsLite.toHex; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import com.android.apksig.SourceStampVerifier.Result; import com.android.apksig.SourceStampVerifier.Result.SignerInfo; +import com.android.apksig.internal.util.AndroidSdkVersion; import com.android.apksig.internal.util.Resources; import com.android.apksig.util.DataSources; @@ -269,6 +271,110 @@ public class SourceStampVerifierTest { ApkVerificationIssue.JAR_SIG_NO_SIGNATURES); } + @Test + public void verifySourceStamp_noTimestamp_returnsDefaultValue() throws Exception { + // A timestamp attribute was added to the source stamp, but verification of APKs that were + // generated prior to the addition of the timestamp should still complete successfully, + // returning a default value of 0 for the timestamp. + Result verificationResult = verifySourceStamp("v3-only-with-stamp.apk", AndroidSdkVersion.P, + AndroidSdkVersion.P); + + assertVerified(verificationResult); + assertEquals( + "A value of 0 should be returned for the timestamp when the attribute is not " + + "present", + 0, verificationResult.getSourceStampInfo().getTimestampEpochSeconds()); + } + + @Test + public void verifySourceStamp_validTimestamp_returnsExpectedValue() throws Exception { + // Once an APK is signed with a source stamp that contains a valid value for the timestamp + // attribute, verification of the source stamp should result in the same value for the + // timestamp returned to the verifier. + Result verificationResult = verifySourceStamp("stamp-valid-timestamp-value.apk"); + + assertVerified(verificationResult); + assertEquals(1644886584, verificationResult.getSourceStampInfo().getTimestampEpochSeconds()); + } + + @Test + public void verifySourceStamp_validTimestampLargerBuffer_returnsExpectedValue() + throws Exception { + // The source stamp timestamp attribute value is expected to be written to an 8 byte buffer + // as a little-endian long; while a larger buffer will not result in an error, any + // additional space after the buffer's initial 8 bytes will be ignored. This test verifies a + // valid timestamp value written to the first 8 bytes of a 16 byte buffer can still be read + // successfully. + Result verificationResult = verifySourceStamp("stamp-valid-timestamp-16-byte-buffer.apk"); + + assertEquals(1645126786, + verificationResult.getSourceStampInfo().getTimestampEpochSeconds()); + } + + @Test + public void verifySourceStamp_invalidTimestampValueEqualsZero_verificationFails() + throws Exception { + // If the source stamp timestamp attribute exists and is <= 0, then a warning should be + // reported to notify the caller to the invalid attribute value. This test verifies a + // a warning is reported when the timestamp attribute value is 0. + Result verificationResult = verifySourceStamp("stamp-invalid-timestamp-value-zero.apk"); + + assertSourceStampVerificationFailure(verificationResult, + ApkVerificationIssue.SOURCE_STAMP_INVALID_TIMESTAMP); + } + + @Test + public void verifySourceStamp_invalidTimestampValueLessThanZero_verificationFails() + throws Exception { + // If the source stamp timestamp attribute exists and is <= 0, then a warning should be + // reported to notify the caller to the invalid attribute value. This test verifies a + // a warning is reported when the timestamp attribute value is < 0. + Result verificationResult = verifySourceStamp( + "stamp-invalid-timestamp-value-less-than-zero.apk"); + + assertSourceStampVerificationFailure(verificationResult, + ApkVerificationIssue.SOURCE_STAMP_INVALID_TIMESTAMP); + } + + @Test + public void verifySourceStamp_invalidTimestampZeroInFirst8BytesOfBuffer_verificationFails() + throws Exception { + // The source stamp's timestamp attribute value is expected to be written to the first 8 + // bytes of the attribute's value buffer; if a larger buffer is used and the timestamp + // value is not written as a little-endian long to the first 8 bytes of the buffer, then + // an error should be reported for the timestamp attribute since the rest of the buffer will + // be ignored. + Result verificationResult = verifySourceStamp( + "stamp-timestamp-in-last-8-of-16-byte-buffer.apk"); + + assertSourceStampVerificationFailure(verificationResult, + ApkVerificationIssue.SOURCE_STAMP_INVALID_TIMESTAMP); + } + + @Test + public void verifySourceStamp_intTimestampValue_verificationFails() throws Exception { + // Since the source stamp timestamp attribute value is a long, an attribute value with + // insufficient space to hold a long value should result in a warning reported to the user. + Result verificationResult = verifySourceStamp( + "stamp-int-timestamp-value.apk"); + + assertSourceStampVerificationFailure(verificationResult, + ApkVerificationIssue.SOURCE_STAMP_MALFORMED_ATTRIBUTE); + } + + @Test + public void verifySourceStamp_modifiedTimestampValue_verificationFails() throws Exception { + // The source stamp timestamp attribute is part of the block's signed data; this test + // verifies if the value of the timestamp in the stamp block is modified then verification + // of the source stamp should fail. + Result verificationResult = verifySourceStamp( + "stamp-valid-timestamp-value-modified.apk"); + + assertSourceStampVerificationFailure(verificationResult, + ApkVerificationIssue.SOURCE_STAMP_DID_NOT_VERIFY); + } + + private Result verifySourceStamp(String apkFilenameInResources) throws Exception { return verifySourceStamp(apkFilenameInResources, null, null, null); diff --git a/src/test/resources/com/android/apksig/stamp-int-timestamp-value.apk b/src/test/resources/com/android/apksig/stamp-int-timestamp-value.apk Binary files differnew file mode 100644 index 0000000..0cd740c --- /dev/null +++ b/src/test/resources/com/android/apksig/stamp-int-timestamp-value.apk diff --git a/src/test/resources/com/android/apksig/stamp-invalid-timestamp-value-less-than-zero.apk b/src/test/resources/com/android/apksig/stamp-invalid-timestamp-value-less-than-zero.apk Binary files differnew file mode 100644 index 0000000..f4a189e --- /dev/null +++ b/src/test/resources/com/android/apksig/stamp-invalid-timestamp-value-less-than-zero.apk diff --git a/src/test/resources/com/android/apksig/stamp-invalid-timestamp-value-zero.apk b/src/test/resources/com/android/apksig/stamp-invalid-timestamp-value-zero.apk Binary files differnew file mode 100644 index 0000000..6cfd082 --- /dev/null +++ b/src/test/resources/com/android/apksig/stamp-invalid-timestamp-value-zero.apk diff --git a/src/test/resources/com/android/apksig/stamp-timestamp-in-last-8-of-16-byte-buffer.apk b/src/test/resources/com/android/apksig/stamp-timestamp-in-last-8-of-16-byte-buffer.apk Binary files differnew file mode 100644 index 0000000..260b0ca --- /dev/null +++ b/src/test/resources/com/android/apksig/stamp-timestamp-in-last-8-of-16-byte-buffer.apk diff --git a/src/test/resources/com/android/apksig/stamp-valid-timestamp-16-byte-buffer.apk b/src/test/resources/com/android/apksig/stamp-valid-timestamp-16-byte-buffer.apk Binary files differnew file mode 100644 index 0000000..da9c34d --- /dev/null +++ b/src/test/resources/com/android/apksig/stamp-valid-timestamp-16-byte-buffer.apk diff --git a/src/test/resources/com/android/apksig/stamp-valid-timestamp-value-modified.apk b/src/test/resources/com/android/apksig/stamp-valid-timestamp-value-modified.apk Binary files differnew file mode 100644 index 0000000..eefc148 --- /dev/null +++ b/src/test/resources/com/android/apksig/stamp-valid-timestamp-value-modified.apk diff --git a/src/test/resources/com/android/apksig/stamp-valid-timestamp-value.apk b/src/test/resources/com/android/apksig/stamp-valid-timestamp-value.apk Binary files differnew file mode 100644 index 0000000..3c6a501 --- /dev/null +++ b/src/test/resources/com/android/apksig/stamp-valid-timestamp-value.apk |