aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKhaled Abdelmohsen <khelmy@google.com>2020-09-25 21:23:33 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2020-09-25 21:23:33 +0000
commit8fa509e2a0f4e492b449bad535b439e0df262869 (patch)
tree53fdb2db70c855d15dc4ada0097494e624c77f4f
parent70fae881edf1c920f38460cc05eab34e3f6f3238 (diff)
parent75a024658218358354801ddde2ea754fdda7f8df (diff)
downloadapksig-8fa509e2a0f4e492b449bad535b439e0df262869.tar.gz
Add stamp attributes to source stamp signing block am: 75a0246582
Original change: https://googleplex-android-review.googlesource.com/c/platform/tools/apksig/+/12692884 Change-Id: Idf01645c6091f7606b6454ac617a549dcddfa5e2
-rw-r--r--src/main/java/com/android/apksig/DefaultApkSignerEngine.java7
-rw-r--r--src/main/java/com/android/apksig/SigningCertificateLineage.java16
-rw-r--r--src/main/java/com/android/apksig/internal/apk/stamp/SourceStampConstants.java1
-rw-r--r--src/main/java/com/android/apksig/internal/apk/stamp/V2SourceStampSigner.java64
-rw-r--r--src/main/java/com/android/apksig/internal/apk/v3/V3SchemeSigner.java18
-rw-r--r--src/test/java/com/android/apksig/SigningCertificateLineageTest.java4
6 files changed, 88 insertions, 22 deletions
diff --git a/src/main/java/com/android/apksig/DefaultApkSignerEngine.java b/src/main/java/com/android/apksig/DefaultApkSignerEngine.java
index 5fb2600..7aa7bf1 100644
--- a/src/main/java/com/android/apksig/DefaultApkSignerEngine.java
+++ b/src/main/java/com/android/apksig/DefaultApkSignerEngine.java
@@ -381,10 +381,15 @@ public class DefaultApkSignerEngine implements ApkSignerEngine {
private ApkSigningBlockUtils.SignerConfig createSourceStampSignerConfig()
throws InvalidKeyException {
- return createSigningBlockSignerConfig(
+ ApkSigningBlockUtils.SignerConfig config = createSigningBlockSignerConfig(
mSourceStampSignerConfig,
/* apkSigningBlockPaddingSupported= */ false,
ApkSigningBlockUtils.VERSION_SOURCE_STAMP);
+ if (mSourceStampSigningCertificateLineage != null) {
+ config.mSigningCertificateLineage = mSourceStampSigningCertificateLineage.getSubLineage(
+ config.certificates.get(0));
+ }
+ return config;
}
private int getMinSdkFromV3SignatureAlgorithms(List<SignatureAlgorithm> algorithms) {
diff --git a/src/main/java/com/android/apksig/SigningCertificateLineage.java b/src/main/java/com/android/apksig/SigningCertificateLineage.java
index 7645b26..b8f1f8b 100644
--- a/src/main/java/com/android/apksig/SigningCertificateLineage.java
+++ b/src/main/java/com/android/apksig/SigningCertificateLineage.java
@@ -492,20 +492,8 @@ public class SigningCertificateLineage {
return result;
}
- public byte[] generateV3SignerAttribute() {
- // FORMAT (little endian):
- // * length-prefixed bytes: attribute pair
- // * uint32: ID
- // * bytes: value - encoded V3 SigningCertificateLineage
- byte[] encodedLineage =
- V3SigningCertificateLineage.encodeSigningCertificateLineage(mSigningLineage);
- int payloadSize = 4 + 4 + encodedLineage.length;
- ByteBuffer result = ByteBuffer.allocate(payloadSize);
- result.order(ByteOrder.LITTLE_ENDIAN);
- result.putInt(4 + encodedLineage.length);
- result.putInt(V3SchemeConstants.PROOF_OF_ROTATION_ATTR_ID);
- result.put(encodedLineage);
- return result.array();
+ public byte[] encodeSigningCertificateLineage() {
+ return V3SigningCertificateLineage.encodeSigningCertificateLineage(mSigningLineage);
}
public List<DefaultApkSignerEngine.SignerConfig> sortSignerConfigs(
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 afb6bce..465fbb0 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
@@ -23,4 +23,5 @@ public class SourceStampConstants {
public static final int V1_SOURCE_STAMP_BLOCK_ID = 0x2b09189e;
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;
}
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 401a43e..46c5b17 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
@@ -23,11 +23,14 @@ import static com.android.apksig.internal.apk.ApkSigningBlockUtils.encodeAsLengt
import static com.android.apksig.internal.apk.ApkSigningBlockUtils.encodeAsSequenceOfLengthPrefixedElements;
import static com.android.apksig.internal.apk.ApkSigningBlockUtils.encodeAsSequenceOfLengthPrefixedPairsOfIntAndLengthPrefixedBytes;
+import com.android.apksig.SigningCertificateLineage;
import com.android.apksig.internal.apk.ApkSigningBlockUtils;
import com.android.apksig.internal.apk.ApkSigningBlockUtils.SignerConfig;
import com.android.apksig.internal.apk.ContentDigestAlgorithm;
import com.android.apksig.internal.util.Pair;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
@@ -35,6 +38,7 @@ import java.security.cert.CertificateEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -55,7 +59,8 @@ public abstract class V2SourceStampSigner {
SourceStampConstants.V2_SOURCE_STAMP_BLOCK_ID;
/** Hidden constructor to prevent instantiation. */
- private V2SourceStampSigner() {}
+ private V2SourceStampSigner() {
+ }
public static Pair<byte[], Integer> generateSourceStampBlock(
SignerConfig sourceStampSignerConfig,
@@ -96,17 +101,30 @@ public abstract class V2SourceStampSigner {
sourceStampBlock.signedDigests = signatureSchemeDigests;
+ sourceStampBlock.stampAttributes = encodeStampAttributes(
+ generateStampAttributes(sourceStampSignerConfig.mSigningCertificateLineage));
+ sourceStampBlock.signedStampAttributes =
+ ApkSigningBlockUtils.generateSignaturesOverData(sourceStampSignerConfig,
+ sourceStampBlock.stampAttributes);
+
// FORMAT:
// * length-prefixed bytes: X.509 certificate (ASN.1 DER encoded)
// * length-prefixed sequence of length-prefixed signed signature scheme digests:
// * uint32: signature scheme id
// * length-prefixed bytes: signed digests for the respective signature scheme
+ // * length-prefixed bytes: encoded stamp attributes
+ // * length-prefixed sequence of length-prefixed signed stamp attributes:
+ // * uint32: signature algorithm id
+ // * length-prefixed bytes: signed stamp attributes for the respective signature algorithm
byte[] sourceStampSignerBlock =
encodeAsSequenceOfLengthPrefixedElements(
- new byte[][] {
- sourceStampBlock.stampCertificate,
- encodeAsSequenceOfLengthPrefixedPairsOfIntAndLengthPrefixedBytes(
- sourceStampBlock.signedDigests),
+ new byte[][]{
+ sourceStampBlock.stampCertificate,
+ encodeAsSequenceOfLengthPrefixedPairsOfIntAndLengthPrefixedBytes(
+ sourceStampBlock.signedDigests),
+ sourceStampBlock.stampAttributes,
+ encodeAsSequenceOfLengthPrefixedPairsOfIntAndLengthPrefixedBytes(
+ sourceStampBlock.signedStampAttributes),
});
// FORMAT:
@@ -159,8 +177,44 @@ public abstract class V2SourceStampSigner {
signedDigest)));
}
+ private static byte[] encodeStampAttributes(Map<Integer, byte[]> stampAttributes) {
+ if (stampAttributes == null || stampAttributes.isEmpty()) {
+ return new byte[0];
+ }
+
+ int payloadSize = 0;
+ for (byte[] attributeValue : stampAttributes.values()) {
+ payloadSize += 4 + attributeValue.length;
+ }
+
+ // FORMAT (little endian):
+ // * length-prefixed bytes: pair
+ // * uint32: ID
+ // * bytes: value
+ ByteBuffer result = ByteBuffer.allocate(4 + payloadSize);
+ result.order(ByteOrder.LITTLE_ENDIAN);
+ result.putInt(payloadSize);
+ for (Map.Entry<Integer, byte[]> stampAttribute : stampAttributes.entrySet()) {
+ result.putInt(stampAttribute.getKey());
+ result.put(stampAttribute.getValue());
+ }
+ return result.array();
+ }
+
+ private static Map<Integer, byte[]> generateStampAttributes(SigningCertificateLineage lineage) {
+ HashMap<Integer, byte[]> stampAttributes = new HashMap<>();
+ if (lineage != null) {
+ stampAttributes.put(SourceStampConstants.PROOF_OF_ROTATION_ATTR_ID,
+ lineage.encodeSigningCertificateLineage());
+ }
+ return stampAttributes;
+ }
+
private static final class SourceStampBlock {
public byte[] stampCertificate;
public List<Pair<Integer, byte[]>> signedDigests;
+ // Optional stamp attributes that are not required for verification.
+ public byte[] stampAttributes;
+ public List<Pair<Integer, byte[]>> signedStampAttributes;
}
}
diff --git a/src/main/java/com/android/apksig/internal/apk/v3/V3SchemeSigner.java b/src/main/java/com/android/apksig/internal/apk/v3/V3SchemeSigner.java
index 2c70311..cab2a47 100644
--- a/src/main/java/com/android/apksig/internal/apk/v3/V3SchemeSigner.java
+++ b/src/main/java/com/android/apksig/internal/apk/v3/V3SchemeSigner.java
@@ -142,6 +142,22 @@ public abstract class V3SchemeSigner {
digestInfo.getSecond());
}
+ public static byte[] generateV3SignerAttribute(
+ SigningCertificateLineage signingCertificateLineage) {
+ // FORMAT (little endian):
+ // * length-prefixed bytes: attribute pair
+ // * uint32: ID
+ // * bytes: value - encoded V3 SigningCertificateLineage
+ byte[] encodedLineage = signingCertificateLineage.encodeSigningCertificateLineage();
+ int payloadSize = 4 + 4 + encodedLineage.length;
+ ByteBuffer result = ByteBuffer.allocate(payloadSize);
+ result.order(ByteOrder.LITTLE_ENDIAN);
+ result.putInt(4 + encodedLineage.length);
+ result.putInt(V3SchemeConstants.PROOF_OF_ROTATION_ATTR_ID);
+ result.put(encodedLineage);
+ return result.array();
+ }
+
private static Pair<byte[], Integer> generateApkSignatureSchemeV3Block(
List<SignerConfig> signerConfigs, Map<ContentDigestAlgorithm, byte[]> contentDigests)
throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
@@ -289,7 +305,7 @@ public abstract class V3SchemeSigner {
if (signerConfig.mSigningCertificateLineage == null) {
return new byte[0];
}
- return signerConfig.mSigningCertificateLineage.generateV3SignerAttribute();
+ return generateV3SignerAttribute(signerConfig.mSigningCertificateLineage);
}
private static final class V3SignatureSchemeBlock {
diff --git a/src/test/java/com/android/apksig/SigningCertificateLineageTest.java b/src/test/java/com/android/apksig/SigningCertificateLineageTest.java
index d1a1568..14cab83 100644
--- a/src/test/java/com/android/apksig/SigningCertificateLineageTest.java
+++ b/src/test/java/com/android/apksig/SigningCertificateLineageTest.java
@@ -26,6 +26,7 @@ import com.android.apksig.SigningCertificateLineage.SignerConfig;
import com.android.apksig.apk.ApkFormatException;
import com.android.apksig.internal.apk.ApkSigningBlockUtils;
import com.android.apksig.internal.apk.v3.V3SchemeConstants;
+import com.android.apksig.internal.apk.v3.V3SchemeSigner;
import com.android.apksig.internal.util.ByteBufferUtils;
import com.android.apksig.internal.util.Resources;
import com.android.apksig.util.DataSource;
@@ -244,7 +245,8 @@ public class SigningCertificateLineageTest {
// * length-prefixed bytes: attribute pair
// * uint32: ID
// * bytes: value - encoded V3 SigningCertificateLineage
- ByteBuffer v3SignerAttribute = ByteBuffer.wrap(lineage.generateV3SignerAttribute());
+ ByteBuffer v3SignerAttribute = ByteBuffer.wrap(
+ V3SchemeSigner.generateV3SignerAttribute(lineage));
v3SignerAttribute.order(ByteOrder.LITTLE_ENDIAN);
ByteBuffer attribute = ApkSigningBlockUtils.getLengthPrefixedSlice(v3SignerAttribute);
// The generateV3SignerAttribute method should only use the PROOF_OF_ROTATION_ATTR_ID