summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYoshiaki Naka <yoshiaki.naka@sony.com>2018-02-20 15:43:39 +0900
committerRuchi Kandoi <kandoiruchi@google.com>2018-03-06 13:33:12 -0800
commit3e785e28c90aefc1a5c09f089684fdd48633fa32 (patch)
tree8b83d745a05bfd097b00df08bd8cd1faf9a83f20
parente203d59e3de287889ff65a79abbcd74fd8e5c3b5 (diff)
downloadSecureElement-3e785e28c90aefc1a5c09f089684fdd48633fa32.tar.gz
IOError happened while opening channel for retrieving access rules
IOException shall be thrown to client application if communication problem happens between the terminal and the secure element while the terminal retrieves the access rules. That is the expected behavior described in the clause 6.2.7 (h) of Open Mobile API Specification. Bug: 74094356 Test: OMAPI TC 6.4.7 ID8 and TC 6.4.10 ID8 pass with this change. Change-Id: I5baae8356d2ab2f61b2e45647d7e6b6a297b2483 (cherry picked from commit 174fb5cc697fd159b2167091e6984c2172164dee)
-rw-r--r--[-rwxr-xr-x]src/com/android/se/SecureElementService.java24
-rw-r--r--[-rwxr-xr-x]src/com/android/se/Terminal.java76
-rw-r--r--[-rwxr-xr-x]src/com/android/se/security/AccessControlEnforcer.java24
-rw-r--r--[-rwxr-xr-x]src/com/android/se/security/ara/AraController.java3
-rw-r--r--[-rwxr-xr-x]src/com/android/se/security/arf/ArfController.java4
-rw-r--r--[-rwxr-xr-x]src/com/android/se/security/arf/PKCS15/PKCS15Handler.java12
-rw-r--r--[-rwxr-xr-x]src/com/android/se/security/arf/SecureElement.java5
7 files changed, 101 insertions, 47 deletions
diff --git a/src/com/android/se/SecureElementService.java b/src/com/android/se/SecureElementService.java
index 7ecaaf6..7519fc3 100755..100644
--- a/src/com/android/se/SecureElementService.java
+++ b/src/com/android/se/SecureElementService.java
@@ -31,16 +31,19 @@ import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.ServiceSpecificException;
import android.se.omapi.ISecureElementChannel;
import android.se.omapi.ISecureElementListener;
import android.se.omapi.ISecureElementReader;
import android.se.omapi.ISecureElementService;
import android.se.omapi.ISecureElementSession;
+import android.se.omapi.SEService;
import android.util.Log;
import com.android.se.Terminal.SecureElementReader;
import java.io.FileDescriptor;
+import java.io.IOException;
import java.io.PrintWriter;
import java.security.AccessControlException;
import java.util.ArrayList;
@@ -264,8 +267,15 @@ public final class SecureElementService extends Service {
}
String packageName = getPackageNameFromCallingUid(Binder.getCallingUid());
- Channel channel = mReader.getTerminal().openBasicChannel(this, aid,
- p2, listener, packageName, Binder.getCallingPid());
+ Channel channel = null;
+
+ try {
+ channel = mReader.getTerminal().openBasicChannel(this, aid, p2, listener,
+ packageName, Binder.getCallingPid());
+ } catch (IOException e) {
+ throw new ServiceSpecificException(SEService.IO_ERROR, e.getMessage());
+ }
+
if (channel == null) {
Log.i(mTag, "OpenBasicChannel() - returning null");
return null;
@@ -291,8 +301,14 @@ public final class SecureElementService extends Service {
}
String packageName = getPackageNameFromCallingUid(Binder.getCallingUid());
- Channel channel = mReader.getTerminal().openLogicalChannel(this, aid, p2,
- listener, packageName, Binder.getCallingPid());
+ Channel channel = null;
+
+ try {
+ channel = mReader.getTerminal().openLogicalChannel(this, aid, p2, listener,
+ packageName, Binder.getCallingPid());
+ } catch (IOException e) {
+ throw new ServiceSpecificException(SEService.IO_ERROR, e.getMessage());
+ }
if (channel == null) {
Log.i(mTag, "openLogicalChannel() - returning null");
diff --git a/src/com/android/se/Terminal.java b/src/com/android/se/Terminal.java
index 2733a6e..dd28917 100755..100644
--- a/src/com/android/se/Terminal.java
+++ b/src/com/android/se/Terminal.java
@@ -42,6 +42,7 @@ import com.android.se.internal.ByteArrayConverter;
import com.android.se.security.AccessControlEnforcer;
import com.android.se.security.ChannelAccess;
+import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
@@ -237,12 +238,13 @@ public class Terminal {
* Opens a Basic Channel with the given AID and P2 paramters
*/
public Channel openBasicChannel(SecureElementSession session, byte[] aid, byte p2,
- ISecureElementListener listener, String packageName,
- int pid) throws RemoteException {
+ ISecureElementListener listener, String packageName, int pid) throws IOException {
if (aid != null && aid.length == 0) {
aid = null;
} else if (aid != null && (aid.length < 5 || aid.length > 16)) {
throw new IllegalArgumentException("AID out of range");
+ } else if (!mIsConnected) {
+ throw new IOException("Secure Element is not connected");
}
Log.w(mTag, "Enable access control on basic channel for " + packageName);
@@ -260,22 +262,28 @@ public class Terminal {
ArrayList<byte[]> responseList = new ArrayList<byte[]>();
byte[] status = new byte[1];
- mSEHal.openBasicChannel(byteArrayToArrayList(aid), p2,
- new ISecureElement.openBasicChannelCallback() {
- @Override
- public void onValues(ArrayList<Byte> responseObject, byte halStatus) {
- status[0] = halStatus;
- responseList.add(arrayListToByteArray(responseObject));
- return;
- }
- });
+
+ try {
+ mSEHal.openBasicChannel(byteArrayToArrayList(aid), p2,
+ new ISecureElement.openBasicChannelCallback() {
+ @Override
+ public void onValues(ArrayList<Byte> responseObject, byte halStatus) {
+ status[0] = halStatus;
+ responseList.add(arrayListToByteArray(responseObject));
+ return;
+ }
+ });
+ } catch (RemoteException e) {
+ throw new IOException(e.getMessage());
+ }
+
byte[] selectResponse = responseList.get(0);
if (status[0] == SecureElementStatus.CHANNEL_NOT_AVAILABLE) {
return null;
} else if (status[0] == SecureElementStatus.UNSUPPORTED_OPERATION) {
throw new UnsupportedOperationException("OpenBasicChannel() failed");
} else if (status[0] == SecureElementStatus.IOERROR) {
- throw new ServiceSpecificException(SEService.IO_ERROR, "OpenBasicChannel() failed");
+ throw new IOException("OpenBasicChannel() failed");
} else if (status[0] == SecureElementStatus.NO_SUCH_ELEMENT_ERROR) {
throw new ServiceSpecificException(SEService.NO_SUCH_ELEMENT_ERROR,
"OpenBasicChannel() failed");
@@ -303,24 +311,21 @@ public class Terminal {
/**
* Opens a logical Channel without Channel Access initialization.
*/
- public Channel openLogicalChannelWithoutChannelAccess(byte[] aid) throws RemoteException {
+ public Channel openLogicalChannelWithoutChannelAccess(byte[] aid) throws IOException {
return openLogicalChannel(null, aid, (byte) 0x00, null, null, 0);
}
/**
* Opens a logical Channel with AID.
*/
- public Channel openLogicalChannel(
- SecureElementSession session, byte[] aid, byte p2,
- ISecureElementListener listener, String packageName,
- int pid) throws RemoteException {
+ public Channel openLogicalChannel(SecureElementSession session, byte[] aid, byte p2,
+ ISecureElementListener listener, String packageName, int pid) throws IOException {
if (aid != null && aid.length == 0) {
aid = null;
} else if (aid != null && (aid.length < 5 || aid.length > 16)) {
throw new IllegalArgumentException("AID out of range");
} else if (!mIsConnected) {
- throw new ServiceSpecificException(SEService.IO_ERROR,
- "Secure Element is not connected");
+ throw new IOException("Secure Element is not connected");
}
ChannelAccess channelAccess = null;
@@ -332,22 +337,27 @@ public class Terminal {
synchronized (mLock) {
LogicalChannelResponse[] responseArray = new LogicalChannelResponse[1];
byte[] status = new byte[1];
- mSEHal.openLogicalChannel(byteArrayToArrayList(aid), p2,
- new ISecureElement.openLogicalChannelCallback() {
- @Override
- public void onValues(LogicalChannelResponse response, byte halStatus) {
- status[0] = halStatus;
- responseArray[0] = response;
- return;
- }
- });
+
+ try {
+ mSEHal.openLogicalChannel(byteArrayToArrayList(aid), p2,
+ new ISecureElement.openLogicalChannelCallback() {
+ @Override
+ public void onValues(LogicalChannelResponse response, byte halStatus) {
+ status[0] = halStatus;
+ responseArray[0] = response;
+ return;
+ }
+ });
+ } catch (RemoteException e) {
+ throw new IOException(e.getMessage());
+ }
+
if (status[0] == SecureElementStatus.CHANNEL_NOT_AVAILABLE) {
return null;
} else if (status[0] == SecureElementStatus.UNSUPPORTED_OPERATION) {
throw new UnsupportedOperationException("OpenLogicalChannel() failed");
} else if (status[0] == SecureElementStatus.IOERROR) {
- throw new ServiceSpecificException(SEService.IO_ERROR,
- "OpenLogicalChannel() failed");
+ throw new IOException("OpenLogicalChannel() failed");
} else if (status[0] == SecureElementStatus.NO_SUCH_ELEMENT_ERROR) {
throw new ServiceSpecificException(SEService.NO_SUCH_ELEMENT_ERROR,
"OpenLogicalChannel() failed");
@@ -499,8 +509,8 @@ public class Terminal {
/**
* Initialize the Access Control and set up the channel access.
*/
- public ChannelAccess setUpChannelAccess(byte[] aid, String packageName,
- boolean checkRefreshTag, int pid) {
+ private ChannelAccess setUpChannelAccess(byte[] aid, String packageName,
+ boolean checkRefreshTag, int pid) throws IOException {
if (mAccessControlEnforcer == null) {
Log.e(mTag, "Access Control Enforcer not properly set up");
initializeAccessControl();
@@ -514,6 +524,8 @@ public class Terminal {
checkRefreshTag);
channelAccess.setCallingPid(pid);
return channelAccess;
+ } catch (IOException e) {
+ throw e;
} catch (Exception e) {
throw new SecurityException("Exception in setUpChannelAccess()" + e);
}
diff --git a/src/com/android/se/security/AccessControlEnforcer.java b/src/com/android/se/security/AccessControlEnforcer.java
index da41956..e6ce5b7 100755..100644
--- a/src/com/android/se/security/AccessControlEnforcer.java
+++ b/src/com/android/se/security/AccessControlEnforcer.java
@@ -51,6 +51,7 @@ import com.android.se.security.ara.AraController;
import com.android.se.security.arf.ArfController;
import java.io.ByteArrayInputStream;
+import java.io.IOException;
import java.io.PrintWriter;
import java.security.AccessControlException;
import java.security.MessageDigest;
@@ -264,7 +265,7 @@ public class AccessControlEnforcer {
/** Sets up the Channel Access for the given Package */
public ChannelAccess setUpChannelAccess(
- byte[] aid, String packageName, boolean checkRefreshTag) {
+ byte[] aid, String packageName, boolean checkRefreshTag) throws IOException {
ChannelAccess channelAccess = null;
// check result of channel access during initialization procedure
if (mInitialChannelAccess.getAccess() == ChannelAccess.ACCESS.DENIED) {
@@ -291,7 +292,7 @@ public class AccessControlEnforcer {
}
private synchronized ChannelAccess internal_setUpChannelAccess(byte[] aid,
- String packageName, boolean checkRefreshTag) {
+ String packageName, boolean checkRefreshTag) throws IOException {
if (packageName == null || packageName.isEmpty()) {
throw new AccessControlException("package names must be specified");
}
@@ -307,6 +308,8 @@ public class AccessControlEnforcer {
updateAccessRuleIfNeed();
}
return getAccessRule(aid, appCerts);
+ } catch (IOException e) {
+ throw e;
} catch (Throwable exp) {
throw new AccessControlException(exp.getMessage());
}
@@ -378,7 +381,12 @@ public class AccessControlEnforcer {
private synchronized boolean[] internal_isNfcEventAllowed(byte[] aid,
String[] packageNames, boolean checkRefreshTag) {
if (checkRefreshTag) {
- updateAccessRuleIfNeed();
+ try {
+ updateAccessRuleIfNeed();
+ } catch (IOException e) {
+ throw new AccessControlException("Access-Control not found in "
+ + mTerminal.getName());
+ }
}
int i = 0;
@@ -404,18 +412,26 @@ public class AccessControlEnforcer {
return nfcEventFlags;
}
- private void updateAccessRuleIfNeed() {
+ private void updateAccessRuleIfNeed() throws IOException {
if (mUseAra && mAraController != null) {
try {
mAraController.initialize();
mUseArf = false;
mFullAccess = false;
+ } catch (IOException e) {
+ // There was a communication error between the terminal and the SE.
+ // IOError shall be notified to the client application in this case.
+ throw e;
} catch (Exception e) {
throw new AccessControlException("No ARA applet found in " + mTerminal.getName());
}
} else if (mUseArf && mArfController != null) {
try {
mArfController.initialize();
+ } catch (IOException e) {
+ // There was a communication error between the terminal and the SE.
+ // IOError shall be notified to the client application in this case.
+ throw e;
} catch (Exception e) {
Log.e(mTag, e.getMessage());
}
diff --git a/src/com/android/se/security/ara/AraController.java b/src/com/android/se/security/ara/AraController.java
index 680a66b..99b1942 100755..100644
--- a/src/com/android/se/security/ara/AraController.java
+++ b/src/com/android/se/security/ara/AraController.java
@@ -47,6 +47,7 @@ import com.android.se.security.gpac.REF_AR_DO;
import com.android.se.security.gpac.Response_ALL_AR_DO;
import com.android.se.security.gpac.Response_DO_Factory;
+import java.io.IOException;
import java.security.AccessControlException;
import java.util.ArrayList;
import java.util.Iterator;
@@ -84,7 +85,7 @@ public class AraController {
* Initialize the AraController, reads the refresh tag.
* and fetch the access rules
*/
- public synchronized void initialize() throws Exception {
+ public synchronized void initialize() throws IOException {
Channel channel = mTerminal.openLogicalChannelWithoutChannelAccess(getAraMAid());
if (channel == null) {
throw new AccessControlException("could not open channel");
diff --git a/src/com/android/se/security/arf/ArfController.java b/src/com/android/se/security/arf/ArfController.java
index 0257b5d..adaf114 100755..100644
--- a/src/com/android/se/security/arf/ArfController.java
+++ b/src/com/android/se/security/arf/ArfController.java
@@ -38,6 +38,8 @@ import com.android.se.Terminal;
import com.android.se.security.AccessRuleCache;
import com.android.se.security.arf.pkcs15.PKCS15Handler;
+import java.io.IOException;
+
/** Initializes and maintains the ARF access rules of a Secure Element */
public class ArfController {
@@ -52,7 +54,7 @@ public class ArfController {
}
/** Initializes the ARF Rules for the Secure Element */
- public synchronized boolean initialize() {
+ public synchronized boolean initialize() throws IOException {
if (mSecureElement == null) {
mSecureElement = new SecureElement(this, mTerminal);
}
diff --git a/src/com/android/se/security/arf/PKCS15/PKCS15Handler.java b/src/com/android/se/security/arf/PKCS15/PKCS15Handler.java
index 6bee6ea..59e0ba0 100755..100644
--- a/src/com/android/se/security/arf/PKCS15/PKCS15Handler.java
+++ b/src/com/android/se/security/arf/PKCS15/PKCS15Handler.java
@@ -45,6 +45,7 @@ import com.android.se.Channel;
import com.android.se.security.arf.SecureElement;
import com.android.se.security.arf.SecureElementException;
+import java.io.IOException;
import java.security.AccessControlException;
import java.security.cert.CertificateException;
import java.util.MissingResourceException;
@@ -87,7 +88,8 @@ public class PKCS15Handler {
}
/** Updates "Access Control Rules" */
- private boolean updateACRules() throws Exception, PKCS15Exception, SecureElementException {
+ private boolean updateACRules() throws CertificateException, IOException, PKCS15Exception,
+ SecureElementException {
byte[] ACRulesPath = null;
if (!mACMFfound) {
mSEHandle.resetAccessRules();
@@ -133,7 +135,7 @@ public class PKCS15Handler {
/** Initializes "Access Control" entry point [ACMain] */
private void initACEntryPoint()
- throws PKCS15Exception, SecureElementException, CertificateException {
+ throws IOException, PKCS15Exception, SecureElementException, CertificateException {
byte[] DODFPath = null;
for (int ind = 0; ind < CONTAINER_AIDS.length; ind++) {
@@ -171,7 +173,7 @@ public class PKCS15Handler {
* @return <code>true</code> when container is active; <code>false</code> otherwise
*/
private boolean selectACRulesContainer(byte[] aid)
- throws PKCS15Exception, SecureElementException {
+ throws IOException, PKCS15Exception, SecureElementException {
if (aid == null) {
mArfChannel = mSEHandle.openLogicalArfChannel(new byte[]{});
if (mArfChannel != null) {
@@ -216,12 +218,14 @@ public class PKCS15Handler {
*
* @return false if access rules where not read due to constant refresh tag.
*/
- public synchronized boolean loadAccessControlRules(String secureElement) {
+ public synchronized boolean loadAccessControlRules(String secureElement) throws IOException {
mSELabel = secureElement;
Log.i(mTag, "- Loading " + mSELabel + " rules...");
try {
initACEntryPoint();
return updateACRules();
+ } catch (IOException e) {
+ throw e;
} catch (Exception e) {
if (e instanceof MissingResourceException) {
// this indicates that no channel is left for accessing the SE element
diff --git a/src/com/android/se/security/arf/SecureElement.java b/src/com/android/se/security/arf/SecureElement.java
index c5b8da5..134881a 100755..100644
--- a/src/com/android/se/security/arf/SecureElement.java
+++ b/src/com/android/se/security/arf/SecureElement.java
@@ -49,6 +49,7 @@ import com.android.se.security.gpac.AID_REF_DO;
import com.android.se.security.gpac.Hash_REF_DO;
import com.android.se.security.gpac.REF_DO;
+import java.io.IOException;
import java.util.MissingResourceException;
/**
@@ -95,7 +96,7 @@ public class SecureElement {
* @param aid Applet identifier
* @return Handle to "Logical Channel" allocated by the SE; <code>0</code> if error occurred
*/
- public Channel openLogicalArfChannel(byte[] aid) {
+ public Channel openLogicalArfChannel(byte[] aid) throws IOException {
try {
mArfChannel = mTerminalHandle.openLogicalChannelWithoutChannelAccess(aid);
if (mArfChannel == null) {
@@ -103,6 +104,8 @@ public class SecureElement {
}
setUpChannelAccess(mArfChannel);
return mArfChannel;
+ } catch (IOException e) {
+ throw e;
} catch (Exception e) {
if (e instanceof MissingResourceException) {
// this indicates that no channel is left for accessing the SE element