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 package com.android.se.security.arf.pkcs15;
37 
38 import android.util.Log;
39 
40 import com.android.se.security.arf.ASN1;
41 import com.android.se.security.arf.DERParser;
42 import com.android.se.security.arf.SecureElement;
43 import com.android.se.security.arf.SecureElementException;
44 
45 import java.io.IOException;
46 import java.util.Arrays;
47 
48 /** EF_DIR related features */
49 public class EFDIR extends EF {
50 
51     public static final String TAG = "ACE ARF EF_Dir";
52     // Standardized ID for EF_DIR file
53     public static final byte[] EFDIR_PATH = {0x3F, 0x00, 0x2F, 0x00};
54 
55     /**
56      * Constructor
57      *
58      * @param secureElement SE on which ISO7816 commands are applied
59      */
EFDIR(SecureElement handle)60     public EFDIR(SecureElement handle) {
61         super(handle);
62     }
63 
64     /**
65      * Decodes EF_DIR file
66      *
67      * @param buffer ASN.1 data
68      * @param aid    Record key to search for
69      * @return Path to "EF_ODF" when an expected record is found; <code>null</code> otherwise
70      */
decodeDER(byte[] buffer, byte[] aid)71     private byte[] decodeDER(byte[] buffer, byte[] aid) throws PKCS15Exception {
72         DERParser der = new DERParser(buffer);
73         der.parseTLV(ASN1.TAG_ApplTemplate);
74         // Application Identifier
75         der.parseTLV(ASN1.TAG_ApplIdentifier);
76         if (!Arrays.equals(der.getTLVData(), aid)) return null; // Record for another AID
77 
78         // Application Label or Application Path
79         byte objectType = der.parseTLV();
80         if (objectType == ASN1.TAG_ApplLabel) {
81             // Application Label [Optional]
82             der.getTLVData();
83             der.parseTLV(ASN1.TAG_ApplPath);
84         } else if (objectType != ASN1.TAG_ApplPath) {
85             throw new PKCS15Exception("[Parser] Application Tag expected");
86         }
87         // Application Path
88         return der.getTLVData();
89     }
90 
91     /**
92      * Analyses DIR file and lookups for AID record
93      *
94      * @param aid Record key to search for
95      * @return Path to "EF_ODF" when an expected record is found; <code>null</code> otherwise
96      */
lookupAID(byte[] aid)97     public byte[] lookupAID(byte[] aid) throws IOException, PKCS15Exception,
98             SecureElementException {
99         Log.i(TAG, "Analysing EF_DIR...");
100 
101         if (selectFile(EFDIR_PATH) != APDU_SUCCESS) throw new PKCS15Exception("EF_DIR not found!!");
102 
103         byte[] data, ODFPath = null;
104         short index = 1;
105         while (index <= getFileNbRecords()) {
106             data = readRecord(index++);
107             if ((ODFPath = decodeDER(data, aid)) != null) break;
108         }
109         return ODFPath;
110     }
111 }
112