Add rule for 'All devices apps' when access rule is empty.
[platform/core/connectivity/smartcard-service.git] / common / GPARFACL.cpp
1 /*
2  * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd.
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 #include "Debug.h"
18 #include "GPARFACL.h"
19 #include "PKCS15ODF.h"
20 #include "PKCS15DODF.h"
21 #include "NumberStream.h"
22 #include "SimpleTLV.h"
23 #include "AccessCondition.h"
24
25 #ifndef EXTERN_API
26 #define EXTERN_API __attribute__((visibility("default")))
27 #endif
28
29 namespace smartcard_service_api
30 {
31         static unsigned char oid_globalplatform[] = { 0x2A, 0x86, 0x48, 0x86, 0xFC, 0x6B, 0x81, 0x48, 0x01, 0x01 };
32         static ByteArray OID_GLOBALPLATFORM(ARRAY_AND_SIZE(oid_globalplatform));
33
34         GPARFACL::GPARFACL() : AccessControlList()
35         {
36         }
37
38         GPARFACL::~GPARFACL()
39         {
40         }
41
42         int GPARFACL::loadACL(Channel *channel)
43         {
44                 int result = SCARD_ERROR_OK;
45
46                 _BEGIN();
47
48                 if (channel == NULL)
49                 {
50                         return SCARD_ERROR_ILLEGAL_PARAM;
51                 }
52
53                 PKCS15 pkcs15(channel);
54
55                 /* basically, all requests will be accepted when PKCS #15 doesn't exist or global platform OID is not placed */
56                 allGranted = false;
57
58                 result = pkcs15.select();
59                 if (result >= SCARD_ERROR_OK)
60                 {
61                         PKCS15ODF *odf;
62
63                         result = SCARD_ERROR_OK;
64                         allGranted = true;
65
66                         if ((odf = pkcs15.getODF()) != NULL)
67                         {
68                                 PKCS15DODF *dodf;
69
70                                 if ((dodf = odf->getDODF()) != NULL)
71                                 {
72                                         result = loadAccessControl(channel, dodf);
73                                         if (result == SCARD_ERROR_OK)
74                                         {
75                                         }
76                                         else
77                                         {
78                                                 _INFO("loadAccessControl failed, every request will be accepted.");
79                                                 result = SCARD_ERROR_OK;
80                                         }
81                                 }
82                                 else
83                                 {
84                                         _INFO("dodf null, every request will be accepted.");
85                                 }
86                         }
87                         else
88                         {
89                                 _INFO("odf null, every request will be accepted.");
90                         }
91                 }
92                 else
93                 {
94                         _ERR("failed to open PKCS15, every request will be denied.");
95                 }
96
97                 _END();
98
99                 return result;
100         }
101
102         int GPARFACL::loadAccessControl(Channel *channel, PKCS15DODF *dodf)
103         {
104                 int result = -1;
105                 ByteArray path;
106
107                 if ((result = dodf->searchOID(OID_GLOBALPLATFORM, path)) == 0)
108                 {
109                         ByteArray data;
110                         FileObject file(channel);
111
112                         _DBG("oid path : %s", path.toString().c_str());
113
114                         file.select(NumberStream::getLittleEndianNumber(path));
115                         file.readBinary(0, 0, file.getFCP()->getFileSize(), data);
116
117                         _DBG("data : %s", data.toString().c_str());
118
119                         /* PKCS #15 and DODF OID exists. apply access control rule!! */
120                         allGranted = false;
121
122                         SimpleTLV tlv(data);
123
124                         if (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE : AccessControlMainFile */
125                         {
126                                 tlv.enterToValueTLV();
127
128                                 /* refresh Tag */
129                                 ByteArray refreshTag;
130
131                                 refreshTag = SimpleTLV::getOctetString(tlv);
132                                 _DBG("current refresh tag : %s", refreshTag.toString().c_str());
133
134                                 if (this->refreshTag != refreshTag) /* need to update access control list */
135                                 {
136                                         this->refreshTag = refreshTag;
137
138                                         releaseACL();
139
140                                         /* access control rule path */
141                                         if (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE : Path */
142                                         {
143                                                 /* TODO : parse path */
144                                                 ByteArray path;
145
146                                                 /* OCTET STRING */
147                                                 path = SimpleTLV::getOctetString(tlv.getValue());
148                                                 _DBG("access control rule path : %s", path.toString().c_str());
149
150                                                 if (loadRules(channel, path) == 0)
151                                                 {
152                                                         _DBG("loadRules success");
153                                                 }
154                                                 else
155                                                 {
156                                                         _ERR("loadRules failed");
157                                                 }
158                                         }
159                                 }
160                                 else
161                                 {
162                                         _INFO("access rules are not changed. skip update");
163                                 }
164                                 tlv.returnToParentTLV();
165                         }
166                         else
167                         {
168                                 _ERR("tlv.decodeTLV failed");
169                         }
170                 }
171                 else
172                 {
173                         _ERR("OID not found");
174                 }
175
176                 return result;
177         }
178
179         int GPARFACL::loadRules(Channel *channel, const ByteArray &path)
180         {
181                 FileObject file(channel);
182                 ByteArray data, aid;
183
184                 file.select(NumberStream::getLittleEndianNumber(path));
185                 file.readBinary(0, 0, file.getFCP()->getFileSize(), data);
186
187                 _DBG("data : %s", data.toString().c_str());
188
189                 SimpleTLV tlv(data);
190
191                 while (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE : Rule */
192                 {
193                         tlv.enterToValueTLV();
194                         if (tlv.decodeTLV() == true)
195                         {
196                                 /* target */
197                                 switch (tlv.getTag())
198                                 {
199                                 case 0xA0 : /* CHOICE 0 : EXPLICIT AID */
200                                         /* OCTET STRING */
201                                         aid = SimpleTLV::getOctetString(tlv.getValue());
202                                         break;
203
204                                 case 0x81 : /* CHOICE 1?? : default */
205                                         aid = AccessControlList::DEFAULT_SE_APP;
206                                         break;
207
208                                 case 0x82 : /* CHOICE 2?? : any application */
209                                         aid = AccessControlList::ALL_SE_APPS;
210                                         break;
211                                 }
212
213                                 _DBG("aid : %s", aid.toString().c_str());
214
215                                 /* access condition path */
216                                 if (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE : Path */
217                                 {
218                                         ByteArray path;
219
220                                         /* OCTET STRING */
221                                         path = SimpleTLV::getOctetString(tlv.getValue());
222                                         _DBG("path : %s", path.toString().c_str());
223
224                                         if (loadAccessConditions(channel, aid, path) == 0)
225                                         {
226                                                 _DBG("loadCertHashes success");
227                                         }
228                                         else
229                                         {
230                                                 _ERR("loadCertHashes failed");
231                                         }
232                                 }
233                                 else
234                                 {
235                                         _ERR("decodeTLV failed");
236                                 }
237                         }
238                         else
239                         {
240                                 _ERR("decodeTLV failed");
241                         }
242                         tlv.returnToParentTLV();
243                 }
244
245                 return 0;
246         }
247
248         static void loadAPDUAccessRule(AccessRule *rule, const ByteArray &data)
249         {
250                 SimpleTLV tlv(data);
251
252                 if (rule == NULL) {
253                         _ERR("invalid parameter");
254                         return;
255                 }
256
257                 if (tlv.decodeTLV() == true)
258                 {
259                         switch (tlv.getTag())
260                         {
261                         case 0xA0 : /* CHOICE 0 : APDUPermission */
262                                 rule->setAPDUAccessRule(SimpleTLV::getBoolean(tlv.getValue()));
263                                 break;
264
265                         case 0xA1 : /* CHOICE 1 : APDUFilters */
266                                 tlv.enterToValueTLV();
267                                 while (tlv.decodeTLV() == true)
268                                 {
269                                         if (tlv.getTag() == 0x04) /* OCTET STRING */
270                                         {
271                                                 ByteArray apdu, mask, value;
272
273                                                 value = tlv.getValue();
274
275                                                 _DBG("APDU rule : %s", value.toString().c_str());
276
277                                                 if (value.size() == 8) /* apdu 4 bytes + mask 4 bytes */
278                                                 {
279                                                         apdu.assign(value.getBuffer(), 4);
280                                                         mask.assign(value.getBuffer(4), 4);
281
282                                                         rule->addAPDUAccessRule(apdu, mask);
283                                                 }
284                                                 else
285                                                 {
286                                                         _ERR("Invalid APDU rule : %s", value.toString().c_str());
287                                                 }
288                                         }
289                                         else
290                                         {
291                                                 _ERR("Unknown tag : 0x%02X", tlv.getTag());
292                                         }
293                                 }
294                                 tlv.returnToParentTLV();
295                                 break;
296
297                         default :
298                                 _ERR("Unknown tag : 0x%02X", tlv.getTag());
299                                 break;
300                         }
301                 }
302         }
303
304         static void loadNFCAccessRule(AccessRule *rule, const ByteArray &data)
305         {
306                 if (rule == NULL) {
307                         _ERR("invalid parameter");
308                         return;
309                 }
310
311                 rule->setNFCAccessRule(SimpleTLV::getBoolean(data));
312         }
313
314         static void loadAccessCondition(AccessCondition &condition, const ByteArray &data)
315         {
316                 if (data.size() > 0)
317                 {
318                         SimpleTLV tlv(data);
319                         ByteArray hash;
320
321                         while (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE */
322                         {
323                                 if (tlv.size() > 0)
324                                 {
325                                         /* access granted for specific applications */
326                                         tlv.enterToValueTLV();
327                                         if (tlv.decodeTLV())
328                                         {
329                                                 switch (tlv.getTag())
330                                                 {
331                                                 case 0x04 : /* OCTET STRING : CertHash */
332                                                         _DBG("aid : %s, hash : %s", condition.getAID().toString().c_str(), tlv.getValue().toString().c_str());
333
334                                                         hash = tlv.getValue();
335                                                         condition.addAccessRule(tlv.getValue());
336                                                         break;
337
338                                                 case 0xA0 : /* CHOICE 0 : AccessRules */
339                                                         tlv.enterToValueTLV();
340                                                         if (tlv.decodeTLV())
341                                                         {
342                                                                 AccessRule *rule = condition.getAccessRule(hash);
343                                                                 if (rule == NULL) {
344                                                                         condition.addAccessRule(hash);
345                                                                         rule = condition.getAccessRule(hash);
346                                                                 }
347
348                                                                 switch (tlv.getTag())
349                                                                 {
350                                                                 case 0xA0 : /* CHOICE 0 : APDUAccessRule */
351                                                                         loadAPDUAccessRule(rule, tlv.getValue());
352                                                                         break;
353
354                                                                 case 0xA1 : /* CHOICE 1 : NFCAccessRule */
355                                                                         loadNFCAccessRule(rule, tlv.getValue());
356                                                                         break;
357
358                                                                 default :
359                                                                         _ERR("Unknown tag : 0x%02X", tlv.getTag());
360                                                                         break;
361                                                                 }
362                                                         }
363                                                         else
364                                                         {
365                                                                 _ERR("tlv.decodeTLV failed");
366                                                         }
367                                                         tlv.returnToParentTLV();
368                                                         break;
369
370                                                 default :
371                                                         _ERR("Unknown tag : 0x%02X", tlv.getTag());
372                                                         break;
373                                                 }
374                                         }
375                                         else
376                                         {
377                                                 _ERR("tlv.decodeTLV failed");
378                                         }
379                                         tlv.returnToParentTLV();
380                                 }
381                                 else
382                                 {
383                                         _INFO("access denied for all applications, aid : %s", condition.getAID().toString().c_str());
384
385                                         condition.setAccessCondition(false);
386                                         break;
387                                 }
388                         }
389                 }
390                 else
391                 {
392                         /* empty file, it means deny for all application */
393                         _INFO("access denied for all applications, aid : %s", condition.getAID().toString().c_str());
394
395                         condition.setAccessCondition(false);
396                 }
397         }
398
399         int GPARFACL::loadAccessConditions(Channel *channel, const ByteArray &aid, const ByteArray &path)
400         {
401                 FileObject file(channel);
402                 ByteArray data;
403
404                 file.select(NumberStream::getLittleEndianNumber(path));
405                 file.readBinary(0, 0, file.getFCP()->getFileSize(), data);
406
407                 _DBG("data : %s", data.toString().c_str());
408
409                 AccessCondition condition;
410
411                 condition.setAID(aid);
412                 loadAccessCondition(condition, data);
413
414                 pair<ByteArray, AccessCondition> newItem(aid, condition);
415
416                 mapConditions.insert(newItem);
417
418                 return 0;
419         }
420
421 } /* namespace smartcard_service_api */