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.io.IOException;
     39 import java.util.Arrays;
     40 
     41 /**
     42  * The AID-REF-DO is used for retrieving and storing the corresponding access rules for an SE
     43  * application (which is identified by its AID) from and to the ARA. Two different AID reference
     44  * data objects exist and one of these can be chosen and applied for a GET DATA and STORE DATA
     45  * command
     46  */
     47 public class AID_REF_DO extends BerTlv {
     48 
     49     public static final int TAG = 0x4F;
     50     public static final int TAG_DEFAULT_APPLICATION = 0xC0;
     51 
     52     private byte[] mAid = new byte[0];
     53 
     54     public AID_REF_DO(byte[] rawData, int tag, int valueIndex, int valueLength) {
     55         super(rawData, tag, valueIndex, valueLength);
     56     }
     57 
     58     public AID_REF_DO(int tag, byte[] aid) {
     59         super(aid, tag, 0, (aid == null ? 0 : aid.length));
     60         if (aid != null) mAid = aid;
     61     }
     62 
     63     public AID_REF_DO(int tag) {
     64         super(null, tag, 0, 0);
     65     }
     66 
     67     /**
     68      * Comapares two AID_REF_DO objects and returns true if they are equal
     69      */
     70     public static boolean equals(AID_REF_DO obj1, AID_REF_DO obj2) {
     71         if (obj1 == null) {
     72             return (obj2 == null) ? true : false;
     73         }
     74         return obj1.equals(obj2);
     75     }
     76 
     77     @Override
     78     public String toString() {
     79         StringBuilder b = new StringBuilder();
     80         ByteArrayOutputStream out = new ByteArrayOutputStream();
     81         b.append("AID_REF_DO: ");
     82         try {
     83             this.build(out);
     84             b.append(BerTlv.toHex(out.toByteArray()));
     85         } catch (Exception e) {
     86             b.append(e.getLocalizedMessage());
     87         }
     88         return b.toString();
     89     }
     90 
     91     public byte[] getAid() {
     92         return mAid;
     93     }
     94 
     95     /**
     96      * Tags: C0 -> Length: 0 -> Default selected application (all channels) 4F -> Length: 0 or 5 -
     97      * 16
     98      * bytes
     99      *
    100      * <p>Value: AID: identifies a specific application Empty: refers to all SE applications
    101      *
    102      * <p>Length: 5-16 for an AID according to ISO/IEC7816-5 0 for empty value field
    103      */
    104     @Override
    105     public void interpret() throws ParserException {
    106 
    107         mAid = null;
    108 
    109         byte[] data = getRawData();
    110         int index = getValueIndex();
    111 
    112         if (getTag() == TAG_DEFAULT_APPLICATION) {
    113             if (getValueLength() != 0) {
    114                 throw new ParserException("Invalid value length for AID-REF-DO!");
    115             }
    116         } else if (getTag() == TAG) {
    117 
    118             // sanity checks
    119             if ((getValueLength() < 5 || getValueLength() > 16) && getValueLength() != 0) {
    120                 throw new ParserException("Invalid value length for AID-REF-DO!");
    121             }
    122 
    123             if (index + getValueLength() > data.length) {
    124                 throw new ParserException("Not enough data for AID-REF-DO!");
    125             }
    126 
    127             mAid = new byte[getValueLength()];
    128             System.arraycopy(data, index, mAid, 0, getValueLength());
    129 
    130         } else {
    131             throw new ParserException("Invalid Tag for AID-REF-DO!");
    132         }
    133     }
    134 
    135     /**
    136      * Tags: C0 -> Length: 0 -> Default selected application (all channels) 4F -> Length: 0 or 5 -
    137      * 16
    138      * bytes
    139      *
    140      * <p>Value: AID: identifies a specific application Empty: refers to all SE applications
    141      *
    142      * <p>Length: 5-16 for an AID according to ISO/IEC7816-5 0 for empty value field
    143      */
    144     @Override
    145     public void build(ByteArrayOutputStream stream) throws DO_Exception {
    146 
    147         if (getTag() == TAG_DEFAULT_APPLICATION) {
    148             if (mAid.length > 0) {
    149                 throw new DO_Exception("No value allowed for default selected application!");
    150             }
    151             stream.write(getTag());
    152             stream.write(0x00);
    153         } else if (getTag() == TAG) {
    154 
    155             // sanity check
    156             if (getValueLength() != 0) {
    157                 if (getValueLength() < 5 || getValueLength() > 16) {
    158                     throw new DO_Exception("Invalid length of AID!");
    159                 }
    160             }
    161 
    162             stream.write(getTag());
    163             stream.write(mAid.length);
    164             try {
    165                 stream.write(mAid);
    166             } catch (IOException ioe) {
    167                 throw new DO_Exception("AID could not be written!");
    168             }
    169         } else {
    170             throw new DO_Exception("AID-REF-DO must either be C0 or 4F!");
    171         }
    172     }
    173 
    174     @Override
    175     public boolean equals(Object obj) {
    176         if (obj instanceof AID_REF_DO) {
    177             AID_REF_DO aid_ref_do = (AID_REF_DO) obj;
    178             if (getTag() == aid_ref_do.getTag()) {
    179                 return Arrays.equals(mAid, aid_ref_do.mAid);
    180             }
    181         }
    182         return false;
    183     }
    184 }
    185