diff options
author | alk3pInjection <webmaster@raspii.tech> | 2021-09-14 11:26:25 +0800 |
---|---|---|
committer | alk3pInjection <webmaster@raspii.tech> | 2021-09-14 11:26:25 +0800 |
commit | 7ca989b67fb2686cbf4af249c8f3641cbcba2932 (patch) | |
tree | 8a944cc08c24ea9710b75b973cf12ef8bdd61bf0 | |
parent | 734b7eb48b7deb06c45370a6120ca5487ce6dedd (diff) | |
parent | 2fa1d5140d8e614c7f18c9d3aa4d4f8ede6dd077 (diff) |
Merge remote-tracking branch 'nxp-oss/br_android_ncihalx_row_12' into lineage-18.1
Signed-off-by: alk3pInjection <webmaster@raspii.tech>
Change-Id: Ifda025f9963e067b37475cf65de4276fdaeeedd2
-rw-r--r-- | Android.bp | 3 | ||||
-rw-r--r-- | src/com/android/se/SecureElementService.java | 18 | ||||
-rw-r--r-- | src/com/android/se/Terminal.java | 184 | ||||
-rw-r--r-- | src/com/android/se/security/gpac/AID_REF_DO.java | 2 |
4 files changed, 195 insertions, 12 deletions
@@ -16,7 +16,8 @@ android_app { certificate: "platform", static_libs: ["android.hardware.secure_element-V1.0-java", "android.hardware.secure_element-V1.1-java", - "android.hardware.secure_element-V1.2-java"], + "android.hardware.secure_element-V1.2-java", + "vendor.nxp.nxpese-V1.0-java"], optimize: { enabled: false, }, diff --git a/src/com/android/se/SecureElementService.java b/src/com/android/se/SecureElementService.java index 758fc77..705d629 100644 --- a/src/com/android/se/SecureElementService.java +++ b/src/com/android/se/SecureElementService.java @@ -96,8 +96,12 @@ public final class SecureElementService extends Service { if (packageNames == null || packageNames.length == 0) { throw new IllegalArgumentException("package names not specified"); } - Terminal terminal = getTerminal(reader); - return terminal.isNfcEventAllowed(getPackageManager(), aid, packageNames); + try { + Terminal terminal = getTerminal(reader); + return terminal.isNfcEventAllowed(getPackageManager(), aid, packageNames); + } catch (IllegalArgumentException e) { + return null; + } } @Override @@ -145,6 +149,7 @@ public final class SecureElementService extends Service { @Override public void onCreate() { + super.onCreate(); Log.i(mTag, Thread.currentThread().getName() + " onCreate"); initialize(); createTerminals(); @@ -156,6 +161,7 @@ public final class SecureElementService extends Service { * close all the channels. */ public void onDestroy() { + super.onDestroy(); Log.i(mTag, "onDestroy"); for (Terminal terminal : mTerminals.values()) { terminal.closeChannels(); @@ -333,7 +339,9 @@ public final class SecureElementService extends Service { Log.i(mTag, "Open basic channel success. Channel: " + channel.getChannelNumber()); - mChannels.add(channel); + synchronized (mLock) { + mChannels.add(channel); + } return channel.new SecureElementChannel(); } @@ -373,7 +381,9 @@ public final class SecureElementService extends Service { Log.i(mTag, "openLogicalChannel() Success. Channel: " + channel.getChannelNumber()); - mChannels.add(channel); + synchronized (mLock) { + mChannels.add(channel); + } return channel.new SecureElementChannel(); } } diff --git a/src/com/android/se/Terminal.java b/src/com/android/se/Terminal.java index 3be9749..a8de7ca 100644 --- a/src/com/android/se/Terminal.java +++ b/src/com/android/se/Terminal.java @@ -33,6 +33,7 @@ import android.hardware.secure_element.V1_0.LogicalChannelResponse; import android.hardware.secure_element.V1_0.SecureElementStatus; import android.os.Build; import android.os.Handler; +import android.os.Binder; import android.os.HwBinder; import android.os.Message; import android.os.RemoteException; @@ -58,6 +59,31 @@ import java.util.Map; import java.util.MissingResourceException; import java.util.NoSuchElementException; +import java.io.ByteArrayInputStream; +import android.content.pm.PackageInfo; +import android.content.pm.Signature; +import java.security.MessageDigest; +import java.security.cert.Certificate; +import java.security.cert.CertificateFactory; +import vendor.nxp.nxpese.V1_0.INxpEse; +import vendor.nxp.nxpese.V1_0.INxpEse.Stub; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import android.app.Activity; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.content.pm.Signature; +import android.os.Bundle; +import android.util.Log; + /** * Each Terminal represents a Secure Element. * Communicates to the SE via SecureElement HAL. @@ -75,12 +101,20 @@ public class Terminal { private static final boolean DEBUG = Build.IS_DEBUGGABLE; private static final int GET_SERVICE_DELAY_MILLIS = 4 * 1000; private static final int EVENT_GET_HAL = 1; + private static final long HAL_ESE_IOCTL_OMAPI_TRY_GET_ESE_SESSION = 0xB7; + private static final long HAL_ESE_IOCTL_OMAPI_RELEASE_ESE_SESSION = 0xB8; + /** + * Error code used with ServiceSpecificException. + * Thrown if RF is observed ON while opening connection to ESE over SPI. + */ + private static final int NFC_IN_USE = 3; private final int mMaxGetHalRetryCount = 5; private int mGetHalRetryCount = 0; private ISecureElement mSEHal; private android.hardware.secure_element.V1_2.ISecureElement mSEHal12; + private INxpEse mNxpEseHal; /** For each Terminal there will be one AccessController object. */ private AccessControlEnforcer mAccessControlEnforcer; @@ -172,6 +206,8 @@ public class Terminal { mName); synchronized (mLock) { mIsConnected = false; + if (mName.equals("eSE1")) + mNxpEseHal = null; if (mAccessControlEnforcer != null) { mAccessControlEnforcer.reset(); } @@ -249,12 +285,25 @@ public class Terminal { } } } - if (mSEHal11 != null || mSEHal12 != null) { + if (mSEHal11 != null) { mSEHal11.init_1_1(mHalCallback11); } else { mSEHal.init(mHalCallback); } mSEHal.linkToDeath(mDeathRecipient, 0); + + if (mName.equals("eSE1")) { + if (mNxpEseHal == null) { + try { + mNxpEseHal = INxpEse.getService(true /* retry */); + } catch (Exception e) { + Log.e(mTag, "Error getting HAL for NxpEse"); + } + } + if (mNxpEseHal == null) { + throw new NoSuchElementException("No HAL is provided for NxpEse"); + } + } } Log.i(mTag, mName + " was initialized"); SecureElementStatsLog.write( @@ -319,11 +368,13 @@ public class Terminal { /** * Cleans up all the channels in use. */ - public synchronized void closeChannels() { - Collection<Channel> col = mChannels.values(); - Channel[] channelList = col.toArray(new Channel[col.size()]); - for (Channel channel : channelList) { - channel.close(); + public void closeChannels() { + synchronized (mLock) { + Collection<Channel> col = mChannels.values(); + Channel[] channelList = col.toArray(new Channel[col.size()]); + for (Channel channel : channelList) { + channel.close(); + } } } @@ -643,6 +694,9 @@ public class Terminal { sw1 = rsp[rsp.length - 2] & 0xFF; sw2 = rsp[rsp.length - 1] & 0xFF; } while (sw1 == 0x61); + } else if ((sw1 == 0x65) && (sw2 == 0x15)) { + Log.e(mTag, "Secure Element write failed, Nfc in use"); + throw new IOException("Secure Element write failed, Nfc in use"); } return rsp; } @@ -665,6 +719,24 @@ public class Terminal { return rsp; } + private byte[] nxpEseHalIoctlInternal(long ioctlType, byte[] ioctlData) throws IOException { + ArrayList<Byte> ioctlResponse; + try { + ioctlResponse = mNxpEseHal.ioctl(ioctlType, byteArrayToArrayList(ioctlData)); + } catch (RemoteException e) { + throw new IOException(e.getMessage()); + } + if (ioctlResponse.isEmpty()) { + throw new IOException("Error in transmit()"); + } + byte[] rsp = arrayListToByteArray(ioctlResponse); + if (DEBUG) { + Log.i(mTag, "Sent : " + ByteArrayConverter.byteArrayToHexString(ioctlData)); + Log.i(mTag, "Received : " + ByteArrayConverter.byteArrayToHexString(rsp)); + } + return rsp; + } + /** * Checks if the application is authorized to receive the transaction event. */ @@ -923,8 +995,25 @@ public class Terminal { if (session == null) { throw new NullPointerException("session is null"); } - mSessions.remove(session); + if (mName.equals("eSE1")) { + synchronized (mLock) { + String callingPackageName = mService.getPackageManager().getNameForUid( + Binder.getCallingUid()); + String hash = getPublicKeySHA1(callingPackageName); + if (hash == null) { + throw new NullPointerException("hash is null"); + } + try { + Log.i(mTag, "removeSession(): Package Name:" + callingPackageName + " SHA:" + hash); + nxpEseHalIoctlInternal(HAL_ESE_IOCTL_OMAPI_RELEASE_ESE_SESSION, hexString2ByteArray(hash)); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + synchronized (mLock) { + mSessions.remove(session); if (mSessions.size() == 0) { mDefaultApplicationSelectedOnBasicChannel = true; } @@ -939,6 +1028,26 @@ public class Terminal { } synchronized (mLock) { + if (mName.equals("eSE1")) { + String callingPackageName = mService.getPackageManager().getNameForUid( + Binder.getCallingUid()); + String hash = getPublicKeySHA1(callingPackageName); + if (hash == null) { + return null; + } + byte[] rsp = new byte[]{ (byte)(256) }; + try { + Log.i(mTag, "openSession(): Package Name:" + callingPackageName + " SHA:" + hash); + rsp = nxpEseHalIoctlInternal(HAL_ESE_IOCTL_OMAPI_TRY_GET_ESE_SESSION, hexString2ByteArray(hash)); + } catch (Exception e) { + e.printStackTrace(); + } + if ((rsp[8] == 0x3A) && (rsp[9] == 0x00)) { + throw new ServiceSpecificException(NFC_IN_USE, + "Secure Element session can not be established, Nfc in use."); + } + } + SecureElementSession session = mService.new SecureElementSession(this); mSessions.add(session); return session; @@ -953,5 +1062,66 @@ public class Terminal { public boolean reset() { return Terminal.this.reset(); } + + private String getPublicKeySHA1(String pkg) { + PackageManager pm = mContext.getPackageManager(); + PackageInfo packageInfo = null; + try { + packageInfo = pm.getPackageInfo(pkg, PackageManager.GET_SIGNATURES); + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + Signature[] signatures = packageInfo.signatures; + byte[] cert = signatures[0].toByteArray(); + InputStream input = new ByteArrayInputStream(cert); + CertificateFactory certfact = null; + try { + certfact = CertificateFactory.getInstance("X509"); + } catch (CertificateException e) { + e.printStackTrace(); + } + X509Certificate x509cert = null; + try { + x509cert = (X509Certificate) certfact.generateCertificate(input); + } catch (CertificateException e) { + e.printStackTrace(); + } + String hexSHA1 = null; + try { + MessageDigest md = MessageDigest.getInstance("SHA1"); + if (x509cert == null) { + return null; + } + byte[] publicKey = md.digest(x509cert.getEncoded()); + hexSHA1 = byteArray2HexString(publicKey); + } catch (NoSuchAlgorithmException e1) { + e1.printStackTrace(); + } catch (CertificateEncodingException e) { + e.printStackTrace(); + } + return hexSHA1; + } + + public String byteArray2HexString(byte[] arr) { + StringBuilder str = new StringBuilder(arr.length * 2); + for (int i = 0; i < arr.length; i++) { + String h = Integer.toHexString(arr[i]); + int l = h.length(); + if (l == 1) h = "0" + h; + if (l > 2) h = h.substring(l - 2, l); + str.append(h.toUpperCase()); + } + return str.toString(); + } + + public byte[] hexString2ByteArray(String s) { + int len = s.length(); + byte[] data = new byte[len / 2]; + for (int i = 0; i < len; i += 2) { + data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + + Character.digit(s.charAt(i+1), 16)); + } + return data; + } } } diff --git a/src/com/android/se/security/gpac/AID_REF_DO.java b/src/com/android/se/security/gpac/AID_REF_DO.java index 70bddfb..48d5c74 100644 --- a/src/com/android/se/security/gpac/AID_REF_DO.java +++ b/src/com/android/se/security/gpac/AID_REF_DO.java @@ -105,6 +105,8 @@ public class AID_REF_DO extends BerTlv { */ @Override public void interpret() throws ParserException { + mAid = null; + byte[] data = getRawData(); int index = getValueIndex(); |