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 51 public REF_DO(byte[] rawData, int valueIndex, int valueLength) { 52 super(rawData, TAG, valueIndex, valueLength); 53 } 54 55 public REF_DO(AID_REF_DO aidRefDo, Hash_REF_DO hashRefDo) { 56 super(null, TAG, 0, 0); 57 mAidDo = aidRefDo; 58 mHashDo = hashRefDo; 59 } 60 61 @Override 62 public String toString() { 63 StringBuilder b = new StringBuilder(); 64 b.append("REF_DO: "); 65 if (mAidDo != null) { 66 b.append(mAidDo.toString()); 67 b.append(' '); 68 } 69 if (mHashDo != null) { 70 b.append(mHashDo.toString()); 71 } 72 return b.toString(); 73 } 74 75 public AID_REF_DO getAidDo() { 76 return mAidDo; 77 } 78 79 public Hash_REF_DO getHashDo() { 80 return mHashDo; 81 } 82 83 /** 84 * Interpret data. 85 * 86 * <p>Tags: E1 -> Length: n 87 * 88 * <p>Value: AID-REF-DO | Hash-REF-DO: A concatenation of an AID-REF-DO and a Hash-REF-DO. 89 * 90 * <p>Length: n bytes. 91 */ 92 @Override 93 public void interpret() throws ParserException { 94 95 mAidDo = null; 96 mHashDo = null; 97 98 byte[] data = getRawData(); 99 int index = getValueIndex(); 100 101 if (index + getValueLength() > data.length) { 102 throw new ParserException("Not enough data for AR_DO!"); 103 } 104 105 do { 106 BerTlv temp = BerTlv.decode(data, index); 107 108 if (temp.getTag() == AID_REF_DO.TAG 109 || temp.getTag() == AID_REF_DO.TAG_DEFAULT_APPLICATION) { // AID-REF-DO 110 mAidDo = new AID_REF_DO(data, temp.getTag(), temp.getValueIndex(), 111 temp.getValueLength()); 112 mAidDo.interpret(); 113 } else if (temp.getTag() == Hash_REF_DO.TAG) { // Hash-REF-DO 114 mHashDo = new Hash_REF_DO(data, temp.getValueIndex(), temp.getValueLength()); 115 mHashDo.interpret(); 116 } else { 117 // uncomment following line if a more restrictive 118 // behaviour is necessary. 119 // throw new ParserException("Invalid DO in REF-DO!"); 120 } 121 index = temp.getValueIndex() + temp.getValueLength(); 122 } while (getValueIndex() + getValueLength() > index); 123 124 // check if there is a AID-REF-DO 125 if (mAidDo == null) { 126 throw new ParserException("Missing AID-REF-DO in REF-DO!"); 127 } 128 // check if there is a Hash-REF-DO 129 if (mHashDo == null) { 130 throw new ParserException("Missing Hash-REF-DO in REF-DO!"); 131 } 132 } 133 134 /** 135 * Tag: E1 Length: n Value: AID-REF-DO | Hash-REF-DO: A concatenation of an AID-REF-DO and a 136 * Hash-REF-DO. 137 */ 138 @Override 139 public void build(ByteArrayOutputStream stream) throws DO_Exception { 140 ByteArrayOutputStream temp = new ByteArrayOutputStream(); 141 142 if (mAidDo == null || mHashDo == null) { 143 throw new DO_Exception("REF-DO: Required DO missing!"); 144 } 145 146 mAidDo.build(temp); 147 mHashDo.build(temp); 148 149 byte[] data = temp.toByteArray(); 150 BerTlv tlv = new BerTlv(data, getTag(), 0, data.length); 151 tlv.build(stream); 152 } 153 154 @Override 155 public boolean equals(Object obj) { 156 if (obj instanceof REF_DO) { 157 REF_DO ref_do = (REF_DO) obj; 158 if (getTag() == ref_do.getTag()) { 159 if (AID_REF_DO.equals(mAidDo, ref_do.mAidDo)) { 160 if (Hash_REF_DO.equals(mHashDo, ref_do.mHashDo)) { 161 return true; 162 } 163 } 164 } 165 } 166 return false; 167 } 168 169 @Override 170 public int hashCode() { 171 ByteArrayOutputStream stream = new ByteArrayOutputStream(); 172 try { 173 this.build(stream); 174 } catch (DO_Exception e) { 175 return 1; 176 } 177 byte[] data = stream.toByteArray(); 178 int hash = Arrays.hashCode(data); 179 // int hash = data.hashCode(); 180 return hash; 181 } 182 } 183