Apply coding rule
[platform/core/connectivity/smartcard-service.git] / common / GPARAACL.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 "GPARAACL.h"
24 #include "GPARAM.h"
25 #include "NumberStream.h"
26 #include "SimpleTLV.h"
27 #include "ISO7816BERTLV.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 aid_aram[] = { 0xA0, 0x00, 0x00, 0x01, 0x51, 0x41, 0x43, 0x4C, 0x00 };
37         static ByteArray AID_ARAM(ARRAY_AND_SIZE(aid_aram));
38
39 #define GET_DATA_ALL            0
40 #define GET_DATA_SPECIFIC       1
41 #define GET_DATA_REFRESH_TAG    2
42 #define GET_DATA_NEXT           3
43
44 #define ARAM_TAG_ALL_AR         0x0000FF40
45 #define ARAM_TAG_AR             0x0000FF50
46 #define ARAM_TAG_REFRESH        0x0000DF20
47
48 #define DO_TAG_AID_REF          0x0000004F
49 #define DO_TAG_AID_REF_DEFAULT  0x000000C0
50 #define DO_TAG_HASH_REF         0x000000C1
51 #define DO_TAG_APDU_AR          0x000000D0
52 #define DO_TAG_NFC_AR           0x000000D1
53 #define DO_TAG_REF              0x000000E1
54 #define DO_TAG_REF_AR           0x000000E2
55 #define DO_TAG_AR               0x000000E3
56
57         GPARAACL::GPARAACL() : AccessControlList()
58         {
59         }
60
61         GPARAACL::~GPARAACL()
62         {
63         }
64
65         static ByteArray getAID(SimpleTLV &tlv)
66         {
67                 ByteArray result;
68
69                 _BEGIN();
70
71                 if (tlv.decodeTLV() == true) {
72                         switch (tlv.getTag()) {
73                         case DO_TAG_AID_REF :
74                                 if (tlv.size() > 0) {
75                                         result = tlv.getValue();
76                                 } else {
77                                         result = AccessControlList::ALL_SE_APPS;
78                                 }
79                                 break;
80
81                         case DO_TAG_AID_REF_DEFAULT :
82                                 result = AccessControlList::DEFAULT_SE_APP;
83                                 break;
84
85                         default :
86                                 _ERR("decodeTLV failed, %s", tlv.toString().c_str());
87                                 break;
88                         }
89                 } else {
90                         _ERR("decodeTLV failed, %s", tlv.toString().c_str());
91                 }
92
93                 _END();
94
95                 return result;
96         }
97
98         static ByteArray getHash(SimpleTLV &tlv)
99         {
100                 ByteArray result;
101
102                 _BEGIN();
103
104                 if (tlv.decodeTLV() == true &&
105                         tlv.getTag() == DO_TAG_HASH_REF) {
106                         if (tlv.size() > 0) {
107                                 result = tlv.getValue();
108                         } else {
109                                 result = AccessControlList::ALL_DEVICE_APPS;
110                         }
111                 } else {
112                         _ERR("decodeTLV failed, %s", tlv.toString().c_str());
113                 }
114
115                 _END();
116
117                 return result;
118         }
119
120         static int parseRefDO(SimpleTLV &tlv, ByteArray &aid, ByteArray &hash)
121         {
122                 int result = SCARD_ERROR_OK;
123
124                 _BEGIN();
125
126                 if (tlv.decodeTLV() == true && tlv.getTag() == DO_TAG_REF) {
127                         tlv.enterToValueTLV();
128                         aid = getAID(tlv);
129                         hash = getHash(tlv);
130                         tlv.returnToParentTLV();
131
132                         _DBG("aid : %s, hash : %s", aid.toString().c_str(), hash.toString().c_str());
133                 } else {
134                         _ERR("unknown tag : %s", tlv.toString().c_str());
135                         result = SCARD_ERROR_ILLEGAL_PARAM;
136                 }
137
138                 _END();
139
140                 return result;
141         }
142
143         static int parseARDO(SimpleTLV &tlv, vector<ByteArray> &apduRule,
144                 ByteArray &nfcRule)
145         {
146                 int result = SCARD_ERROR_OK;
147
148                 _BEGIN();
149
150                 if (tlv.decodeTLV() == true && tlv.getTag() == DO_TAG_AR) {
151                         tlv.enterToValueTLV();
152                         while (tlv.decodeTLV() == true) {
153                                 int length = tlv.size();
154
155                                 switch (tlv.getTag()) {
156                                 case DO_TAG_APDU_AR :
157                                         if (length > 1) {
158                                                 int i;
159                                                 ByteArray temp;
160
161                                                 for (i = 0; i < length; i += 8) {
162                                                         temp.assign(tlv.getValue().getBuffer(i), 8);
163                                                         _DBG("apdu rule[%d] : %s", temp.size(), temp.toString().c_str());
164                                                         apduRule.push_back(temp);
165                                                 }
166                                         } else if (length == 1){
167                                                 _DBG("apdu rule : %s", tlv.getValue().toString().c_str());
168                                                 apduRule.push_back(tlv.getValue());
169                                         } else {
170                                                 _ERR("invalid rule, %s", tlv.toString().c_str());
171                                         }
172                                         break;
173
174                                 case DO_TAG_NFC_AR :
175                                         nfcRule = tlv.getValue();
176                                         _DBG("nfc rule : %s", tlv.getValue().toString().c_str());
177                                         break;
178
179                                 default :
180                                         break;
181                                 }
182                         }
183                         tlv.returnToParentTLV();
184                 } else {
185                         result = SCARD_ERROR_ILLEGAL_PARAM;
186                 }
187
188                 _END();
189
190                 return result;
191         }
192
193         void GPARAACL::addCondition(const ByteArray &aid, const ByteArray &hash,
194                 const vector<ByteArray> &apduRule, const ByteArray &nfcRule)
195         {
196                 AccessCondition &condition = getAccessCondition(aid);
197
198                 _BEGIN();
199
200                 condition.addAccessRule(hash);
201
202                 if (apduRule.size() > 0) {
203                         if (apduRule.size() == 1 &&
204                                 apduRule[0].size() == 1) {
205                                 /* apdu grant/deny */
206                                 if (apduRule[0][0] == 1) {
207                                         condition.setAPDUAccessRule(hash, true);
208                                 } else {
209                                         condition.setAPDUAccessRule(hash, false);
210                                 }
211                         } else {
212                                 size_t i;
213
214                                 for (i = 0; i < apduRule.size(); i++) {
215                                         condition.addAPDUAccessRule(hash, apduRule[i]);
216                                 }
217                         }
218                 }
219
220                 if (nfcRule.size() == 1) {
221                         if (nfcRule[0] == 1) {
222                                 condition.setNFCAccessRule(hash, true);
223                         } else {
224                                 condition.setNFCAccessRule(hash, false);
225                         }
226                 }
227
228                 _END();
229         }
230
231         int GPARAACL::updateRule(const ByteArray &data)
232         {
233                 int result = SCARD_ERROR_OK;
234                 SimpleTLV tlv(data);
235
236                 _BEGIN();
237
238                 while (tlv.decodeTLV() == true) {
239                         if (tlv.getTag() == DO_TAG_REF_AR) {
240                                 ByteArray aid, hash, nfcRule;
241                                 vector<ByteArray> apduRule;
242
243                                 tlv.enterToValueTLV();
244                                 result = parseRefDO(tlv, aid, hash);
245
246                                 if (result >= SCARD_ERROR_OK) {
247                                         result = parseARDO(tlv, apduRule, nfcRule);
248                                 }
249                                 tlv.returnToParentTLV();
250
251                                 addCondition(aid, hash, apduRule, nfcRule);
252                         } else {
253                                 _ERR("unknown tag, [%x]", tlv.getTag());
254                                 result = SCARD_ERROR_ILLEGAL_PARAM;
255                                 break;
256                         }
257                 }
258
259                 _END();
260
261                 return result;
262         }
263
264         int GPARAACL::loadACL(GPARAM &aram)
265         {
266                 int result = SCARD_ERROR_OK;
267                 ByteArray refreshTag, response;
268
269                 _BEGIN();
270
271                 if (aram.isClosed() == true) {
272                         return SCARD_ERROR_ILLEGAL_STATE;
273                 }
274
275                 /* get refresh tag */
276                 result = aram.getDataRefreshTag(refreshTag);
277                 if (result >= SCARD_ERROR_OK) {
278                         /* check refresh tag */
279                         if (this->refreshTag.isEmpty() == true ||
280                                 this->refreshTag != refreshTag) {
281                                 result = aram.getDataAll(response);
282                                 if (result >= SCARD_ERROR_OK) {
283                                         result = updateRule(response);
284
285                                         /* update refresh tag */
286                                         this->refreshTag = refreshTag;
287                                 } else {
288                                         _ERR("getDataAll failed, [%x]", result);
289                                 }
290                         } else {
291                                 _INFO("access rules are not changed. skip update");
292                         }
293
294                         printAccessControlList();
295                 } else {
296                         _ERR("transmitSync failed, %x", result);
297                 }
298
299                 _END();
300
301                 return result;
302         }
303
304         int GPARAACL::loadACL(Channel *channel)
305         {
306                 int result = SCARD_ERROR_OK;
307
308                 _BEGIN();
309
310                 if (channel == NULL) {
311                         return SCARD_ERROR_ILLEGAL_PARAM;
312                 }
313
314                 GPARAM aram(channel);
315
316                 result = aram.select();
317                 if (result >= SCARD_ERROR_OK) {
318                         result = loadACL(aram);
319                 } else {
320                         _ERR("select failed, [%x]", result);
321                 }
322
323                 _END();
324
325                 return result;
326         }
327
328         static bool _isAuthorizedAccess(const ByteArray &data, const ByteArray &command)
329         {
330                 vector<ByteArray> apduRule;
331                 ByteArray nfcRule;
332                 SimpleTLV tlv(data);
333                 bool result = false;
334
335                 if (parseARDO(tlv, apduRule, nfcRule) >= SCARD_ERROR_OK) {
336                         if (apduRule.size() > 0) {
337                                 if (apduRule.size() > 1 ||
338                                         apduRule[0].size() != 1) {
339                                         if (command.size() > 0) {
340                                                 /* TODO : check apdu rule */
341                                         } else {
342                                                 /* check hash only */
343                                                 result = true;
344                                         }
345                                 } else {
346                                         result = (apduRule[0][0] == 1 ? true : false);
347                                 }
348                         } else {
349                                 _ERR("unknown data : %s", tlv.toString().c_str());
350                         }
351                 } else {
352                         _ERR("parseARDO failed : %s", tlv.toString().c_str());
353                 }
354
355                 return result;
356         }
357
358         static bool _isAuthorizedNFCAccess(const ByteArray &data)
359         {
360                 vector<ByteArray> apduRule;
361                 ByteArray nfcRule;
362                 SimpleTLV tlv(data);
363                 bool result = false;
364
365                 if (parseARDO(tlv, apduRule, nfcRule) >= SCARD_ERROR_OK) {
366                         if (nfcRule.size() == 1) {
367                                 result = (nfcRule[0] == 1 ? true : false);
368                         } else {
369                                 _ERR("unknown data : %s", nfcRule.toString().c_str());
370                         }
371                 } else {
372                         _ERR("parseARDO failed : %s", tlv.toString().c_str());
373                 }
374
375                 return result;
376         }
377
378         bool GPARAACL::isAuthorizedAccess(GPARAM &aram, const ByteArray &aid,
379                 const ByteArray &certHash) const
380         {
381                 vector<ByteArray> hashes;
382
383                 hashes.push_back(certHash);
384
385                 return isAuthorizedAccess(aram, aid, hashes, ByteArray::EMPTY);
386         }
387
388         bool GPARAACL::isAuthorizedAccess(GPARAM &aram,
389                 const unsigned char *aidBuffer,
390                 unsigned int aidLength,
391                 const unsigned char *certHashBuffer,
392                 unsigned int certHashLength) const
393         {
394                 ByteArray aid(aidBuffer, aidLength);
395                 ByteArray hash(certHashBuffer, certHashLength);
396
397                 return isAuthorizedAccess(aram, aid, hash);
398         }
399
400         bool GPARAACL::isAuthorizedAccess(GPARAM &aram, const ByteArray &aid,
401                 const vector<ByteArray> &certHashes) const
402         {
403                 return isAuthorizedAccess(aram, aid, certHashes, ByteArray::EMPTY);
404         }
405
406         bool GPARAACL::isAuthorizedAccess(GPARAM &aram, const ByteArray &aid,
407                 const vector<ByteArray> &certHashes, const ByteArray &command) const
408         {
409                 bool result = allGranted;
410                 ByteArray data;
411                 vector<ByteArray>::const_reverse_iterator item;
412
413                 if (aram.isClosed() == true)
414                         return result;
415
416                 _BEGIN();
417
418                 if (result == true) {
419                         goto END;
420                 }
421                 /* Step A, find with aid and cert hashes */
422                 for (item = certHashes.rbegin();
423                         result == false && item != certHashes.rend();
424                         item++) {
425                         if (aram.getDataSpecific(aid, *item, data)
426                                 >= SCARD_ERROR_OK && data.size() > 0) {
427                                 result = _isAuthorizedAccess(data, command);
428                                 _INFO("rule found (%s): [%s:%s]", result ? "accept" : "deny", aid.toString().c_str(), (*item).toString().c_str());
429                                 goto END;
430                         }
431                 }
432
433                 /* Step B, find with aid and ALL_DEVICES_APPS */
434                 if (aram.getDataSpecific(aid, ByteArray::EMPTY, data)
435                         >= SCARD_ERROR_OK && data.size() > 0) {
436                         result = _isAuthorizedAccess(data, command);
437                         _INFO("rule found (%s): [%s:%s]", result ? "accept" : "deny", aid.toString().c_str(), "All device applications");
438                         goto END;
439                 }
440
441                 /* Step C, find with ALL_SE_APPS and hashes */
442                 for (item = certHashes.rbegin();
443                         result == false && item != certHashes.rend();
444                         item++) {
445                         if (aram.getDataSpecific(ByteArray::EMPTY, *item, data)
446                                 >= SCARD_ERROR_OK && data.size() > 0) {
447                                 result = _isAuthorizedAccess(data, command);
448                                 _INFO("rule found (%s): [%s:%s]", result ? "accept" : "deny", "All SE Applications", (*item).toString().c_str());
449                                 goto END;
450                         }
451                 }
452
453                 /* Step D, find with ALL_SE_APPS and ALL_DEVICES_APPS */
454                 if (aram.getDataSpecific(ByteArray::EMPTY, ByteArray::EMPTY, data)
455                         >= SCARD_ERROR_OK && data.size() > 0) {
456                         result = _isAuthorizedAccess(data, command);
457                         _INFO("rule found (%s): [%s:%s]", result ? "accept" : "deny", "All SE Applications", "All device applications");
458                         goto END;
459                 }
460
461         END :
462                 _END();
463
464                 return result;
465         }
466
467         bool GPARAACL::isAuthorizedNFCAccess(GPARAM &aram, const ByteArray &aid,
468                 const vector<ByteArray> &certHashes) const
469         {
470                 bool result = allGranted;
471                 ByteArray data;
472                 vector<ByteArray>::const_reverse_iterator item;
473
474                 if (aram.isClosed() == true)
475                         return result;
476
477                 _BEGIN();
478
479                 if (result == true) {
480                         goto END;
481                 }
482                 /* Step A, find with aid and cert hashes */
483                 for (item = certHashes.rbegin();
484                         result == false && item != certHashes.rend();
485                         item++) {
486                         if (aram.getDataSpecific(aid, *item, data)
487                                 >= SCARD_ERROR_OK && data.size() > 0) {
488                                 result = _isAuthorizedNFCAccess(data);
489                                 _INFO("rule found (%s): [%s:%s]", result ? "accept" : "deny", aid.toString().c_str(), (*item).toString().c_str());
490                                 goto END;
491                         }
492                 }
493
494                 /* Step B, find with aid and ALL_DEVICES_APPS */
495                 if (aram.getDataSpecific(aid, ByteArray::EMPTY, data)
496                         >= SCARD_ERROR_OK && data.size() > 0) {
497                         result = _isAuthorizedNFCAccess(data);
498                         _INFO("rule found (%s): [%s:%s]", result ? "accept" : "deny", aid.toString().c_str(), "All device applications");
499                         goto END;
500                 }
501
502                 /* Step C, find with ALL_SE_APPS and hashes */
503                 for (item = certHashes.rbegin();
504                         result == false && item != certHashes.rend();
505                         item++) {
506                         if (aram.getDataSpecific(ByteArray::EMPTY, *item, data)
507                                 >= SCARD_ERROR_OK && data.size() > 0) {
508                                 result = _isAuthorizedNFCAccess(data);
509                                 _INFO("rule found (%s): [%s:%s]", result ? "accept" : "deny", "All SE Applications", (*item).toString().c_str());
510                                 goto END;
511                         }
512                 }
513
514                 /* Step D, find with ALL_SE_APPS and ALL_DEVICES_APPS */
515                 if (aram.getDataSpecific(ByteArray::EMPTY, ByteArray::EMPTY, data)
516                         >= SCARD_ERROR_OK && data.size() > 0) {
517                         result = _isAuthorizedNFCAccess(data);
518                         _INFO("rule found (%s): [%s:%s]", result ? "accept" : "deny", "All SE Applications", "All device applications");
519                         goto END;
520                 }
521
522         END :
523                 _END();
524
525                 return result;
526         }
527 } /* namespace smartcard_service_api */