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