1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 /*
17  * Copyright (c) 2015-2017, The Linux Foundation.
18  */
19 
20 /*
21  * Copyright (C) 2011 Deutsche Telekom, A.G.
22  *
23  * Licensed under the Apache License, Version 2.0 (the "License");
24  * you may not use this file except in compliance with the License.
25  * You may obtain a copy of the License at
26  *
27  *      http://www.apache.org/licenses/LICENSE-2.0
28  *
29  * Unless required by applicable law or agreed to in writing, software
30  * distributed under the License is distributed on an "AS IS" BASIS,
31  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
32  * See the License for the specific language governing permissions and
33  * limitations under the License.
34  */
35 
36 /*
37  * Contributed by: Giesecke & Devrient GmbH.
38  */
39 
40 package com.android.se.security.arf;
41 
42 import android.util.Log;
43 
44 import com.android.se.Channel;
45 import com.android.se.Terminal;
46 import com.android.se.security.ChannelAccess;
47 import com.android.se.security.arf.pkcs15.EF;
48 import com.android.se.security.gpac.AID_REF_DO;
49 import com.android.se.security.gpac.Hash_REF_DO;
50 import com.android.se.security.gpac.REF_DO;
51 
52 import java.io.IOException;
53 import java.util.MissingResourceException;
54 import java.util.NoSuchElementException;
55 
56 /**
57  * Provides high-level functions for SE communication
58  */
59 public class SecureElement {
60     public final String mTag = "SecureElement-ARF";
61     // Logical channel used for SE communication (optional)
62     private Channel mArfChannel = null;
63     // Handle to a built-in "Secure Element"
64     private Terminal mTerminalHandle = null;
65     // Arf Controller within the SCAPI handler
66     private ArfController mArfHandler = null;
67 
68     /**
69      * Constructor
70      *
71      * @param arfHandler - handle to the owning arf controller object
72      * @param handle     - handle to the SE terminal to be accessed.
73      */
SecureElement(ArfController arfHandler, Terminal handle)74     public SecureElement(ArfController arfHandler, Terminal handle) {
75         mTerminalHandle = handle;
76         mArfHandler = arfHandler;
77     }
78 
79     /**
80      * Transmits ADPU commands
81      *
82      * @param cmd APDU command
83      * @return Data returned by the APDU command
84      */
exchangeAPDU(EF ef, byte[] cmd)85     public byte[] exchangeAPDU(EF ef, byte[] cmd) throws IOException, SecureElementException {
86         try {
87             return mArfChannel.transmit(cmd);
88         } catch (IOException e) {
89             // Communication error happened while the terminal sending a command.
90             throw e;
91         } catch (Exception e) {
92             throw new SecureElementException(
93                     "Secure Element access error " + e.getLocalizedMessage());
94         }
95     }
96 
97     /**
98      * Opens a logical channel to ARF Applet or ADF
99      *
100      * @param aid Applet identifier
101      * @return Handle to "Logical Channel" allocated by the SE; <code>0</code> if error occurred
102      */
openLogicalArfChannel(byte[] aid)103     public Channel openLogicalArfChannel(byte[] aid) throws IOException, MissingResourceException,
104             NoSuchElementException {
105         try {
106             mArfChannel = mTerminalHandle.openLogicalChannelWithoutChannelAccess(aid);
107             if (mArfChannel == null) {
108                 throw new MissingResourceException("No channel was available", "", "");
109             }
110             setUpChannelAccess(mArfChannel);
111             return mArfChannel;
112         } catch (IOException | MissingResourceException | NoSuchElementException e) {
113             throw e;
114         } catch (Exception e) {
115             Log.e(mTag, "Error opening logical channel " + e.getLocalizedMessage());
116             mArfChannel = null;
117             return null;
118         }
119     }
120 
121     /**
122      * Closes a logical channel previously allocated by the SE
123      */
closeArfChannel()124     public void closeArfChannel() {
125         try {
126             if (mArfChannel != null) {
127                 mArfChannel.close();
128                 mArfChannel = null;
129             }
130 
131         } catch (Exception e) {
132             Log.e(mTag, "Error closing channel " + e.getLocalizedMessage());
133         }
134     }
135 
136     /**
137      * Set up channel access to allow, so that PKCS15 files can be read.
138      */
setUpChannelAccess(Channel channel)139     private void setUpChannelAccess(Channel channel) {
140         // set access conditions to access ARF.
141         ChannelAccess arfChannelAccess = new ChannelAccess();
142         arfChannelAccess.setAccess(ChannelAccess.ACCESS.ALLOWED, "");
143         arfChannelAccess.setApduAccess(ChannelAccess.ACCESS.ALLOWED);
144         channel.setChannelAccess(arfChannelAccess);
145     }
146 
147     /** Fetches the Refresh Tag */
getRefreshTag()148     public byte[] getRefreshTag() {
149         if (mArfHandler != null) {
150             return mArfHandler.getAccessRuleCache().getRefreshTag();
151         }
152         return null;
153     }
154 
155     /** Sets the given Refresh Tag */
setRefreshTag(byte[] refreshTag)156     public void setRefreshTag(byte[] refreshTag) {
157         if (mArfHandler != null) {
158             mArfHandler.getAccessRuleCache().setRefreshTag(refreshTag);
159         }
160     }
161 
162     /** Addsthe Access Rule to the Cache */
putAccessRule( AID_REF_DO aidRefDo, Hash_REF_DO hashRefDo, ChannelAccess channelAccess)163     public void putAccessRule(
164             AID_REF_DO aidRefDo, Hash_REF_DO hashRefDo, ChannelAccess channelAccess) {
165 
166         REF_DO ref_do = new REF_DO(aidRefDo, hashRefDo);
167         mArfHandler.getAccessRuleCache().putWithMerge(ref_do, channelAccess);
168     }
169 
170     /** Resets the Access Rule Cache */
resetAccessRules()171     public void resetAccessRules() {
172         this.mArfHandler.getAccessRuleCache().reset();
173     }
174 
175     /** Clears the Access Rule Cache */
clearAccessRuleCache()176     public void clearAccessRuleCache() {
177         this.mArfHandler.getAccessRuleCache().clearCache();
178     }
179 }
180