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.
20 #include "NumberStream.h"
21 #include "SimpleTLV.h"
22 #include "ISO7816BERTLV.h"
23 #include "AccessCondition.h"
26 #define EXTERN_API __attribute__((visibility("default")))
29 namespace smartcard_service_api
31 static unsigned char aid_aram[] = { 0xA0, 0x00, 0x00, 0x01, 0x51, 0x41, 0x43, 0x4C, 0x00 };
32 static ByteArray AID_ARAM(ARRAY_AND_SIZE(aid_aram));
34 #define GET_DATA_ALL 0
35 #define GET_DATA_SPECIFIC 1
36 #define GET_DATA_REFRESH_TAG 2
37 #define GET_DATA_NEXT 3
39 #define ARAM_TAG_ALL_AR 0x0000FF40
40 #define ARAM_TAG_AR 0x0000FF50
41 #define ARAM_TAG_REFRESH 0x0000DF20
43 #define DO_TAG_AID_REF 0x0000004F
44 #define DO_TAG_AID_REF_DEFAULT 0x000000C0
45 #define DO_TAG_HASH_REF 0x000000C1
46 #define DO_TAG_APDU_AR 0x000000D0
47 #define DO_TAG_NFC_AR 0x000000D1
48 #define DO_TAG_REF 0x000000E1
49 #define DO_TAG_REF_AR 0x000000E2
50 #define DO_TAG_AR 0x000000E3
52 GPARAACL::GPARAACL() : AccessControlList()
60 static ByteArray getAID(SimpleTLV &tlv)
66 if (tlv.decodeTLV() == true) {
67 switch (tlv.getTag()) {
70 result = tlv.getValue();
72 result = AccessControlList::ALL_SE_APPS;
76 case DO_TAG_AID_REF_DEFAULT :
77 result = AccessControlList::DEFAULT_SE_APP;
81 _ERR("decodeTLV failed, %s", tlv.toString().c_str());
85 _ERR("decodeTLV failed, %s", tlv.toString().c_str());
93 static ByteArray getHash(SimpleTLV &tlv)
99 if (tlv.decodeTLV() == true &&
100 tlv.getTag() == DO_TAG_HASH_REF) {
101 if (tlv.size() > 0) {
102 result = tlv.getValue();
104 result = AccessControlList::ALL_DEVICE_APPS;
107 _ERR("decodeTLV failed, %s", tlv.toString().c_str());
115 static int parseRefDO(SimpleTLV &tlv, ByteArray &aid, ByteArray &hash)
117 int result = SCARD_ERROR_OK;
121 if (tlv.decodeTLV() == true && tlv.getTag() == DO_TAG_REF) {
122 tlv.enterToValueTLV();
125 tlv.returnToParentTLV();
127 _DBG("aid : %s, hash : %s", aid.toString().c_str(), hash.toString().c_str());
129 _ERR("unknown tag : %s", tlv.toString().c_str());
130 result = SCARD_ERROR_ILLEGAL_PARAM;
138 static int parseARDO(SimpleTLV &tlv, vector<ByteArray> &apduRule,
141 int result = SCARD_ERROR_OK;
145 if (tlv.decodeTLV() == true && tlv.getTag() == DO_TAG_AR) {
146 tlv.enterToValueTLV();
147 while (tlv.decodeTLV() == true) {
148 int length = tlv.size();
150 switch (tlv.getTag()) {
151 case DO_TAG_APDU_AR :
156 for (i = 0; i < length; i += 8) {
157 temp.assign(tlv.getValue().getBuffer(i), 8);
158 _DBG("apdu rule[%d] : %s", temp.size(), temp.toString().c_str());
159 apduRule.push_back(temp);
161 } else if (length == 1){
162 _DBG("apdu rule : %s", tlv.getValue().toString().c_str());
163 apduRule.push_back(tlv.getValue());
165 _ERR("invalid rule, %s", tlv.toString().c_str());
170 nfcRule = tlv.getValue();
171 _DBG("nfc rule : %s", tlv.getValue().toString().c_str());
178 tlv.returnToParentTLV();
180 result = SCARD_ERROR_ILLEGAL_PARAM;
188 void GPARAACL::addCondition(const ByteArray &aid, const ByteArray &hash,
189 const vector<ByteArray> &apduRule, const ByteArray &nfcRule)
191 AccessCondition &condition = getAccessCondition(aid);
195 condition.addAccessRule(hash);
197 if (apduRule.size() > 0) {
198 if (apduRule.size() == 1 &&
199 apduRule[0].size() == 1) {
200 /* apdu grant/deny */
201 if (apduRule[0][0] == 1) {
202 condition.setAPDUAccessRule(hash, true);
204 condition.setAPDUAccessRule(hash, false);
209 for (i = 0; i < apduRule.size(); i++) {
210 condition.addAPDUAccessRule(hash, apduRule[i]);
215 if (nfcRule.size() == 1) {
216 if (nfcRule[0] == 1) {
217 condition.setNFCAccessRule(hash, true);
219 condition.setNFCAccessRule(hash, false);
226 int GPARAACL::updateRule(const ByteArray &data)
228 int result = SCARD_ERROR_OK;
233 while (tlv.decodeTLV() == true) {
234 if (tlv.getTag() == DO_TAG_REF_AR) {
235 ByteArray aid, hash, nfcRule;
236 vector<ByteArray> apduRule;
238 tlv.enterToValueTLV();
239 result = parseRefDO(tlv, aid, hash);
241 if (result >= SCARD_ERROR_OK) {
242 result = parseARDO(tlv, apduRule, nfcRule);
244 tlv.returnToParentTLV();
246 addCondition(aid, hash, apduRule, nfcRule);
248 _ERR("unknown tag, [%x]", tlv.getTag());
249 result = SCARD_ERROR_ILLEGAL_PARAM;
259 int GPARAACL::loadACL(GPARAM &aram)
261 int result = SCARD_ERROR_OK;
262 ByteArray refreshTag, response;
266 if (aram.isClosed() == true) {
267 return SCARD_ERROR_ILLEGAL_STATE;
270 /* get refresh tag */
271 result = aram.getDataRefreshTag(refreshTag);
272 if (result >= SCARD_ERROR_OK) {
273 /* check refresh tag */
274 if (this->refreshTag.isEmpty() == true ||
275 this->refreshTag != refreshTag) {
276 result = aram.getDataAll(response);
277 if (result >= SCARD_ERROR_OK) {
278 result = updateRule(response);
280 /* update refresh tag */
281 this->refreshTag = refreshTag;
283 _ERR("getDataAll failed, [%x]", result);
288 _INFO("access rules are not changed. skip update");
291 _ERR("transmitSync failed, %x", result);
299 int GPARAACL::loadACL(Channel *channel)
301 int result = SCARD_ERROR_OK;
305 if (channel == NULL) {
306 return SCARD_ERROR_ILLEGAL_PARAM;
309 GPARAM aram(channel);
311 result = aram.select();
312 if (result >= SCARD_ERROR_OK) {
313 result = loadACL(aram);
315 _ERR("select failed, [%x]", result);
323 static bool _isAuthorizedAccess(const ByteArray &data, const ByteArray &command)
325 vector<ByteArray> apduRule;
330 if (parseARDO(tlv, apduRule, nfcRule) >= SCARD_ERROR_OK) {
331 if (apduRule.size() > 0) {
332 if (apduRule.size() > 1 ||
333 apduRule[0].size() != 1) {
334 if (command.size() > 0) {
335 /* TODO : check apdu rule */
337 /* check hash only */
341 result = (apduRule[0][0] == 1 ? true : false);
344 _ERR("unknown data : %s", tlv.toString().c_str());
347 _ERR("parseARDO failed : %s", tlv.toString().c_str());
353 static bool _isAuthorizedNFCAccess(const ByteArray &data)
355 vector<ByteArray> apduRule;
360 if (parseARDO(tlv, apduRule, nfcRule) >= SCARD_ERROR_OK) {
361 if (nfcRule.size() == 1) {
362 result = (nfcRule[0] == 1 ? true : false);
364 _ERR("unknown data : %s", nfcRule.toString().c_str());
367 _ERR("parseARDO failed : %s", tlv.toString().c_str());
373 bool GPARAACL::isAuthorizedAccess(GPARAM &aram, const ByteArray &aid,
374 const ByteArray &certHash) const
376 vector<ByteArray> hashes;
378 hashes.push_back(certHash);
380 return isAuthorizedAccess(aram, aid, hashes, ByteArray::EMPTY);
383 bool GPARAACL::isAuthorizedAccess(GPARAM &aram,
384 const unsigned char *aidBuffer,
385 unsigned int aidLength,
386 const unsigned char *certHashBuffer,
387 unsigned int certHashLength) const
389 ByteArray aid(aidBuffer, aidLength);
390 ByteArray hash(certHashBuffer, certHashLength);
392 return isAuthorizedAccess(aram, aid, hash);
395 bool GPARAACL::isAuthorizedAccess(GPARAM &aram, const ByteArray &aid,
396 const vector<ByteArray> &certHashes) const
398 return isAuthorizedAccess(aram, aid, certHashes, ByteArray::EMPTY);
401 bool GPARAACL::isAuthorizedAccess(GPARAM &aram, const ByteArray &aid,
402 const vector<ByteArray> &certHashes, const ByteArray &command) const
404 bool result = allGranted;
406 vector<ByteArray>::const_reverse_iterator item;
408 if (aram.isClosed() == true)
413 if (result == true) {
416 /* Step A, find with aid and cert hashes */
417 for (item = certHashes.rbegin();
418 result == false && item != certHashes.rend();
420 if (aram.getDataSpecific(aid, *item, data)
421 >= SCARD_ERROR_OK && data.size() > 0) {
422 result = _isAuthorizedAccess(data, command);
423 _INFO("rule found (%s): [%s:%s]", result ? "accept" : "deny", aid.toString().c_str(), (*item).toString().c_str());
428 /* Step B, find with aid and ALL_DEVICES_APPS */
429 if (aram.getDataSpecific(aid, ByteArray::EMPTY, data)
430 >= SCARD_ERROR_OK && data.size() > 0) {
431 result = _isAuthorizedAccess(data, command);
432 _INFO("rule found (%s): [%s:%s]", result ? "accept" : "deny", aid.toString().c_str(), "All device applications");
436 /* Step C, find with ALL_SE_APPS and hashes */
437 for (item = certHashes.rbegin();
438 result == false && item != certHashes.rend();
440 if (aram.getDataSpecific(ByteArray::EMPTY, *item, data)
441 >= SCARD_ERROR_OK && data.size() > 0) {
442 result = _isAuthorizedAccess(data, command);
443 _INFO("rule found (%s): [%s:%s]", result ? "accept" : "deny", "All SE Applications", (*item).toString().c_str());
448 /* Step D, find with ALL_SE_APPS and ALL_DEVICES_APPS */
449 if (aram.getDataSpecific(ByteArray::EMPTY, ByteArray::EMPTY, data)
450 >= SCARD_ERROR_OK && data.size() > 0) {
451 result = _isAuthorizedAccess(data, command);
452 _INFO("rule found (%s): [%s:%s]", result ? "accept" : "deny", "All SE Applications", "All device applications");
462 bool GPARAACL::isAuthorizedNFCAccess(GPARAM &aram, const ByteArray &aid,
463 const vector<ByteArray> &certHashes) const
465 bool result = allGranted;
467 vector<ByteArray>::const_reverse_iterator item;
469 if (aram.isClosed() == true)
474 if (result == true) {
477 /* Step A, find with aid and cert hashes */
478 for (item = certHashes.rbegin();
479 result == false && item != certHashes.rend();
481 if (aram.getDataSpecific(aid, *item, data)
482 >= SCARD_ERROR_OK && data.size() > 0) {
483 result = _isAuthorizedNFCAccess(data);
484 _INFO("rule found (%s): [%s:%s]", result ? "accept" : "deny", aid.toString().c_str(), (*item).toString().c_str());
489 /* Step B, find with aid and ALL_DEVICES_APPS */
490 if (aram.getDataSpecific(aid, ByteArray::EMPTY, data)
491 >= SCARD_ERROR_OK && data.size() > 0) {
492 result = _isAuthorizedNFCAccess(data);
493 _INFO("rule found (%s): [%s:%s]", result ? "accept" : "deny", aid.toString().c_str(), "All device applications");
497 /* Step C, find with ALL_SE_APPS and hashes */
498 for (item = certHashes.rbegin();
499 result == false && item != certHashes.rend();
501 if (aram.getDataSpecific(ByteArray::EMPTY, *item, data)
502 >= SCARD_ERROR_OK && data.size() > 0) {
503 result = _isAuthorizedNFCAccess(data);
504 _INFO("rule found (%s): [%s:%s]", result ? "accept" : "deny", "All SE Applications", (*item).toString().c_str());
509 /* Step D, find with ALL_SE_APPS and ALL_DEVICES_APPS */
510 if (aram.getDataSpecific(ByteArray::EMPTY, ByteArray::EMPTY, data)
511 >= SCARD_ERROR_OK && data.size() > 0) {
512 result = _isAuthorizedNFCAccess(data);
513 _INFO("rule found (%s): [%s:%s]", result ? "accept" : "deny", "All SE Applications", "All device applications");
522 } /* namespace smartcard_service_api */