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) 2017, The Linux Foundation. 18 */ 19 20 /* 21 * Contributed by: Giesecke & Devrient GmbH. 22 */ 23 24 package com.android.se.internal; 25 26 import android.content.Context; 27 import android.content.pm.PackageManager; 28 29 import java.security.AccessControlException; 30 31 /** Util class for byte[] operations */ 32 public class Util { 33 34 public static final byte END = -1; 35 36 /** Returns a new array containing both the arrays appended */ mergeBytes(byte[] array1, byte[] array2)37 public static byte[] mergeBytes(byte[] array1, byte[] array2) { 38 byte[] data = new byte[array1.length + array2.length]; 39 System.arraycopy(array1, 0, data, 0, array1.length); 40 System.arraycopy(array2, 0, data, array1.length, array2.length); 41 return data; 42 } 43 44 /** Extracts the required bytes from the array */ getMid(byte[] array, int start, int length)45 public static byte[] getMid(byte[] array, int start, int length) { 46 byte[] data = new byte[length]; 47 System.arraycopy(array, start, data, 0, length); 48 return data; 49 } 50 51 /** 52 * Returns a concatenated response. 53 * 54 * @param r1 the first part of the response. 55 * @param r2 the second part of the response. 56 * @param length the number of bytes of the second part to be appended. 57 * @return a concatenated response. 58 */ appendResponse(byte[] r1, byte[] r2, int length)59 public static byte[] appendResponse(byte[] r1, byte[] r2, int length) { 60 byte[] rsp = new byte[r1.length + length]; 61 System.arraycopy(r1, 0, rsp, 0, r1.length); 62 System.arraycopy(r2, 0, rsp, r1.length, length); 63 return rsp; 64 } 65 66 /** 67 * Creates a formatted exception message. 68 * 69 * @param commandName the name of the command. <code>null</code> if not specified. 70 * @param sw the response status word. 71 * @return a formatted exception message. 72 */ createMessage(String commandName, int sw)73 public static String createMessage(String commandName, int sw) { 74 StringBuilder message = new StringBuilder(); 75 if (commandName != null) { 76 message.append(commandName).append(" "); 77 } 78 message.append("SW1/2 error: "); 79 message.append(Integer.toHexString(sw | 0x10000).substring(1)); 80 return message.toString(); 81 } 82 83 /** 84 * Creates a formatted exception message. 85 * 86 * @param commandName the name of the command. <code>null</code> if not specified. 87 * @param message the message to be formatted. 88 * @return a formatted exception message. 89 */ createMessage(String commandName, String message)90 public static String createMessage(String commandName, String message) { 91 if (commandName == null) { 92 return message; 93 } 94 return commandName + " " + message; 95 } 96 97 /** 98 * Get package name from the user id. 99 * 100 * <p>This shall fix the problem the issue that process name != package name due to 101 * anndroid:process attribute in manifest file. 102 * 103 * <p>But this call is not really secure either since a uid can be shared between one and more 104 * apks 105 * 106 * @return The first package name associated with this uid. 107 */ getPackageNameFromCallingUid(Context context, int uid)108 public static String getPackageNameFromCallingUid(Context context, int uid) { 109 PackageManager packageManager = context.getPackageManager(); 110 if (packageManager != null) { 111 String[] packageName = packageManager.getPackagesForUid(uid); 112 if (packageName != null && packageName.length > 0) { 113 return packageName[0]; 114 } 115 } 116 throw new AccessControlException("Caller PackageName can not be determined"); 117 } 118 119 /** 120 * Returns a copy of the given CLA byte where the channel number bits are set as specified by 121 * the 122 * given channel number See GlobalPlatform Card Specification 2.2.0.7: 11.1.4 Class Byte 123 * Coding. 124 * 125 * @param cla the CLA byte. Won't be modified 126 * @param channelNumber within [0..3] (for first interindustry class byte coding) or [4..19] 127 * (for 128 * further interindustry class byte coding) 129 * @return the CLA byte with set channel number bits. The seventh bit indicating the used coding 130 * (first/further interindustry class byte coding) might be modified 131 */ setChannelToClassByte(byte cla, int channelNumber)132 public static byte setChannelToClassByte(byte cla, int channelNumber) { 133 if (channelNumber < 4) { 134 // b7 = 0 indicates the first interindustry class byte coding 135 cla = (byte) ((cla & 0xBC) | channelNumber); 136 } else if (channelNumber < 20) { 137 // b7 = 1 indicates the further interindustry class byte coding 138 boolean isSM = (((cla & 0x40) == 0x00) && ((cla & 0x0C) != 0)); 139 cla = (byte) ((cla & 0xB0) | 0x40 | (channelNumber - 4)); 140 if (isSM) { 141 cla |= 0x20; 142 } 143 } else { 144 throw new IllegalArgumentException("Channel number must be within [0..19]"); 145 } 146 return cla; 147 } 148 149 /** 150 * Clear the channel number. 151 * 152 * @return the cla without channel number 153 */ clearChannelNumber(byte cla)154 public static byte clearChannelNumber(byte cla) { 155 // bit 7 determines which standard is used 156 boolean isFirstInterindustryClassByteCoding = (cla & 0x40) == 0x00; 157 158 if (isFirstInterindustryClassByteCoding) { 159 // First Interindustry Class Byte Coding 160 // see 11.1.4.1: channel number is encoded in the 2 rightmost bits 161 return (byte) (cla & 0xFC); 162 } else { 163 // Further Interindustry Class Byte Coding 164 // see 11.1.4.2: channel number is encoded in the 4 rightmost bits 165 return (byte) (cla & 0xF0); 166 } 167 } 168 169 /** 170 * Extracts the channel number from a CLA byte. Specified in GlobalPlatform Card Specification 171 * 2.2.0.7: 11.1.4 Class Byte Coding. 172 * 173 * @param cla the command's CLA byte 174 * @return the channel number within [0x00..0x0F] 175 */ parseChannelNumber(byte cla)176 public static int parseChannelNumber(byte cla) { 177 // bit 7 determines which standard is used 178 boolean isFirstInterindustryClassByteCoding = (cla & 0x40) == 0x00; 179 180 if (isFirstInterindustryClassByteCoding) { 181 // First Interindustry Class Byte Coding 182 // see 11.1.4.1: channel number is encoded in the 2 rightmost bits 183 return cla & 0x03; 184 } else { 185 // Further Interindustry Class Byte Coding 186 // see 11.1.4.2: channel number is encoded in the 4 rightmost bits 187 return (cla & 0x0F) + 4; 188 } 189 } 190 } 191