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