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.util.Arrays; 39 40 /** 41 * REF-DO: The REF-DO contains a reference to uniquely assign or identify an access rule for an SE 42 * application (with an AID reference) and for a device application (with a hash reference). 43 */ 44 public class REF_DO extends BerTlv { 45 46 public static final int TAG = 0xE1; 47 48 private AID_REF_DO mAidDo = null; 49 private Hash_REF_DO mHashDo = null; 50 private PKG_REF_DO mPkgDo = null; 51 REF_DO(byte[] rawData, int valueIndex, int valueLength)52 public REF_DO(byte[] rawData, int valueIndex, int valueLength) { 53 super(rawData, TAG, valueIndex, valueLength); 54 } 55 REF_DO(AID_REF_DO aidRefDo, Hash_REF_DO hashRefDo, PKG_REF_DO pkgRefDo)56 public REF_DO(AID_REF_DO aidRefDo, Hash_REF_DO hashRefDo, PKG_REF_DO pkgRefDo) { 57 super(null, TAG, 0, 0); 58 mAidDo = aidRefDo; 59 mHashDo = hashRefDo; 60 mPkgDo = pkgRefDo; 61 } 62 REF_DO(AID_REF_DO aidRefDo, Hash_REF_DO hashRefDo)63 public REF_DO(AID_REF_DO aidRefDo, Hash_REF_DO hashRefDo) { 64 super(null, TAG, 0, 0); 65 mAidDo = aidRefDo; 66 mHashDo = hashRefDo; 67 mPkgDo = null; 68 } 69 70 @Override toString()71 public String toString() { 72 StringBuilder b = new StringBuilder(); 73 b.append("REF_DO: "); 74 if (mAidDo != null) { 75 b.append(mAidDo.toString()); 76 b.append(' '); 77 } 78 if (mHashDo != null) { 79 b.append(mHashDo.toString()); 80 b.append(' '); 81 } 82 if (mPkgDo != null) { 83 b.append(mPkgDo.toString()); 84 } 85 return b.toString(); 86 } 87 getAidDo()88 public AID_REF_DO getAidDo() { 89 return mAidDo; 90 } 91 getHashDo()92 public Hash_REF_DO getHashDo() { 93 return mHashDo; 94 } 95 getPkgDo()96 public PKG_REF_DO getPkgDo() { 97 return mPkgDo; 98 } 99 100 /** 101 * Interpret data. 102 * 103 * <p>Tags: E1 -> Length: n 104 * 105 * <p>Value: 106 * 1. AID-REF-DO | Hash-REF-DO: A concatenation of an AID-REF-DO and a Hash-REF-DO. 107 * 2. Hash-REF-DO or Hash-REF-DO | PKG-REF-DO A concatenation of a Hash-REF-DO and a 108 * PKG-REF-DO. 109 * 110 * <p>Length: n bytes. 111 */ 112 @Override interpret()113 public void interpret() throws ParserException { 114 115 mAidDo = null; 116 mHashDo = null; 117 mPkgDo = null; 118 119 byte[] data = getRawData(); 120 int index = getValueIndex(); 121 122 if (index + getValueLength() > data.length) { 123 throw new ParserException("Not enough data for AR_DO!"); 124 } 125 126 do { 127 BerTlv temp = BerTlv.decode(data, index); 128 129 if (temp.getTag() == AID_REF_DO.TAG 130 || temp.getTag() == AID_REF_DO.TAG_DEFAULT_APPLICATION) { // AID-REF-DO 131 mAidDo = new AID_REF_DO(data, temp.getTag(), temp.getValueIndex(), 132 temp.getValueLength()); 133 mAidDo.interpret(); 134 } else if (temp.getTag() == Hash_REF_DO.TAG) { // Hash-REF-DO 135 mHashDo = new Hash_REF_DO(data, temp.getValueIndex(), temp.getValueLength()); 136 mHashDo.interpret(); 137 } else if (temp.getTag() == PKG_REF_DO.TAG) { // PKG-REF-DO 138 mPkgDo = new PKG_REF_DO(data, temp.getValueIndex(), temp.getValueLength()); 139 mPkgDo.interpret(); 140 } else { 141 // uncomment following line if a more restrictive 142 // behaviour is necessary. 143 // throw new ParserException("Invalid DO in REF-DO!"); 144 } 145 index = temp.getValueIndex() + temp.getValueLength(); 146 } while (getValueIndex() + getValueLength() > index); 147 148 if (mAidDo != null && !mAidDo.isCarrierPrivilege() && mHashDo != null && mPkgDo != null) { 149 throw new ParserException("Unexpected combination of SEAC DOs and DAC DO"); 150 } 151 152 // A rule without AID is a Carrier Privilege Rule. 153 // Enforces the AID to be the Carrier Privilege AID to avoid a null AID. 154 if (mAidDo == null && mHashDo != null) { 155 mAidDo = AID_REF_DO.createCarrierPrivilegeAid(); 156 } 157 158 // check if there is a AID-REF-DO 159 if (mAidDo == null) { 160 throw new ParserException("Missing AID-REF-DO in REF-DO!"); 161 } 162 // check if there is a Hash-REF-DO 163 if (mHashDo == null) { 164 throw new ParserException("Missing Hash-REF-DO in REF-DO!"); 165 } 166 } 167 168 /** 169 * Tag: E1 Length: n Value: 170 * 1. AID-REF-DO | Hash-REF-DO: A concatenation of an AID-REF-DO and a Hash-REF-DO. 171 * 2. Hash-REF-DO or Hash-REF-DO | PKG-REF-DO A concatenation of a Hash-REF-DO and a 172 * PKG-REF-DO. 173 */ 174 @Override build(ByteArrayOutputStream stream)175 public void build(ByteArrayOutputStream stream) throws DO_Exception { 176 ByteArrayOutputStream temp = new ByteArrayOutputStream(); 177 178 if (mHashDo == null) { 179 throw new DO_Exception("REF-DO: Required DO missing!"); 180 } 181 182 if (mAidDo != null) { 183 mAidDo.build(temp); 184 } 185 186 if (mHashDo != null) { 187 mHashDo.build(temp); 188 } 189 190 if (mPkgDo != null) { 191 mPkgDo.build(temp); 192 } 193 194 byte[] data = temp.toByteArray(); 195 BerTlv tlv = new BerTlv(data, getTag(), 0, data.length); 196 tlv.build(stream); 197 } 198 199 @Override equals(Object obj)200 public boolean equals(Object obj) { 201 if (obj instanceof REF_DO) { 202 REF_DO ref_do = (REF_DO) obj; 203 if (getTag() == ref_do.getTag()) { 204 if (AID_REF_DO.equals(mAidDo, ref_do.mAidDo)) { 205 if (Hash_REF_DO.equals(mHashDo, ref_do.mHashDo)) { 206 if (PKG_REF_DO.equals(mPkgDo, ref_do.mPkgDo)) { 207 return true; 208 } 209 } 210 } 211 } 212 } 213 return false; 214 } 215 216 @Override hashCode()217 public int hashCode() { 218 ByteArrayOutputStream stream = new ByteArrayOutputStream(); 219 try { 220 this.build(stream); 221 } catch (DO_Exception e) { 222 return 1; 223 } 224 byte[] data = stream.toByteArray(); 225 int hash = Arrays.hashCode(data); 226 // int hash = data.hashCode(); 227 return hash; 228 } 229 isCarrierPrivilegeRefDo()230 public boolean isCarrierPrivilegeRefDo() { 231 return (mAidDo != null && mAidDo.isCarrierPrivilege()); 232 } 233 } 234