summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoralk3pInjection <webmaster@raspii.tech>2021-09-14 11:26:25 +0800
committeralk3pInjection <webmaster@raspii.tech>2021-09-14 11:26:25 +0800
commit7ca989b67fb2686cbf4af249c8f3641cbcba2932 (patch)
tree8a944cc08c24ea9710b75b973cf12ef8bdd61bf0
parent734b7eb48b7deb06c45370a6120ca5487ce6dedd (diff)
parent2fa1d5140d8e614c7f18c9d3aa4d4f8ede6dd077 (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.bp3
-rw-r--r--src/com/android/se/SecureElementService.java18
-rw-r--r--src/com/android/se/Terminal.java184
-rw-r--r--src/com/android/se/security/gpac/AID_REF_DO.java2
4 files changed, 195 insertions, 12 deletions
diff --git a/Android.bp b/Android.bp
index f7941f9..1b9d30c 100644
--- a/Android.bp
+++ b/Android.bp
@@ -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();