diff options
author | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2020-01-18 02:21:03 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2020-01-18 02:21:03 +0000 |
commit | ad7ee467d57d28c5e852efc0850fc0c106fb0e5a (patch) | |
tree | 4b14a3d11e317ec2539ff0ceed7b874c3604ab03 | |
parent | 0260a8c34fbc70772c90dcd129dd95dfa3ab6bf1 (diff) | |
parent | aa39f5e4a17d1b439f568ee3c629ccee8d66bb6a (diff) | |
download | SecureElement-ad7ee467d57d28c5e852efc0850fc0c106fb0e5a.tar.gz |
Add Carrier Privilege support am: 2b58f07680 am: aa39f5e4a1
Change-Id: Ifa56c3fba9cf26c0d92e58e62fe83d952b851394
-rw-r--r-- | src/com/android/se/Terminal.java | 68 | ||||
-rw-r--r-- | src/com/android/se/security/AccessControlEnforcer.java | 29 | ||||
-rw-r--r-- | src/com/android/se/security/AccessRuleCache.java | 39 | ||||
-rwxr-xr-x | src/com/android/se/security/ChannelAccess.java | 11 |
4 files changed, 134 insertions, 13 deletions
diff --git a/src/com/android/se/Terminal.java b/src/com/android/se/Terminal.java index c248c89..d7d9d99 100644 --- a/src/com/android/se/Terminal.java +++ b/src/com/android/se/Terminal.java @@ -24,7 +24,9 @@ package com.android.se; import android.content.Context; +import android.content.pm.PackageInfo; import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; import android.hardware.secure_element.V1_0.ISecureElement; import android.hardware.secure_element.V1_0.ISecureElementHalCallback; import android.hardware.secure_element.V1_0.LogicalChannelResponse; @@ -387,17 +389,19 @@ public class Terminal { throw new IOException("Secure Element is not connected"); } - Log.w(mTag, "Enable access control on basic channel for " + packageName); - StatsLog.write( - StatsLog.SE_OMAPI_REPORTED, - StatsLog.SE_OMAPI_REPORTED__OPERATION__OPEN_CHANNEL, - mName, - packageName); - ChannelAccess channelAccess; - try { - channelAccess = setUpChannelAccess(aid, packageName, pid); - } catch (MissingResourceException e) { - return null; + ChannelAccess channelAccess = null; + if (packageName != null) { + Log.w(mTag, "Enable access control on basic channel for " + packageName); + StatsLog.write( + StatsLog.SE_OMAPI_REPORTED, + StatsLog.SE_OMAPI_REPORTED__OPERATION__OPEN_CHANNEL, + mName, + packageName); + try { + channelAccess = setUpChannelAccess(aid, packageName, pid); + } catch (MissingResourceException e) { + return null; + } } synchronized (mLock) { @@ -680,6 +684,9 @@ public class Terminal { if (isPrivilegedApplication(packageName)) { return ChannelAccess.getPrivilegeAccess(packageName, pid); + } else if (getName().startsWith(SecureElementService.UICC_TERMINAL) + && isCarrierPrivilegeApplication(packageName)) { + return ChannelAccess.getCarrierPrivilegeAccess(packageName, pid); } synchronized (mLock) { @@ -739,6 +746,45 @@ public class Terminal { return mContext; } + /** + * Checks if Carrier Privilege exists for the given package + */ + private boolean isCarrierPrivilegeApplication(String packageName) { + try { + PackageManager pm = mContext.getPackageManager(); + if (pm != null) { + PackageInfo pkgInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES); + return checkCarrierPrivilegeRules(pkgInfo); + } + } catch (NameNotFoundException ne) { } + return false; + } + + /** + * Checks if Carrier Privilege exists for the given package + */ + public boolean checkCarrierPrivilegeRules(PackageInfo pInfo) { + boolean checkRefreshTag = true; + if (mAccessControlEnforcer == null || mAccessControlEnforcer.isNoRuleFound()) { + try { + initializeAccessControl(); + } catch (IOException e) { + return false; + } + checkRefreshTag = false; + } + mAccessControlEnforcer.setPackageManager(mContext.getPackageManager()); + + synchronized (mLock) { + try { + return mAccessControlEnforcer.checkCarrierPrivilege(pInfo, checkRefreshTag); + } catch (Exception e) { + Log.i(mTag, "checkCarrierPrivilege() Exception: " + e.getMessage()); + return false; + } + } + } + /** Dump data for debug purpose . */ public void dump(PrintWriter writer) { writer.println("SECURE ELEMENT SERVICE TERMINAL: " + mName); diff --git a/src/com/android/se/security/AccessControlEnforcer.java b/src/com/android/se/security/AccessControlEnforcer.java index a4ceb70..bcf3a9a 100644 --- a/src/com/android/se/security/AccessControlEnforcer.java +++ b/src/com/android/se/security/AccessControlEnforcer.java @@ -451,6 +451,35 @@ public class AccessControlEnforcer { } } + /** Returns true if the given package has Carrier Privileges */ + public synchronized boolean checkCarrierPrivilege(PackageInfo pInfo, boolean checkRefreshTag) { + if (!mUseAra && !mUseArf) { + return false; + } + if (checkRefreshTag) { + try { + updateAccessRuleIfNeed(); + } catch (IOException | MissingResourceException e) { + throw new AccessControlException("Access-Control not found in " + + mTerminal.getName()); + } + } + if (mRulesRead) { + return false; + } + try { + List<byte[]> appCertHashes = getAppCertHashes(pInfo.packageName); + if (appCertHashes == null || appCertHashes.size() == 0) { + return false; + } + + return mAccessRuleCache.checkCarrierPrivilege(pInfo.packageName, appCertHashes); + } catch (Exception e) { + Log.w(mTag, " checkCarrierPrivilege: " + e.getLocalizedMessage()); + } + return false; + } + /** Debug information to be used by dumpsys */ public void dump(PrintWriter writer) { writer.println(mTag + ":"); diff --git a/src/com/android/se/security/AccessRuleCache.java b/src/com/android/se/security/AccessRuleCache.java index 6d854c0..97c63bb 100644 --- a/src/com/android/se/security/AccessRuleCache.java +++ b/src/com/android/se/security/AccessRuleCache.java @@ -41,6 +41,7 @@ import android.util.Log; import com.android.se.security.gpac.AID_REF_DO; import com.android.se.security.gpac.AR_DO; import com.android.se.security.gpac.Hash_REF_DO; +import com.android.se.security.gpac.PKG_REF_DO; import com.android.se.security.gpac.REF_DO; import java.io.PrintWriter; @@ -65,6 +66,7 @@ public class AccessRuleCache { // recreated. private byte[] mRefreshTag = null; private Map<REF_DO, ChannelAccess> mRuleCache = new HashMap<REF_DO, ChannelAccess>(); + private ArrayList<REF_DO> mCarrierPrivilegeCache = new ArrayList<REF_DO>(); private static AID_REF_DO getAidRefDo(byte[] aid) { byte[] defaultAid = new byte[]{0x00, 0x00, 0x00, 0x00, 0x00}; @@ -132,17 +134,19 @@ public class AccessRuleCache { public void reset() { mRefreshTag = null; mRuleCache.clear(); + mCarrierPrivilegeCache.clear(); } /** Clears access rule cache only. */ public void clearCache() { mRuleCache.clear(); + mCarrierPrivilegeCache.clear(); } /** Adds the Rule to the Cache */ public void putWithMerge(REF_DO refDo, AR_DO arDo) { if (refDo.isCarrierPrivilegeRefDo()) { - // Ignore Carrier Privilege Rules + mCarrierPrivilegeCache.add(refDo); return; } ChannelAccess channelAccess = mapArDo2ChannelAccess(arDo); @@ -152,7 +156,7 @@ public class AccessRuleCache { /** Adds the Rule to the Cache */ public void putWithMerge(REF_DO refDo, ChannelAccess channelAccess) { if (refDo.isCarrierPrivilegeRefDo()) { - // Ignore Carrier Privilege Rules + mCarrierPrivilegeCache.add(refDo); return; } if (mRuleCache.containsKey(refDo)) { @@ -443,6 +447,27 @@ public class AccessRuleCache { return null; } + /** Check if the carrier privilege exists for the given package */ + public boolean checkCarrierPrivilege(String packageName, List<byte[]> appCertHashes) { + for (byte[] hash : appCertHashes) { + for (REF_DO ref_do : mCarrierPrivilegeCache) { + Hash_REF_DO hash_ref_do = ref_do.getHashDo(); + PKG_REF_DO pkg_ref_do = ref_do.getPkgDo(); + if (Hash_REF_DO.equals(hash_ref_do, new Hash_REF_DO(hash))) { + // If PKG_REF_DO exists then package name should match, otherwise allow + if (pkg_ref_do != null) { + if (packageName.equals(pkg_ref_do.getPackageName())) { + return true; + } + } else { + return true; + } + } + } + } + return false; + } + /** Check if the given Refresh Tag is equal to the last known */ public boolean isRefreshTagEqual(byte[] refreshTag) { if (refreshTag == null || mRefreshTag == null) return false; @@ -481,5 +506,15 @@ public class AccessRuleCache { writer.println(entry.getKey().toString() + " -> " + entry.getValue().toString()); } writer.println(); + + /* Dump the Carrier Privilege cache */ + writer.println("Carrier Privilege:"); + i = 0; + for (REF_DO ref_do : mCarrierPrivilegeCache) { + i++; + writer.print("carrier privilege " + i + ": "); + writer.println(ref_do.toString()); + } + writer.println(); } } diff --git a/src/com/android/se/security/ChannelAccess.java b/src/com/android/se/security/ChannelAccess.java index 31ca45e..d75ad15 100755 --- a/src/com/android/se/security/ChannelAccess.java +++ b/src/com/android/se/security/ChannelAccess.java @@ -144,6 +144,17 @@ public class ChannelAccess { return ca; } + /** Provides the ChannelAccess with CarrierPrivilege Access */ + public static ChannelAccess getCarrierPrivilegeAccess(String packageName, int pid) { + ChannelAccess ca = new ChannelAccess(); + ca.setPackageName(packageName); + ca.setCallingPid(pid); + ca.setAccess(ACCESS.ALLOWED, "Carrier-Privilege"); + ca.setApduAccess(ACCESS.ALLOWED); + + return ca; + } + @Override public String toString() { StringBuilder sb = new StringBuilder(); |