/* * 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 * *
Value: Hash: identifies a specific device application Empty: refers to all device * applications * *
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 * *
Value: Hash: identifies a specific device application Empty: refers to all device * applications * *
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; } }