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 * Hash-REF-DO: The Hash-REF-DO is used for retrieving and storing the corresponding access rules 43 * for a device application (which is identified by the hash value of its certificate) from and to 44 * the ARA 45 */ 46 public class Hash_REF_DO extends BerTlv { 47 48 public static final int TAG = 0xC1; 49 public static final int SHA1_LEN = 20; 50 51 private byte[] mHash = new byte[0]; 52 53 public Hash_REF_DO(byte[] rawData, int valueIndex, int valueLength) { 54 super(rawData, TAG, valueIndex, valueLength); 55 } 56 57 public Hash_REF_DO(byte[] hash) { 58 super(hash, TAG, 0, (hash == null ? 0 : hash.length)); 59 if (hash != null) mHash = hash; 60 } 61 62 public Hash_REF_DO() { 63 super(null, TAG, 0, 0); 64 } 65 66 /** 67 * Comapares two Hash_REF_DO objects and returns true if they are equal 68 */ 69 public static boolean equals(Hash_REF_DO obj1, Hash_REF_DO obj2) { 70 if (obj1 == null) { 71 return (obj2 == null) ? true : false; 72 } 73 return obj1.equals(obj2); 74 } 75 76 public byte[] getHash() { 77 return mHash; 78 } 79 80 @Override 81 public String toString() { 82 StringBuilder b = new StringBuilder(); 83 ByteArrayOutputStream out = new ByteArrayOutputStream(); 84 b.append("Hash_REF_DO: "); 85 try { 86 this.build(out); 87 b.append(BerTlv.toHex(out.toByteArray())); 88 } catch (Exception e) { 89 b.append(e.getLocalizedMessage()); 90 } 91 return b.toString(); 92 } 93 94 /** 95 * Tags: C1 Length: 0 or SHA1_LEN bytes 96 * 97 * <p>Value: Hash: identifies a specific device application Empty: refers to all device 98 * applications 99 * 100 * <p>Length: SHA1_LEN for 20 bytes SHA-1 hash value 0 for empty value field 101 */ 102 @Override 103 public void interpret() throws ParserException { 104 105 mHash = new byte[0]; 106 107 byte[] data = getRawData(); 108 int index = getValueIndex(); 109 110 // sanity checks 111 if (getValueLength() != 0 && getValueLength() != SHA1_LEN) { 112 throw new ParserException("Invalid value length for Hash-REF-DO!"); 113 } 114 115 if (getValueLength() == SHA1_LEN) { 116 if (index + getValueLength() > data.length) { 117 throw new ParserException("Not enough data for Hash-REF-DO!"); 118 } 119 120 mHash = new byte[getValueLength()]; 121 System.arraycopy(data, index, mHash, 0, getValueLength()); 122 } 123 } 124 125 /** 126 * Tags: C1 Length: 0 or 20 bytes 127 * 128 * <p>Value: Hash: identifies a specific device application Empty: refers to all device 129 * applications 130 * 131 * <p>Length: SHA1_LEN for 20 bytes SHA-1 hash value 0 for empty value field 132 */ 133 @Override 134 public void build(ByteArrayOutputStream stream) throws DO_Exception { 135 136 // sanity checks 137 if (!(mHash.length != SHA1_LEN || mHash.length != 0)) { 138 throw new DO_Exception("Hash value must be " + SHA1_LEN + " bytes in length!"); 139 } 140 141 stream.write(getTag()); 142 143 try { 144 stream.write(mHash.length); 145 stream.write(mHash); 146 } catch (IOException ioe) { 147 throw new DO_Exception("Hash could not be written!"); 148 } 149 } 150 151 @Override 152 public boolean equals(Object obj) { 153 if (obj instanceof Hash_REF_DO) { 154 Hash_REF_DO hash_ref_do = (Hash_REF_DO) obj; 155 if (getTag() == hash_ref_do.getTag()) { 156 return Arrays.equals(mHash, hash_ref_do.mHash); 157 } 158 } 159 return false; 160 } 161 } 162