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