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 byte[] mAid = new byte[0]; 53 54 public AID_REF_DO(byte[] rawData, int tag, int valueIndex, int valueLength) { 55 super(rawData, tag, valueIndex, valueLength); 56 } 57 58 public AID_REF_DO(int tag, byte[] aid) { 59 super(aid, tag, 0, (aid == null ? 0 : aid.length)); 60 if (aid != null) mAid = aid; 61 } 62 63 public AID_REF_DO(int tag) { 64 super(null, tag, 0, 0); 65 } 66 67 /** 68 * Comapares two AID_REF_DO objects and returns true if they are equal 69 */ 70 public static boolean equals(AID_REF_DO obj1, AID_REF_DO obj2) { 71 if (obj1 == null) { 72 return (obj2 == null) ? true : false; 73 } 74 return obj1.equals(obj2); 75 } 76 77 @Override 78 public String toString() { 79 StringBuilder b = new StringBuilder(); 80 ByteArrayOutputStream out = new ByteArrayOutputStream(); 81 b.append("AID_REF_DO: "); 82 try { 83 this.build(out); 84 b.append(BerTlv.toHex(out.toByteArray())); 85 } catch (Exception e) { 86 b.append(e.getLocalizedMessage()); 87 } 88 return b.toString(); 89 } 90 91 public byte[] getAid() { 92 return mAid; 93 } 94 95 /** 96 * Tags: C0 -> Length: 0 -> Default selected application (all channels) 4F -> Length: 0 or 5 - 97 * 16 98 * bytes 99 * 100 * <p>Value: AID: identifies a specific application Empty: refers to all SE applications 101 * 102 * <p>Length: 5-16 for an AID according to ISO/IEC7816-5 0 for empty value field 103 */ 104 @Override 105 public void interpret() throws ParserException { 106 107 mAid = null; 108 109 byte[] data = getRawData(); 110 int index = getValueIndex(); 111 112 if (getTag() == TAG_DEFAULT_APPLICATION) { 113 if (getValueLength() != 0) { 114 throw new ParserException("Invalid value length for AID-REF-DO!"); 115 } 116 } else if (getTag() == TAG) { 117 118 // sanity checks 119 if ((getValueLength() < 5 || getValueLength() > 16) && getValueLength() != 0) { 120 throw new ParserException("Invalid value length for AID-REF-DO!"); 121 } 122 123 if (index + getValueLength() > data.length) { 124 throw new ParserException("Not enough data for AID-REF-DO!"); 125 } 126 127 mAid = new byte[getValueLength()]; 128 System.arraycopy(data, index, mAid, 0, getValueLength()); 129 130 } else { 131 throw new ParserException("Invalid Tag for AID-REF-DO!"); 132 } 133 } 134 135 /** 136 * Tags: C0 -> Length: 0 -> Default selected application (all channels) 4F -> Length: 0 or 5 - 137 * 16 138 * bytes 139 * 140 * <p>Value: AID: identifies a specific application Empty: refers to all SE applications 141 * 142 * <p>Length: 5-16 for an AID according to ISO/IEC7816-5 0 for empty value field 143 */ 144 @Override 145 public void build(ByteArrayOutputStream stream) throws DO_Exception { 146 147 if (getTag() == TAG_DEFAULT_APPLICATION) { 148 if (mAid.length > 0) { 149 throw new DO_Exception("No value allowed for default selected application!"); 150 } 151 stream.write(getTag()); 152 stream.write(0x00); 153 } else if (getTag() == TAG) { 154 155 // sanity check 156 if (getValueLength() != 0) { 157 if (getValueLength() < 5 || getValueLength() > 16) { 158 throw new DO_Exception("Invalid length of AID!"); 159 } 160 } 161 162 stream.write(getTag()); 163 stream.write(mAid.length); 164 try { 165 stream.write(mAid); 166 } catch (IOException ioe) { 167 throw new DO_Exception("AID could not be written!"); 168 } 169 } else { 170 throw new DO_Exception("AID-REF-DO must either be C0 or 4F!"); 171 } 172 } 173 174 @Override 175 public boolean equals(Object obj) { 176 if (obj instanceof AID_REF_DO) { 177 AID_REF_DO aid_ref_do = (AID_REF_DO) obj; 178 if (getTag() == aid_ref_do.getTag()) { 179 return Arrays.equals(mAid, aid_ref_do.mAid); 180 } 181 } 182 return false; 183 } 184 } 185