From 5a1adf38bc5bd3970dd876f07570202f2d351b68 Mon Sep 17 00:00:00 2001 From: Salvo Giangreco Date: Mon, 5 Aug 2024 11:22:38 +0200 Subject: [PATCH] Do not hack certificate chain for Samsung certs Signed-off-by: Salvo Giangreco --- .../tricky_store/keystore/CertHack.java | 2 ++ .../a13e300/tricky_store/keystore/Utils.java | 33 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/service/src/main/java/io/github/a13e300/tricky_store/keystore/CertHack.java b/service/src/main/java/io/github/a13e300/tricky_store/keystore/CertHack.java index 2353338..11e7514 100644 --- a/service/src/main/java/io/github/a13e300/tricky_store/keystore/CertHack.java +++ b/service/src/main/java/io/github/a13e300/tricky_store/keystore/CertHack.java @@ -161,6 +161,8 @@ public static void readFromXml(String data) { public static Certificate[] hackCertificateChain(Certificate[] caList) { if (caList == null) throw new UnsupportedOperationException("caList is null!"); try { + if (Utils.isSAK(caList)) return caList; + X509Certificate leaf = (X509Certificate) certificateFactory.generateCertificate(new ByteArrayInputStream(caList[0].getEncoded())); byte[] bytes = leaf.getExtensionValue(OID.getId()); if (bytes == null) return caList; diff --git a/service/src/main/java/io/github/a13e300/tricky_store/keystore/Utils.java b/service/src/main/java/io/github/a13e300/tricky_store/keystore/Utils.java index 6b1659c..a0074fc 100644 --- a/service/src/main/java/io/github/a13e300/tricky_store/keystore/Utils.java +++ b/service/src/main/java/io/github/a13e300/tricky_store/keystore/Utils.java @@ -2,6 +2,7 @@ import android.system.keystore2.KeyEntryResponse; import android.system.keystore2.KeyMetadata; +import android.util.Base64; import android.util.Log; import java.io.ByteArrayInputStream; @@ -11,11 +12,31 @@ import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Iterator; public class Utils { private final static String TAG = "Utils"; + + private static final String SAKV1_ROOT_PUBLIC_KEY = "" + + "MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBs9Qjr//REhkXW7jUqjY9KNwWac4r" + + "5+kdUGk+TZjRo1YEa47Axwj6AJsbOjo4QsHiYRiWTELvFeiuBsKqyuF0xyAAKvDo" + + "fBqrEq1/Ckxo2mz7Q4NQes3g4ahSjtgUSh0k85fYwwHjCeLyZ5kEqgHG9OpOH526" + + "FFAK3slSUgC8RObbxys="; + + private static final String SAKV2_ROOT_PUBLIC_KEY = "" + + "MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBhbGuLrpql5I2WJmrE5kEVZOo+dgA" + + "46mKrVJf/sgzfzs2u7M9c1Y9ZkCEiiYkhTFE9vPbasmUfXybwgZ2EM30A1ABPd12" + + "4n3JbEDfsB/wnMH1AcgsJyJFPbETZiy42Fhwi+2BCA5bcHe7SrdkRIYSsdBRaKBo" + + "ZsapxB0gAOs0jSPRX5M="; + + private static final String SAKMV1_ROOT_PUBLIC_KEY = "" + + "MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQB9XeEN8lg6p5xvMVWG42P2Qi/aRKX" + + "2rPRNgK92UlO9O/TIFCKHC1AWCLFitPVEow5W+yEgC2wOiYxgepY85TOoH0AuEkL" + + "oiC6ldbF2uNVU3rYYSytWAJg3GFKd1l9VLDmxox58Hyw2Jmdd5VSObGiTFQ/SgKs" + + "n2fbQPtpGlNxgEfd6Y8="; + static X509Certificate toCertificate(byte[] bytes) { try { final CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); @@ -71,4 +92,16 @@ public static void putCertificateChain(KeyMetadata metadata, Certificate[] chain } metadata.certificateChain = output.toByteArray(); } + + public static boolean isSAK(Certificate[] chain) throws Throwable { + var root = toCertificate(chain[chain.length - 1].getEncoded()); + byte[] publicKey = root.getPublicKey().getEncoded(); + if (Arrays.equals(publicKey, Base64.decode(SAKV1_ROOT_PUBLIC_KEY, 0)) + || Arrays.equals(publicKey, Base64.decode(SAKV2_ROOT_PUBLIC_KEY, 0)) + || Arrays.equals(publicKey, Base64.decode(SAKMV1_ROOT_PUBLIC_KEY, 0))) { + Log.w(TAG, "SAK detected, certificate chain won't be touched"); + return true; + } + return false; + } }