code cleanup and fix build 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                                         }
81                                         else
82                                         {
83                                                 _INFO("loadAccessControl failed, every request will be accepted.");
84                                                 result = SCARD_ERROR_OK;
85                                         }
86                                 }
87                                 else
88                                 {
89                                         _INFO("dodf null, every request will be accepted.");
90                                 }
91                         }
92                         else
93                         {
94                                 _INFO("odf null, every request will be accepted.");
95                         }
96                 }
97                 else
98                 {
99                         _ERR("failed to open PKCS15, every request will be denied.");
100                 }
101
102                 _END();
103
104                 return result;
105         }
106
107         int GPARFACL::loadAccessControl(Channel *channel, PKCS15DODF *dodf)
108         {
109                 int result = -1;
110                 ByteArray path;
111
112                 if ((result = dodf->searchOID(OID_GLOBALPLATFORM, path)) == 0)
113                 {
114                         ByteArray data;
115                         FileObject file(channel);
116
117                         _DBG("oid path : %s", path.toString().c_str());
118
119                         file.select(NumberStream::getLittleEndianNumber(path));
120                         file.readBinary(0, 0, file.getFCP()->getFileSize(), data);
121
122                         _DBG("data : %s", data.toString().c_str());
123
124                         /* PKCS #15 and DODF OID exists. apply access control rule!! */
125                         allGranted = false;
126
127                         SimpleTLV tlv(data);
128
129                         if (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE : AccessControlMainFile */
130                         {
131                                 tlv.enterToValueTLV();
132
133                                 /* refresh Tag */
134                                 ByteArray refreshTag;
135
136                                 refreshTag = SimpleTLV::getOctetString(tlv);
137                                 _DBG("current refresh tag : %s", refreshTag.toString().c_str());
138
139                                 if (this->refreshTag != refreshTag) /* need to update access control list */
140                                 {
141                                         this->refreshTag = refreshTag;
142
143                                         releaseACL();
144
145                                         /* access control rule path */
146                                         if (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE : Path */
147                                         {
148                                                 /* TODO : parse path */
149                                                 ByteArray path;
150
151                                                 /* OCTET STRING */
152                                                 path = SimpleTLV::getOctetString(tlv.getValue());
153                                                 _DBG("access control rule path : %s", path.toString().c_str());
154
155                                                 if (loadRules(channel, path) == 0)
156                                                 {
157                                                         _DBG("loadRules success");
158                                                 }
159                                                 else
160                                                 {
161                                                         _ERR("loadRules failed");
162                                                 }
163                                         }
164                                 }
165                                 else
166                                 {
167                                         _INFO("access rules are not changed. skip update");
168                                 }
169                                 tlv.returnToParentTLV();
170                         }
171                         else
172                         {
173                                 _ERR("tlv.decodeTLV failed");
174                         }
175                 }
176                 else
177                 {
178                         _ERR("OID not found");
179                 }
180
181                 return result;
182         }
183
184         int GPARFACL::loadRules(Channel *channel, const ByteArray &path)
185         {
186                 FileObject file(channel);
187                 ByteArray data, aid;
188
189                 file.select(NumberStream::getLittleEndianNumber(path));
190                 file.readBinary(0, 0, file.getFCP()->getFileSize(), data);
191
192                 _DBG("data : %s", data.toString().c_str());
193
194                 SimpleTLV tlv(data);
195
196                 while (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE : Rule */
197                 {
198                         tlv.enterToValueTLV();
199                         if (tlv.decodeTLV() == true)
200                         {
201                                 /* target */
202                                 switch (tlv.getTag())
203                                 {
204                                 case 0xA0 : /* CHOICE 0 : EXPLICIT AID */
205                                         /* OCTET STRING */
206                                         aid = SimpleTLV::getOctetString(tlv.getValue());
207                                         break;
208
209                                 case 0x81 : /* CHOICE 1?? : default */
210                                         aid = AccessControlList::DEFAULT_SE_APP;
211                                         break;
212
213                                 case 0x82 : /* CHOICE 2?? : any application */
214                                         aid = AccessControlList::ALL_SE_APPS;
215                                         break;
216                                 }
217
218                                 _DBG("aid : %s", aid.toString().c_str());
219
220                                 /* access condition path */
221                                 if (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE : Path */
222                                 {
223                                         ByteArray path;
224
225                                         /* OCTET STRING */
226                                         path = SimpleTLV::getOctetString(tlv.getValue());
227                                         _DBG("path : %s", path.toString().c_str());
228
229                                         if (loadAccessConditions(channel, aid, path) == 0)
230                                         {
231                                                 _DBG("loadCertHashes success");
232                                         }
233                                         else
234                                         {
235                                                 _ERR("loadCertHashes failed");
236                                         }
237                                 }
238                                 else
239                                 {
240                                         _ERR("decodeTLV failed");
241                                 }
242                         }
243                         else
244                         {
245                                 _ERR("decodeTLV failed");
246                         }
247                         tlv.returnToParentTLV();
248                 }
249
250                 return 0;
251         }
252
253         static void loadAPDUAccessRule(AccessRule *rule, const ByteArray &data)
254         {
255                 SimpleTLV tlv(data);
256
257                 if (rule == NULL) {
258                         _ERR("invalid parameter");
259                         return;
260                 }
261
262                 if (tlv.decodeTLV() == true)
263                 {
264                         switch (tlv.getTag())
265                         {
266                         case 0xA0 : /* CHOICE 0 : APDUPermission */
267                                 rule->setAPDUAccessRule(SimpleTLV::getBoolean(tlv.getValue()));
268                                 break;
269
270                         case 0xA1 : /* CHOICE 1 : APDUFilters */
271                                 tlv.enterToValueTLV();
272                                 while (tlv.decodeTLV() == true)
273                                 {
274                                         if (tlv.getTag() == 0x04) /* OCTET STRING */
275                                         {
276                                                 ByteArray apdu, mask, value;
277
278                                                 value = tlv.getValue();
279
280                                                 _DBG("APDU rule : %s", value.toString().c_str());
281
282                                                 if (value.size() == 8) /* apdu 4 bytes + mask 4 bytes */
283                                                 {
284                                                         apdu.assign(value.getBuffer(), 4);
285                                                         mask.assign(value.getBuffer(4), 4);
286
287                                                         rule->addAPDUAccessRule(apdu, mask);
288                                                 }
289                                                 else
290                                                 {
291                                                         _ERR("Invalid APDU rule : %s", value.toString().c_str());
292                                                 }
293                                         }
294                                         else
295                                         {
296                                                 _ERR("Unknown tag : 0x%02X", tlv.getTag());
297                                         }
298                                 }
299                                 tlv.returnToParentTLV();
300                                 break;
301
302                         default :
303                                 _ERR("Unknown tag : 0x%02X", tlv.getTag());
304                                 break;
305                         }
306                 }
307         }
308
309         static void loadNFCAccessRule(AccessRule *rule, const ByteArray &data)
310         {
311                 if (rule == NULL) {
312                         _ERR("invalid parameter");
313                         return;
314                 }
315
316                 rule->setNFCAccessRule(SimpleTLV::getBoolean(data));
317         }
318
319         static void loadAccessCondition(AccessCondition &condition, const ByteArray &data)
320         {
321                 if (data.size() > 0)
322                 {
323                         SimpleTLV tlv(data);
324                         ByteArray hash;
325
326                         while (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE */
327                         {
328                                 if (tlv.size() > 0)
329                                 {
330                                         /* access granted for specific applications */
331                                         tlv.enterToValueTLV();
332                                         if (tlv.decodeTLV())
333                                         {
334                                                 switch (tlv.getTag())
335                                                 {
336                                                 case 0x04 : /* OCTET STRING : CertHash */
337                                                         _DBG("aid : %s, hash : %s", condition.getAID().toString().c_str(), tlv.getValue().toString().c_str());
338
339                                                         hash = tlv.getValue();
340                                                         condition.addAccessRule(tlv.getValue());
341                                                         break;
342
343                                                 case 0xA0 : /* CHOICE 0 : AccessRules */
344                                                         tlv.enterToValueTLV();
345                                                         if (tlv.decodeTLV())
346                                                         {
347                                                                 AccessRule *rule = condition.getAccessRule(hash);
348                                                                 if (rule == NULL) {
349                                                                         condition.addAccessRule(hash);
350                                                                         rule = condition.getAccessRule(hash);
351                                                                 }
352
353                                                                 switch (tlv.getTag())
354                                                                 {
355                                                                 case 0xA0 : /* CHOICE 0 : APDUAccessRule */
356                                                                         loadAPDUAccessRule(rule, tlv.getValue());
357                                                                         break;
358
359                                                                 case 0xA1 : /* CHOICE 1 : NFCAccessRule */
360                                                                         loadNFCAccessRule(rule, tlv.getValue());
361                                                                         break;
362
363                                                                 default :
364                                                                         _ERR("Unknown tag : 0x%02X", tlv.getTag());
365                                                                         break;
366                                                                 }
367                                                         }
368                                                         else
369                                                         {
370                                                                 _ERR("tlv.decodeTLV failed");
371                                                         }
372                                                         tlv.returnToParentTLV();
373                                                         break;
374
375                                                 default :
376                                                         _ERR("Unknown tag : 0x%02X", tlv.getTag());
377                                                         break;
378                                                 }
379                                         }
380                                         else
381                                         {
382                                                 _ERR("tlv.decodeTLV failed");
383                                         }
384                                         tlv.returnToParentTLV();
385                                 }
386                                 else
387                                 {
388                                         _INFO("access denied for all applications, aid : %s", condition.getAID().toString().c_str());
389
390                                         condition.setAccessCondition(false);
391                                         break;
392                                 }
393                         }
394                 }
395                 else
396                 {
397                         /* empty file, it means deny for all application */
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 */