| /* |
| * Copyright (C) 2017 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| /* |
| * Copyright (c) 2017, The Linux Foundation. |
| */ |
| |
| /* |
| * Copyright 2012 Giesecke & Devrient GmbH. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package com.android.se.security.gpac; |
| |
| import java.io.ByteArrayOutputStream; |
| import java.io.IOException; |
| import java.util.Arrays; |
| |
| /** |
| * Hash-REF-DO: The Hash-REF-DO is used for retrieving and storing the corresponding access rules |
| * for a device application (which is identified by the hash value of its certificate) from and to |
| * the ARA |
| */ |
| public class Hash_REF_DO extends BerTlv { |
| |
| public static final int TAG = 0xC1; |
| public static final int SHA1_LEN = 20; |
| public static final int SHA256_LEN = 32; |
| |
| private byte[] mHash = new byte[0]; |
| |
| public Hash_REF_DO(byte[] rawData, int valueIndex, int valueLength) { |
| super(rawData, TAG, valueIndex, valueLength); |
| } |
| |
| public Hash_REF_DO(byte[] hash) { |
| super(hash, TAG, 0, (hash == null ? 0 : hash.length)); |
| if (hash != null) mHash = hash; |
| } |
| |
| public Hash_REF_DO() { |
| super(null, TAG, 0, 0); |
| } |
| |
| /** |
| * Comapares two Hash_REF_DO objects and returns true if they are equal |
| */ |
| public static boolean equals(Hash_REF_DO obj1, Hash_REF_DO obj2) { |
| if (obj1 == null) { |
| return (obj2 == null) ? true : false; |
| } |
| return obj1.equals(obj2); |
| } |
| |
| public byte[] getHash() { |
| return mHash; |
| } |
| |
| @Override |
| public String toString() { |
| StringBuilder b = new StringBuilder(); |
| ByteArrayOutputStream out = new ByteArrayOutputStream(); |
| b.append("Hash_REF_DO: "); |
| try { |
| this.build(out); |
| b.append(BerTlv.toHex(out.toByteArray())); |
| } catch (Exception e) { |
| b.append(e.getLocalizedMessage()); |
| } |
| return b.toString(); |
| } |
| |
| /** |
| * Tags: C1 Length: 0 or SHA1_LEN or SHA256_LEN bytes |
| * |
| * <p>Value: Hash: identifies a specific device application Empty: refers to all device |
| * applications |
| * |
| * <p>Length: SHA1_LEN for 20 bytes SHA-1 hash value |
| * SHA256_LEN for 32 bytes SHA-256 hash value |
| * 0 for empty value field |
| */ |
| @Override |
| public void interpret() throws ParserException { |
| |
| mHash = new byte[0]; |
| |
| byte[] data = getRawData(); |
| int index = getValueIndex(); |
| int length = getValueLength(); |
| |
| // sanity checks |
| if (length != 0 && length != SHA1_LEN && length != SHA256_LEN) { |
| throw new ParserException("Invalid value length for Hash-REF-DO!"); |
| } |
| |
| if (length != 0) { |
| if (index + length > data.length) { |
| throw new ParserException("Not enough data for Hash-REF-DO!"); |
| } |
| |
| mHash = new byte[length]; |
| System.arraycopy(data, index, mHash, 0, length); |
| } |
| } |
| |
| /** |
| * Tags: C1 Length: 0 or 20 bytes |
| * |
| * <p>Value: Hash: identifies a specific device application Empty: refers to all device |
| * applications |
| * |
| * <p>Length: 20 for SHA-1 hash or |
| * 32 bytes for SHA-256 hash or |
| * 0 for empty value field |
| */ |
| @Override |
| public void build(ByteArrayOutputStream stream) throws DO_Exception { |
| |
| // sanity checks |
| if (mHash.length != SHA1_LEN && mHash.length != SHA256_LEN && mHash.length != 0) { |
| throw new DO_Exception("Hash value must be " + SHA1_LEN + " or " + SHA256_LEN |
| + " bytes in length!"); |
| } |
| |
| stream.write(getTag()); |
| |
| try { |
| stream.write(mHash.length); |
| stream.write(mHash); |
| } catch (IOException ioe) { |
| throw new DO_Exception("Hash could not be written!"); |
| } |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| if (obj instanceof Hash_REF_DO) { |
| Hash_REF_DO hash_ref_do = (Hash_REF_DO) obj; |
| if (getTag() == hash_ref_do.getTag()) { |
| return Arrays.equals(mHash, hash_ref_do.mHash); |
| } |
| } |
| return false; |
| } |
| } |