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 
40 /**
41  * REF-AR_DO: The REF-AR-DO contains access rules inclusively its corresponding references for the
42  * SE application (AID reference) and device application (hash reference).
43  */
44 public class REF_AR_DO extends BerTlv {
45 
46     public static final int TAG = 0xE2;
47 
48     private REF_DO mRefDo = null;
49     private AR_DO mArDo = null;
50 
REF_AR_DO(byte[] rawData, int valueIndex, int valueLength)51     public REF_AR_DO(byte[] rawData, int valueIndex, int valueLength) {
52         super(rawData, TAG, valueIndex, valueLength);
53     }
54 
REF_AR_DO()55     public REF_AR_DO() {
56         super(null, TAG, 0, 0);
57     }
58 
REF_AR_DO(REF_DO refDo, AR_DO arDo)59     public REF_AR_DO(REF_DO refDo, AR_DO arDo) {
60         super(null, TAG, 0, 0);
61         mRefDo = refDo;
62         mArDo = arDo;
63     }
64 
getRefDo()65     public REF_DO getRefDo() {
66         return mRefDo;
67     }
68 
getArDo()69     public AR_DO getArDo() {
70         return mArDo;
71     }
72 
73     /**
74      * Interpret data.
75      *
76      * <p>Tags: E2 Length: n
77      *
78      * <p>Value: REF-DO | AR-DO: A concatenation of an REF-DO and an AR-DO. The REF-DO must
79      * correspond
80      * to the succeeding AR-DO.
81      *
82      * <p>Length: n bytes.
83      */
84     @Override
interpret()85     public void interpret() throws ParserException {
86 
87         mRefDo = null;
88         mArDo = null;
89 
90         byte[] data = getRawData();
91         int index = getValueIndex();
92 
93         if (index + getValueLength() > data.length) {
94             throw new ParserException("Not enough data for AR_DO!");
95         }
96 
97         do {
98             BerTlv temp = BerTlv.decode(data, index);
99             if (temp.getTag() == REF_DO.TAG) { // REF-DO
100                 mRefDo = new REF_DO(data, temp.getValueIndex(), temp.getValueLength());
101                 mRefDo.interpret();
102             } else if (temp.getTag() == AR_DO.TAG) { // AR-DO
103                 mArDo = new AR_DO(data, temp.getValueIndex(), temp.getValueLength());
104                 mArDo.interpret();
105             } else {
106 
107                 // uncomment following line if a more restrictive
108                 // behavior is necessary.
109                 // throw new ParserException("Invalid DO in REF-AR-DO!");
110             }
111             index = temp.getValueIndex() + temp.getValueLength();
112         } while (getValueIndex() + getValueLength() > index);
113 
114         // check for Carrier Privilege rules
115         if (mRefDo != null && mArDo == null && mRefDo.getAidDo() != null
116                 && mRefDo.getAidDo().isCarrierPrivilege()) {
117             return;
118         }
119 
120         // check for mandatory TLVs.
121         if (mRefDo == null) {
122             throw new ParserException("Missing Ref-DO in REF-AR-DO!");
123         }
124         if (mArDo == null) {
125             throw new ParserException("Missing AR-DO in REF-AR-DO!");
126         }
127     }
128 
129     /** Tag: E2 Length: n Value: REF-DO | AR-DO: A concatenation of an REF-DO and an AR-DO. */
130     @Override
build(ByteArrayOutputStream stream)131     public void build(ByteArrayOutputStream stream) throws DO_Exception {
132         ByteArrayOutputStream temp = new ByteArrayOutputStream();
133 
134         if (mRefDo == null || mArDo == null) {
135             throw new DO_Exception("REF-AR-DO: Required DO missing!");
136         }
137         stream.write(getTag());
138 
139         mRefDo.build(temp);
140         mArDo.build(temp);
141 
142         byte[] data = temp.toByteArray();
143         BerTlv.encodeLength(data.length, stream);
144         try {
145             stream.write(data);
146         } catch (IOException e) {
147             throw new DO_Exception("REF-AR-DO Memory IO problem! " + e.getMessage());
148         }
149     }
150 }
151