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