2 * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 /* standard library header */
19 /* SLP library header */
25 #include "NumberStream.h"
26 #include "SimpleTLV.h"
27 #include "ISO7816BERTLV.h"
28 #include "AccessCondition.h"
31 #define EXTERN_API __attribute__((visibility("default")))
34 namespace smartcard_service_api
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));
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
44 #define ARAM_TAG_ALL_AR 0x0000FF40
45 #define ARAM_TAG_AR 0x0000FF50
46 #define ARAM_TAG_REFRESH 0x0000DF20
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
57 GPARAACL::GPARAACL() : AccessControlList()
65 static ByteArray getAID(SimpleTLV &tlv)
71 if (tlv.decodeTLV() == true) {
72 switch (tlv.getTag()) {
75 result = tlv.getValue();
77 result = AccessControlList::ALL_SE_APPS;
81 case DO_TAG_AID_REF_DEFAULT :
82 result = AccessControlList::DEFAULT_SE_APP;
86 _ERR("decodeTLV failed, %s", tlv.toString().c_str());
90 _ERR("decodeTLV failed, %s", tlv.toString().c_str());
98 static ByteArray getHash(SimpleTLV &tlv)
104 if (tlv.decodeTLV() == true &&
105 tlv.getTag() == DO_TAG_HASH_REF) {
106 if (tlv.size() > 0) {
107 result = tlv.getValue();
109 result = AccessControlList::ALL_DEVICE_APPS;
112 _ERR("decodeTLV failed, %s", tlv.toString().c_str());
120 static int parseRefDO(SimpleTLV &tlv, ByteArray &aid, ByteArray &hash)
122 int result = SCARD_ERROR_OK;
126 if (tlv.decodeTLV() == true && tlv.getTag() == DO_TAG_REF) {
127 tlv.enterToValueTLV();
130 tlv.returnToParentTLV();
132 _DBG("aid : %s, hash : %s", aid.toString().c_str(), hash.toString().c_str());
134 _ERR("unknown tag : %s", tlv.toString().c_str());
135 result = SCARD_ERROR_ILLEGAL_PARAM;
143 static int parseARDO(SimpleTLV &tlv, vector<ByteArray> &apduRule,
146 int result = SCARD_ERROR_OK;
150 if (tlv.decodeTLV() == true && tlv.getTag() == DO_TAG_AR) {
151 tlv.enterToValueTLV();
152 while (tlv.decodeTLV() == true) {
153 int length = tlv.size();
155 switch (tlv.getTag()) {
156 case DO_TAG_APDU_AR :
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);
166 } else if (length == 1){
167 _DBG("apdu rule : %s", tlv.getValue().toString().c_str());
168 apduRule.push_back(tlv.getValue());
170 _ERR("invalid rule, %s", tlv.toString().c_str());
175 nfcRule = tlv.getValue();
176 _DBG("nfc rule : %s", tlv.getValue().toString().c_str());
183 tlv.returnToParentTLV();
185 result = SCARD_ERROR_ILLEGAL_PARAM;
193 void GPARAACL::addCondition(const ByteArray &aid, const ByteArray &hash,
194 const vector<ByteArray> &apduRule, const ByteArray &nfcRule)
196 AccessCondition &condition = getAccessCondition(aid);
200 condition.addAccessRule(hash);
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);
209 condition.setAPDUAccessRule(hash, false);
214 for (i = 0; i < apduRule.size(); i++) {
215 condition.addAPDUAccessRule(hash, apduRule[i]);
220 if (nfcRule.size() == 1) {
221 if (nfcRule[0] == 1) {
222 condition.setNFCAccessRule(hash, true);
224 condition.setNFCAccessRule(hash, false);
231 int GPARAACL::updateRule(const ByteArray &data)
233 int result = SCARD_ERROR_OK;
238 while (tlv.decodeTLV() == true) {
239 if (tlv.getTag() == DO_TAG_REF_AR) {
240 ByteArray aid, hash, nfcRule;
241 vector<ByteArray> apduRule;
243 tlv.enterToValueTLV();
244 result = parseRefDO(tlv, aid, hash);
246 if (result >= SCARD_ERROR_OK) {
247 result = parseARDO(tlv, apduRule, nfcRule);
249 tlv.returnToParentTLV();
251 addCondition(aid, hash, apduRule, nfcRule);
253 _ERR("unknown tag, [%x]", tlv.getTag());
254 result = SCARD_ERROR_ILLEGAL_PARAM;
264 int GPARAACL::loadACL(GPARAM &aram)
266 int result = SCARD_ERROR_OK;
267 ByteArray refreshTag, response;
271 if (aram.isClosed() == true) {
272 return SCARD_ERROR_ILLEGAL_STATE;
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);
285 /* update refresh tag */
286 this->refreshTag = refreshTag;
288 _ERR("getDataAll failed, [%x]", result);
291 _INFO("access rules are not changed. skip update");
294 printAccessControlList();
296 _ERR("transmitSync failed, %x", result);
304 int GPARAACL::loadACL(Channel *channel)
306 int result = SCARD_ERROR_OK;
310 if (channel == NULL) {
311 return SCARD_ERROR_ILLEGAL_PARAM;
314 GPARAM aram(channel);
316 result = aram.select();
317 if (result >= SCARD_ERROR_OK) {
318 result = loadACL(aram);
320 _ERR("select failed, [%x]", result);
328 static bool _isAuthorizedAccess(const ByteArray &data, const ByteArray &command)
330 vector<ByteArray> apduRule;
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 */
342 /* check hash only */
346 result = (apduRule[0][0] == 1 ? true : false);
349 _ERR("unknown data : %s", tlv.toString().c_str());
352 _ERR("parseARDO failed : %s", tlv.toString().c_str());
358 static bool _isAuthorizedNFCAccess(const ByteArray &data)
360 vector<ByteArray> apduRule;
365 if (parseARDO(tlv, apduRule, nfcRule) >= SCARD_ERROR_OK) {
366 if (nfcRule.size() == 1) {
367 result = (nfcRule[0] == 1 ? true : false);
369 _ERR("unknown data : %s", nfcRule.toString().c_str());
372 _ERR("parseARDO failed : %s", tlv.toString().c_str());
378 bool GPARAACL::isAuthorizedAccess(GPARAM &aram, const ByteArray &aid,
379 const ByteArray &certHash) const
381 vector<ByteArray> hashes;
383 hashes.push_back(certHash);
385 return isAuthorizedAccess(aram, aid, hashes, ByteArray::EMPTY);
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
394 ByteArray aid(aidBuffer, aidLength);
395 ByteArray hash(certHashBuffer, certHashLength);
397 return isAuthorizedAccess(aram, aid, hash);
400 bool GPARAACL::isAuthorizedAccess(GPARAM &aram, const ByteArray &aid,
401 const vector<ByteArray> &certHashes) const
403 return isAuthorizedAccess(aram, aid, certHashes, ByteArray::EMPTY);
406 bool GPARAACL::isAuthorizedAccess(GPARAM &aram, const ByteArray &aid,
407 const vector<ByteArray> &certHashes, const ByteArray &command) const
409 bool result = allGranted;
411 vector<ByteArray>::const_reverse_iterator item;
413 if (aram.isClosed() == true)
418 if (result == true) {
421 /* Step A, find with aid and cert hashes */
422 for (item = certHashes.rbegin();
423 result == false && item != certHashes.rend();
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());
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");
441 /* Step C, find with ALL_SE_APPS and hashes */
442 for (item = certHashes.rbegin();
443 result == false && item != certHashes.rend();
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());
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");
467 bool GPARAACL::isAuthorizedNFCAccess(GPARAM &aram, const ByteArray &aid,
468 const vector<ByteArray> &certHashes) const
470 bool result = allGranted;
472 vector<ByteArray>::const_reverse_iterator item;
474 if (aram.isClosed() == true)
479 if (result == true) {
482 /* Step A, find with aid and cert hashes */
483 for (item = certHashes.rbegin();
484 result == false && item != certHashes.rend();
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());
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");
502 /* Step C, find with ALL_SE_APPS and hashes */
503 for (item = certHashes.rbegin();
504 result == false && item != certHashes.rend();
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());
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");
527 } /* namespace smartcard_service_api */