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