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 * Copyright 2012 Giesecke & Devrient GmbH. 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 package com.android.se.security.gpac; 36 37 import java.io.ByteArrayOutputStream; 38 import java.io.IOException; 39 import java.util.Arrays; 40 41 /** 42 * The AID-REF-DO is used for retrieving and storing the corresponding access rules for an SE 43 * application (which is identified by its AID) from and to the ARA. Two different AID reference 44 * data objects exist and one of these can be chosen and applied for a GET DATA and STORE DATA 45 * command 46 */ 47 public class AID_REF_DO extends BerTlv { 48 49 public static final int TAG = 0x4F; 50 public static final int TAG_DEFAULT_APPLICATION = 0xC0; 51 52 private static final byte[] CARRIER_PRIVILEGE_AID = {(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, 53 (byte) 0xFF, (byte) 0xFF, (byte) 0xFF}; 54 private byte[] mAid = new byte[0]; 55 AID_REF_DO(byte[] rawData, int tag, int valueIndex, int valueLength)56 public AID_REF_DO(byte[] rawData, int tag, int valueIndex, int valueLength) { 57 super(rawData, tag, valueIndex, valueLength); 58 } 59 AID_REF_DO(int tag, byte[] aid)60 public AID_REF_DO(int tag, byte[] aid) { 61 super(aid, tag, 0, (aid == null ? 0 : aid.length)); 62 if (aid != null) mAid = aid; 63 } 64 AID_REF_DO(int tag)65 public AID_REF_DO(int tag) { 66 super(null, tag, 0, 0); 67 } 68 69 /** 70 * Comapares two AID_REF_DO objects and returns true if they are equal 71 */ equals(AID_REF_DO obj1, AID_REF_DO obj2)72 public static boolean equals(AID_REF_DO obj1, AID_REF_DO obj2) { 73 if (obj1 == null) { 74 return (obj2 == null) ? true : false; 75 } 76 return obj1.equals(obj2); 77 } 78 79 @Override toString()80 public String toString() { 81 StringBuilder b = new StringBuilder(); 82 ByteArrayOutputStream out = new ByteArrayOutputStream(); 83 b.append("AID_REF_DO: "); 84 try { 85 this.build(out); 86 b.append(BerTlv.toHex(out.toByteArray())); 87 } catch (Exception e) { 88 b.append(e.getLocalizedMessage()); 89 } 90 return b.toString(); 91 } 92 getAid()93 public byte[] getAid() { 94 return mAid; 95 } 96 97 /** 98 * Tags: C0 -> Length: 0 -> Default selected application (all channels) 4F -> Length: 0 or 5 - 99 * 16 100 * bytes 101 * 102 * <p>Value: AID: identifies a specific application Empty: refers to all SE applications 103 * 104 * <p>Length: 5-16 for an AID according to ISO/IEC7816-5 0 for empty value field 105 */ 106 @Override interpret()107 public void interpret() throws ParserException { 108 byte[] data = getRawData(); 109 int index = getValueIndex(); 110 111 if (getTag() == TAG_DEFAULT_APPLICATION) { 112 if (getValueLength() != 0) { 113 throw new ParserException("Invalid value length for AID-REF-DO!"); 114 } 115 } else if (getTag() == TAG) { 116 117 // sanity checks 118 if ((getValueLength() < 5 || getValueLength() > 16) && getValueLength() != 0) { 119 throw new ParserException("Invalid value length for AID-REF-DO!"); 120 } 121 122 if (index + getValueLength() > data.length) { 123 throw new ParserException("Not enough data for AID-REF-DO!"); 124 } 125 126 mAid = new byte[getValueLength()]; 127 System.arraycopy(data, index, mAid, 0, getValueLength()); 128 129 } else { 130 throw new ParserException("Invalid Tag for AID-REF-DO!"); 131 } 132 } 133 134 /** 135 * Tags: C0 -> Length: 0 -> Default selected application (all channels) 4F -> Length: 0 or 5 - 136 * 16 137 * bytes 138 * 139 * <p>Value: AID: identifies a specific application Empty: refers to all SE applications 140 * 141 * <p>Length: 5-16 for an AID according to ISO/IEC7816-5 0 for empty value field 142 */ 143 @Override build(ByteArrayOutputStream stream)144 public void build(ByteArrayOutputStream stream) throws DO_Exception { 145 146 if (getTag() == TAG_DEFAULT_APPLICATION) { 147 if (mAid.length > 0) { 148 throw new DO_Exception("No value allowed for default selected application!"); 149 } 150 stream.write(getTag()); 151 stream.write(0x00); 152 } else if (getTag() == TAG) { 153 154 // sanity check 155 if (getValueLength() != 0) { 156 if (getValueLength() < 5 || getValueLength() > 16) { 157 throw new DO_Exception("Invalid length of AID!"); 158 } 159 } 160 161 stream.write(getTag()); 162 stream.write(mAid.length); 163 try { 164 stream.write(mAid); 165 } catch (IOException ioe) { 166 throw new DO_Exception("AID could not be written!"); 167 } 168 } else { 169 throw new DO_Exception("AID-REF-DO must either be C0 or 4F!"); 170 } 171 } 172 173 @Override equals(Object obj)174 public boolean equals(Object obj) { 175 if (obj instanceof AID_REF_DO) { 176 AID_REF_DO aid_ref_do = (AID_REF_DO) obj; 177 if (getTag() == aid_ref_do.getTag()) { 178 return Arrays.equals(mAid, aid_ref_do.mAid); 179 } 180 } 181 return false; 182 } 183 184 /** Checks if the AID_REF_DO is a Carrier Privilege rule */ isCarrierPrivilege()185 public boolean isCarrierPrivilege() { 186 return Arrays.equals(mAid, CARRIER_PRIVILEGE_AID); 187 } 188 189 /** Creates a Carrier Privilege AID_REF_DO */ createCarrierPrivilegeAid()190 public static AID_REF_DO createCarrierPrivilegeAid() { 191 return new AID_REF_DO(AID_REF_DO.TAG, CARRIER_PRIVILEGE_AID); 192 } 193 } 194