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