Home | History | Annotate | Download | only in gpac
      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