• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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) 2015-2017, The Linux Foundation.
18  */
19 
20 /*
21  * Copyright (C) 2011 Deutsche Telekom, A.G.
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 
36 /*
37  * Contributed by: Giesecke & Devrient GmbH.
38  */
39 
40 package com.android.se.security.arf.pkcs15;
41 
42 import android.util.Log;
43 
44 import com.android.se.internal.Util;
45 import com.android.se.security.ApduFilter;
46 import com.android.se.security.ChannelAccess;
47 import com.android.se.security.arf.ASN1;
48 import com.android.se.security.arf.DERParser;
49 import com.android.se.security.arf.SecureElement;
50 import com.android.se.security.gpac.AID_REF_DO;
51 import com.android.se.security.gpac.Hash_REF_DO;
52 
53 import java.io.IOException;
54 import java.util.Vector;
55 
56 /** EF_ACConditions related features ************************************************* */
57 public class EFACConditions extends EF {
58 
59     public static final String TAG = "ACE ARF EF_ACConditions";
60 
61     // Identification of the cardlet
62     private AID_REF_DO mAidRefDo = null;
63 
64     private byte[] mData = null;
65 
66     /**
67      * Constructor
68      *
69      * @param secureElement SE on which ISO7816 commands are applied
70      * @param AID           Identification of the applet
71      */
EFACConditions(SecureElement handle, AID_REF_DO aidRefDo)72     public EFACConditions(SecureElement handle, AID_REF_DO aidRefDo) {
73         super(handle);
74         mAidRefDo = aidRefDo;
75     }
76 
77     /**
78      * Decodes EF_ACConditions file
79      *
80      * @param buffer ASN.1 data
81      */
decodeDER(byte[] buffer)82     private void decodeDER(byte[] buffer) throws PKCS15Exception {
83         byte[] certificateHash = null;
84         DERParser der = new DERParser(buffer);
85 
86         // the default channelAccess will deny every access.
87         ChannelAccess channelAccess = new ChannelAccess();
88         Hash_REF_DO hash_ref_do = new Hash_REF_DO();
89 
90         // empty condition file
91         if (der.isEndofBuffer()) {
92             channelAccess.setAccess(ChannelAccess.ACCESS.DENIED, "Empty ACCondition");
93             channelAccess.setNFCEventAccess(ChannelAccess.ACCESS.DENIED);
94             channelAccess.setApduAccess(ChannelAccess.ACCESS.DENIED);
95             channelAccess.setUseApduFilter(false);
96             channelAccess.setApduFilter(null);
97             Log.i(TAG, "Empty ACCondition: Access Deny for all apps");
98 
99             mSEHandle.putAccessRule(mAidRefDo, hash_ref_do, channelAccess);
100             return;
101         }
102 
103         // ----
104         // 2012-04-16
105     /*
106       Condition ::= SEQUENCE {
107              cert   CertHash OPTIONAL,
108              accessRules    [0]AccessRules OPTIONAL
109        }
110 
111        AccessRules ::= SEQUENCE OF AccessRule
112 
113        AccessRule ::=CHOICE {
114            apduAccessRule    [0]APDUAccessRule,
115            nfcAccessRule    [1]NFCAccessRule
116        }
117 
118        APDUAccessRule ::= CHOICE {
119               apduPermission [0] APDUPermission,
120               apduFilter [1] APDUFilter
121        }
122 
123        APDUFilters ::= SEQUENCE OF APDUFilter
124 
125        NFCAccessRule ::= CHOICE {
126               nfcPermission [0] NFCPermission
127        }
128     */
129         while (!der.isEndofBuffer()) {
130 
131             // if a hash value was found then access is allowed
132             // even if NO more access rule is given.
133             // missing APDU Permission will always allow APDU access
134             // missing NFC Permission will always allow NFC event.
135             // See GPAC Chapter 7.1.7
136             // See Examples in Annex C of GPAC
137             channelAccess = new ChannelAccess();
138             channelAccess.setAccess(ChannelAccess.ACCESS.ALLOWED, "");
139             channelAccess.setApduAccess(ChannelAccess.ACCESS.ALLOWED);
140             channelAccess.setNFCEventAccess(ChannelAccess.ACCESS.UNDEFINED);
141             channelAccess.setUseApduFilter(false);
142 
143             if (der.parseTLV(ASN1.TAG_Sequence) > 0) {
144                 byte[] tempTLVData = der.getTLVData();
145                 DERParser derRule = new DERParser(tempTLVData);
146 
147                 if (tempTLVData[0] == ASN1.TAG_OctetString) {
148                     derRule.parseTLV(ASN1.TAG_OctetString);
149                     certificateHash = derRule.getTLVData();
150 
151                     if (certificateHash.length != Hash_REF_DO.SHA1_LEN
152                             && certificateHash.length != 0) {
153                         // other hash than SHA-1 hash values are not supported.
154                         throw new PKCS15Exception("Invalid hash found!");
155                     } else {
156                         hash_ref_do = new Hash_REF_DO(certificateHash);
157                     }
158                 } else if (tempTLVData[0] == ASN1.TAG_Padding) {
159                     throw new PKCS15Exception("Invalid hash found!");
160                 } else {
161                     Log.i(TAG, "No hash included");
162                     // Let's put a null hash, to prioritize any more specific rule.
163                     hash_ref_do = new Hash_REF_DO(null);
164                 }
165 
166                 // 2012-04-16
167                 // parse optional Access Rule.
168                 if (!derRule.isEndofBuffer()) {
169 
170                     if (derRule.parseTLV() == (byte) 0xA0) {
171 
172                         DERParser derAccessRules = new DERParser(derRule.getTLVData());
173 
174                         while (!derAccessRules.isEndofBuffer()) {
175                             switch (derAccessRules.parseTLV()) {
176                                 // APDU Access Rule
177                                 case (byte) 0xA0:
178                                     DERParser derApduRule = new DERParser(
179                                             derAccessRules.getTLVData());
180                                     byte tagApduAccessRule = derApduRule.parseTLV();
181 
182                                     if (tagApduAccessRule
183                                             == (byte) 0x80) { // APDU Permission  (primitive)
184 
185                                         channelAccess.setApduAccess(
186                                                 derApduRule.getTLVData()[0] == 0x01
187                                                         ? ChannelAccess.ACCESS.ALLOWED
188                                                         : ChannelAccess.ACCESS.DENIED);
189 
190                                     } else if (tagApduAccessRule
191                                             == (byte) 0xA1) { // APDU Filter (constructed)
192 
193                                         DERParser derApduFilter = new DERParser(
194                                                 derApduRule.getTLVData());
195                                         byte tag = derApduFilter.parseTLV();
196 
197                                         if (tag == ASN1.TAG_OctetString) {
198 
199                                             Vector<ApduFilter> apduFilter =
200                                                     new Vector<ApduFilter>();
201 
202                                             // collect all apdu filter tlvs.
203                                             apduFilter.add(
204                                                     new ApduFilter(derApduFilter.getTLVData()));
205 
206                                             while (!derApduFilter.isEndofBuffer()) {
207                                                 if (derApduFilter.parseTLV()
208                                                         == ASN1.TAG_OctetString) {
209                                                     apduFilter.add(new ApduFilter(
210                                                             derApduFilter.getTLVData()));
211                                                 }
212                                             }
213                                             channelAccess.setUseApduFilter(true);
214                                             channelAccess.setApduFilter(
215                                                     apduFilter.toArray(
216                                                             new ApduFilter[apduFilter.size()]));
217                                         } else {
218                                             throw new PKCS15Exception("Invalid element found!");
219                                         }
220 
221                                     } else {
222                                         throw new PKCS15Exception("Invalid element found!");
223                                     }
224                                     break;
225                                 // NFC Access Rule
226                                 case (byte) 0xA1:
227                                     DERParser derNfc = new DERParser(derAccessRules.getTLVData());
228 
229                                     if (derNfc.parseTLV()
230                                             == (byte) 0x80) { // NFC Permission (primitive)
231                                         channelAccess.setNFCEventAccess(
232                                                 derNfc.getTLVData()[0] == (byte) 0x01
233                                                         ? ChannelAccess.ACCESS.ALLOWED
234                                                         : ChannelAccess.ACCESS.DENIED);
235                                     } else {
236                                         throw new PKCS15Exception("Invalid element found!");
237                                     }
238                                     break;
239                                 default:
240                                     throw new PKCS15Exception("Invalid element found!");
241                             }
242                         }
243                     } else {
244                         // no explicit access rule given.
245                     }
246                 }
247             } else {
248                 // coding 30 00 -> empty hash value given (all applications)
249                 if ((channelAccess.getNFCEventAccess() == ChannelAccess.ACCESS.UNDEFINED)
250                         && (channelAccess.getApduAccess() != ChannelAccess.ACCESS.UNDEFINED)) {
251                     channelAccess.setNFCEventAccess(channelAccess.getApduAccess());
252                 }
253             }
254             // ----
255             mSEHandle.putAccessRule(mAidRefDo, hash_ref_do, channelAccess);
256         }
257     }
258 
259     /**
260      * Stores a restricted list of certificate hashes
261      *
262      * @param path Path of the "EF_ACConditions" file
263      */
addRestrictedHashes(byte[] path)264     public void addRestrictedHashes(byte[] path) throws IOException, PKCS15Exception {
265         try {
266             Log.i(TAG, "Reading and analysing EF_ACConditions...");
267             if (selectFile(path) == APDU_SUCCESS) {
268                 mData = readBinary(0, Util.END);
269                 decodeDER(mData);
270             } else {
271                 Log.e(TAG, "EF_ACConditions not found!");
272             }
273         } catch (Exception e) {
274             throw new PKCS15Exception(e.getMessage());
275         }
276     }
277 
278     /**
279      * Stores a restricted list of certificate hashes
280      */
addRestrictedHashesFromData(byte[] data)281     public void addRestrictedHashesFromData(byte[] data) throws PKCS15Exception {
282         try {
283             Log.i(TAG, "Analysing cached EF_ACConditions data...");
284             if (data != null) {
285                 mData = data;
286                 decodeDER(mData);
287             } else {
288                 Log.e(TAG, "EF_ACConditions data not available!");
289             }
290         } catch (Exception e) {
291             throw new PKCS15Exception(e.getMessage());
292         }
293     }
294 
getData()295     public byte[] getData() {
296         return mData;
297     }
298 }
299