From b356b089fcb7b20050c5e27fdf433de220f53b24 Mon Sep 17 00:00:00 2001 From: Wonkyu Kwon Date: Wed, 24 Jul 2013 17:26:34 +0900 Subject: [PATCH] Implement Access Control Enforcer using ARA Change-Id: Ieb085b3125f682a7e6c6292c9074a28dd75dc7a6 --- common/APDUHelper.cpp | 3 +- common/AccessCondition.cpp | 287 +++++++---------- common/AccessControlList.cpp | 202 +++++++++--- common/ByteArray.cpp | 16 + common/CMakeLists.txt | 1 - common/EFDIR.cpp | 33 +- common/FileObject.cpp | 18 +- common/GPACE.cpp | 122 +++++++ common/GPARAACL.cpp | 527 +++++++++++++++++++++++++++++++ common/GPARAM.cpp | 278 ++++++++++++++++ common/GPARFACL.cpp | 416 ++++++++++++++++++++++++ common/GPSEACL.cpp | 341 -------------------- common/ISO7816BERTLV.cpp | 14 +- common/PKCS15.cpp | 68 ++-- common/PKCS15DODF.cpp | 11 +- common/PKCS15ODF.cpp | 8 +- common/SignatureHelper.cpp | 4 - common/include/AccessCondition.h | 71 +++-- common/include/AccessControlList.h | 27 +- common/include/ByteArray.h | 4 +- common/include/EFDIR.h | 4 +- common/include/FileObject.h | 16 +- common/include/GPACE.h | 59 ++++ common/include/GPARAACL.h | 69 ++++ common/include/GPARAM.h | 58 ++++ common/include/{GPSEACL.h => GPARFACL.h} | 39 +-- common/include/PKCS15.h | 6 +- common/include/PKCS15DODF.h | 3 +- common/include/PKCS15ODF.h | 2 +- server/ServerChannel.cpp | 8 +- server/ServerReader.cpp | 4 +- server/ServerResource.cpp | 142 ++++++--- server/ServerSession.cpp | 2 +- server/include/ServerResource.h | 5 + 34 files changed, 2109 insertions(+), 759 deletions(-) create mode 100644 common/GPACE.cpp create mode 100644 common/GPARAACL.cpp create mode 100644 common/GPARAM.cpp create mode 100644 common/GPARFACL.cpp delete mode 100644 common/GPSEACL.cpp create mode 100644 common/include/GPACE.h create mode 100644 common/include/GPARAACL.h create mode 100644 common/include/GPARAM.h rename common/include/{GPSEACL.h => GPARFACL.h} (55%) diff --git a/common/APDUHelper.cpp b/common/APDUHelper.cpp index f37af2c..f864111 100644 --- a/common/APDUHelper.cpp +++ b/common/APDUHelper.cpp @@ -21,6 +21,7 @@ /* SLP library header */ /* local header */ +#include "smartcard-types.h" #include "Debug.h" #include "APDUHelper.h" @@ -44,7 +45,7 @@ namespace smartcard_service_api bool ResponseHelper::setResponse(const ByteArray &response) { bool result = false; - status = 0; + status = SCARD_ERROR_UNKNOWN; dataField.releaseBuffer(); this->response = response; diff --git a/common/AccessCondition.cpp b/common/AccessCondition.cpp index 964b4cf..865e5c0 100644 --- a/common/AccessCondition.cpp +++ b/common/AccessCondition.cpp @@ -22,254 +22,203 @@ /* local header */ #include "Debug.h" #include "SimpleTLV.h" +#include "AccessControlList.h" #include "AccessCondition.h" namespace smartcard_service_api { - void APDUAccessRule::loadAPDUAccessRule(const ByteArray &data) + void AccessRule::addAPDUAccessRule(const ByteArray &apdu, + const ByteArray &mask) { - SimpleTLV tlv(data); + pair item(apdu, mask); - if (tlv.decodeTLV() == true) - { - switch (tlv.getTag()) - { - case 0xA0 : /* CHOICE 0 : APDUPermission */ - permission = SimpleTLV::getBoolean(tlv.getValue()); - break; - - case 0xA1 : /* CHOICE 1 : APDUFilters */ - tlv.enterToValueTLV(); - while (tlv.decodeTLV() == true) - { - if (tlv.getTag() == 0x04) /* OCTET STRING */ - { - ByteArray apdu, mask, value; - - value = tlv.getValue(); - - _DBG("APDU rule : %s", value.toString()); - - if (value.getLength() == 8) /* apdu 4 bytes + mask 4 bytes */ - { - apdu.setBuffer(value.getBuffer(), 4); - mask.setBuffer(value.getBuffer(4), 4); - - pair newItem(apdu, mask); - - mapApduFilters.insert(newItem); - } - else - { - _ERR("Invalid APDU rule : %s", value.toString()); - } - } - else - { - _ERR("Unknown tag : 0x%02X", tlv.getTag()); - } - } - tlv.returnToParentTLV(); - break; - - default : - _ERR("Unknown tag : 0x%02X", tlv.getTag()); - break; - } - } + listFilters.push_back(item); } - bool APDUAccessRule::isAuthorizedAccess(const ByteArray &command) + bool AccessRule::isAuthorizedAPDUAccess(const ByteArray &command) { bool result = false; - if (mapApduFilters.size() > 0) + if (command.getLength() < 4) /* apdu header size */ + return false; + + if (listFilters.size() > 0) { - /* TODO : search command and check validity */ + unsigned int cmd, mask, rule; + vector >::iterator item; + + cmd = *(unsigned int *)command.getBuffer(); + for (item = listFilters.begin(); item != listFilters.end(); item++) + { + mask = *(unsigned int *)item->second.getBuffer(); + rule = *(unsigned int *)item->first.getBuffer(); + + if ((cmd & mask) == rule) + { + result = true; + break; + } + } } else { /* no filter entry. if permission is true, all access will be granted, if not, all access will be denied */ - result = permission; + result = apduRule; } return result; } - void APDUAccessRule::printAPDUAccessRules() + void AccessRule::printAccessRules() { - _DBG(" +-- APDU Access Rule"); - - if (mapApduFilters.size() > 0) + if (listFilters.size() > 0) { - map::iterator iterMap; + vector >::iterator item; - for (iterMap = mapApduFilters.begin(); iterMap != mapApduFilters.end(); iterMap++) + _DBG(" +---- Granted APDUs"); + + for (item = listFilters.begin(); item != listFilters.end(); item++) { - _DBG(" +--- APDU : %s, Mask : %s", ((ByteArray)(iterMap->first)).toString(), iterMap->second.toString()); + _DBG(" +----- APDU : %s, Mask : %s", item->first.toString(), item->second.toString()); } } else { - _DBG(" +--- permission : %s", permission ? "granted all" : "denied all"); + _DBG(" +---- APDU Access ALLOW : %s", apduRule ? "ALWAYS" : "NEVER"); } + + _DBG(" +---- NFC Access ALLOW : %s", nfcRule ? "ALWAYS" : "NEVER"); } - void NFCAccessRule::loadNFCAccessRule(const ByteArray &data) + bool AccessRule::isAuthorizedNFCAccess(void) { - permission = SimpleTLV::getBoolean(data); + return nfcRule; } - bool NFCAccessRule::isAuthorizedAccess(void) + AccessRule *AccessCondition::getAccessRule(const ByteArray &certHash) { - bool result = false; + AccessRule *result = NULL; + map::iterator item; - result = permission; + item = mapRules.find(certHash); + if (item != mapRules.end()) { + result = &item->second; + } return result; } - void NFCAccessRule::printNFCAccessRules() + void AccessCondition::addAccessRule(const ByteArray &hash) { - _DBG(" +-- NFC Access Rule"); - _DBG(" +--- permission : %s", permission ? "granted all" : "denied all"); + AccessRule rule; + + pair item(hash, rule); + + mapRules.insert(item); } - void AccessCondition::loadAccessCondition(ByteArray &aid, ByteArray &data) + bool AccessCondition::isAuthorizedAccess(const ByteArray &certHash) { - if (data.getLength() > 0) - { - SimpleTLV tlv(data); - - while (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE */ - { - if (tlv.getLength() > 0) - { - /* access granted for specific applications */ - tlv.enterToValueTLV(); - if (tlv.decodeTLV()) - { - switch (tlv.getTag()) - { - case 0x04 : /* OCTET STRING : CertHash */ - _DBG("aid : %s, hash : %s", aid.toString(), tlv.getValue().toString()); - - hashes.push_back(tlv.getValue()); - break; - - case 0xA0 : /* CHOICE 0 : AccessRules */ - tlv.enterToValueTLV(); - if (tlv.decodeTLV()) - { - switch (tlv.getTag()) - { - case 0xA0 : /* CHOICE 0 : APDUAccessRule */ - apduRule.loadAPDUAccessRule(tlv.getValue()); - break; - - case 0xA1 : /* CHOICE 1 : NFCAccessRule */ - nfcRule.loadNFCAccessRule(tlv.getValue()); - break; - - default : - _ERR("Unknown tag : 0x%02X", tlv.getTag()); - break; - } - } - else - { - _ERR("tlv.decodeTLV failed"); - } - tlv.returnToParentTLV(); - break; - - default : - _ERR("Unknown tag : 0x%02X", tlv.getTag()); - break; - } - } - else - { - _ERR("tlv.decodeTLV failed"); - } - tlv.returnToParentTLV(); - } - else - { - _INFO("access granted for all applications, aid : %s", aid.toString()); + bool result = false; + map::iterator item; - permission = true; - break; - } - } + item = mapRules.find(certHash); + if (item != mapRules.end()) + { + result = true; } else { - _INFO("access denied for all applications, aid : %s", aid.toString()); - - permission = false; + /* TODO */ + result = permission; } + + return result; } - bool AccessCondition::isAuthorizedAccess(ByteArray &certHash) + void AccessCondition::printAccessConditions() { - bool result = false; + _DBG(" +-- Access Condition"); - if (hashes.size() > 0) + if (mapRules.size() > 0) { - size_t i; + map::iterator item; - for (i = 0; i < hashes.size(); i++) + for (item = mapRules.begin(); item != mapRules.end(); item++) { - if (certHash == hashes[i]) - { - result = true; - break; - } + ByteArray temp = item->first; + + _DBG(" +--- hash : %s", (temp == AccessControlList::ALL_DEVICE_APPS) ? "All device applications" : temp.toString()); + item->second.printAccessRules(); } } else { - result = permission; + _DBG(" +--- permission : %s", permission ? "granted all" : "denied all"); } + } - return result; + void AccessCondition::setAPDUAccessRule(const ByteArray &certHash, + bool rule) + { + AccessRule *access = getAccessRule(certHash); + + if (access != NULL) { + access->setAPDUAccessRule(rule); + } } - bool AccessCondition::isAuthorizedAPDUAccess(ByteArray &command) + void AccessCondition::addAPDUAccessRule(const ByteArray &certHash, + const ByteArray &apdu, const ByteArray &mask) { - bool result = false; + AccessRule *access = getAccessRule(certHash); - result = apduRule.isAuthorizedAccess(command); + if (access != NULL) { + access->addAPDUAccessRule(apdu, mask); + } + } - return result; + void AccessCondition::addAPDUAccessRule(const ByteArray &certHash, + const ByteArray &rule) + { + if (rule.getLength() != 8) + return; + + addAPDUAccessRule(certHash, rule.sub(0, 4), rule.sub(4, 4)); + } + + void AccessCondition::setNFCAccessRule(const ByteArray &certHash, + bool rule) + { + AccessRule *access = getAccessRule(certHash); + + if (access != NULL) { + access->setNFCAccessRule(rule); + } } - bool AccessCondition::isAuthorizedNFCAccess() + bool AccessCondition::isAuthorizedAPDUAccess(const ByteArray &certHash, + const ByteArray &command) { bool result = false; + AccessRule *access = getAccessRule(certHash); - result = nfcRule.isAuthorizedAccess(); + if (access != NULL) { + result = access->isAuthorizedAPDUAccess(command); + } return result; } - void AccessCondition::printAccessConditions() + bool AccessCondition::isAuthorizedNFCAccess(const ByteArray &certHash) { - _DBG(" +-- Access Condition"); - - if (hashes.size() > 0) - { - size_t i; + bool result = false; + AccessRule *access = getAccessRule(certHash); - for (i = 0; i < hashes.size(); i++) - { - _DBG(" +--- hash : %s", hashes[i].toString()); - } - } - else - { - _DBG(" +--- permission : %s", permission ? "granted all" : "denied all"); + if (access != NULL) { + result = access->isAuthorizedNFCAccess(); } + + return result; } } /* namespace smartcard_service_api */ diff --git a/common/AccessControlList.cpp b/common/AccessControlList.cpp index 47c4982..3bc9f53 100644 --- a/common/AccessControlList.cpp +++ b/common/AccessControlList.cpp @@ -23,19 +23,19 @@ #include "Debug.h" #include "AccessControlList.h" #include "PKCS15.h" -#include "AccessCondition.h" namespace smartcard_service_api { - const unsigned char aid_all[] = { 0x00, 0x00 }; - const unsigned char aid_default[] = { 0x00, 0x01 }; + const unsigned char all_se_apps[] = { 0x00, 0x00 }; + const unsigned char default_se_app[] = { 0x00, 0x01 }; + const unsigned char all_device_apps[] = { 0x00, 0x02 }; - ByteArray AccessControlList::AID_ALL(ARRAY_AND_SIZE(aid_all)); - ByteArray AccessControlList::AID_DEFAULT(ARRAY_AND_SIZE(aid_default)); + ByteArray AccessControlList::ALL_SE_APPS(ARRAY_AND_SIZE(all_se_apps)); + ByteArray AccessControlList::DEFAULT_SE_APP(ARRAY_AND_SIZE(default_se_app)); + ByteArray AccessControlList::ALL_DEVICE_APPS(ARRAY_AND_SIZE(all_device_apps)); - AccessControlList::AccessControlList() + AccessControlList::AccessControlList() : allGranted(false) { - allGranted = false; } AccessControlList::~AccessControlList() @@ -49,78 +49,190 @@ namespace smartcard_service_api allGranted = false; } - bool AccessControlList::isAuthorizedAccess(ByteArray aid, ByteArray certHash, bool update) + AccessCondition &AccessControlList::getAccessCondition(const ByteArray &aid) { - bool result = allGranted; - map::iterator iterMap; + map::iterator item; - if (result == false) + item = mapConditions.find(aid); + if (item == mapConditions.end()) { - _DBG("aid : %s", aid.toString()); - _DBG("hash : %s", certHash.toString()); + AccessCondition condition; + pair temp(aid, condition); + mapConditions.insert(temp); - /* null aid means default applet */ - if (aid.isEmpty() == true) - { - aid = AID_DEFAULT; - } + item = mapConditions.find(aid); + } - /* first.. find hashes matched with aid */ - if ((iterMap = mapConditions.find(aid)) != mapConditions.end()) - { - result = iterMap->second.isAuthorizedAccess(certHash); - } - /* finally.. find hashes in 'all' list */ - else if ((iterMap = mapConditions.find(AID_ALL)) != mapConditions.end()) - { - result = iterMap->second.isAuthorizedAccess(certHash); - } + return item->second; + } + + AccessRule *AccessControlList::findAccessRule(const ByteArray &aid, + const ByteArray &hash) + { + AccessRule *result = NULL; + map::iterator item; + + item = mapConditions.find(aid); + if (item != mapConditions.end()) { + result = item->second.getAccessRule(hash); } return result; } - bool AccessControlList::isAuthorizedAccess(ByteArray aid, ByteArray certHash) + bool AccessControlList::isAuthorizedAccess(ByteArray &aid, + ByteArray &certHash) + { + vector hashes; + + hashes.push_back(certHash); + + return isAuthorizedAccess(aid, hashes); + } + + bool AccessControlList::isAuthorizedAccess(unsigned char *aidBuffer, + unsigned int aidLength, unsigned char *certHashBuffer, + unsigned int certHashLength) { - return isAuthorizedAccess(aid, certHash, true); + ByteArray aid(aidBuffer, aidLength); + ByteArray certHash(certHashBuffer, certHashLength); + + return isAuthorizedAccess(aid, certHash); } - bool AccessControlList::isAuthorizedAccess(unsigned char *aidBuffer, unsigned int aidLength, unsigned char *certHashBuffer, unsigned int certHashLength) + bool AccessControlList::isAuthorizedAccess(ByteArray &aid, + vector &certHashes) { - return isAuthorizedAccess(ByteArray(aidBuffer, aidLength), ByteArray(certHashBuffer, certHashLength), true); + return isAuthorizedAccess(aid, certHashes, ByteArray::EMPTY); } - bool AccessControlList::isAuthorizedAccess(ByteArray aid, vector &certHashes) + bool AccessControlList::isAuthorizedAccess(ByteArray &aid, + vector &certHashes, ByteArray &command) { - bool result; - size_t i; + bool result = allGranted; + vector::reverse_iterator item; + AccessRule *rule = NULL; - result = allGranted; + if (result == true) { + goto END; + } - if (result == false) - { - for (i = 0; result == false && i < certHashes.size(); i++) - { - result = isAuthorizedAccess(aid, certHashes[i], false); + /* Step A, find with aid and cert hashes */ + for (item = certHashes.rbegin(); item != certHashes.rend(); item++) { + rule = findAccessRule(aid, *item); + if (rule != NULL) { + if (command.isEmpty()) { + result = rule->isAuthorizedAccess(); + } else { + result = rule->isAuthorizedAPDUAccess(command); + } + _INFO("rule found (%s): [%s:%s]", result ? "accept" : "deny", aid.toString(), (*item).toString()); + goto END; + } + } + + /* Step B, find with aid and ALL_DEVICES_APPS */ + rule = findAccessRule(aid, ALL_DEVICE_APPS); + if (rule != NULL) { + if (command.isEmpty()) { + result = rule->isAuthorizedAccess(); + } else { + result = rule->isAuthorizedAPDUAccess(command); + } + _INFO("rule found (%s): [%s:%s]", result ? "accept" : "deny", aid.toString(), ALL_DEVICE_APPS.toString()); + goto END; + } + + /* Step C, find with ALL_SE_APPS and hashes */ + for (item = certHashes.rbegin(); item != certHashes.rend(); item++) { + rule = findAccessRule(ALL_SE_APPS, *item); + if (rule != NULL) { + if (command.isEmpty()) { + result = rule->isAuthorizedAccess(); + } else { + result = rule->isAuthorizedAPDUAccess(command); + } + _INFO("rule found (%s): [%s:%s]", result ? "accept" : "deny", "All SE Applications", (*item).toString()); + goto END; + } + } + + /* Step D, find with ALL_SE_APPS and ALL_DEVICES_APPS */ + rule = findAccessRule(ALL_SE_APPS, ALL_DEVICE_APPS); + if (rule != NULL) { + if (command.isEmpty()) { + result = rule->isAuthorizedAccess(); + } else { + result = rule->isAuthorizedAPDUAccess(command); + } + _INFO("rule found (%s): [%s:%s]", result ? "accept" : "deny", "All SE Applications", "All device applications"); + } + +END : + return result; + } + + bool AccessControlList::isAuthorizedNFCAccess(ByteArray &aid, + vector &certHashes) + { + bool result = allGranted; + vector::reverse_iterator item; + AccessRule *rule = NULL; + + if (result == true) { + goto END; + } + + /* Step A, find with aid and cert hashes */ + for (item = certHashes.rbegin(); item != certHashes.rend(); item++) { + rule = findAccessRule(aid, *item); + if (rule != NULL) { + result = rule->isAuthorizedNFCAccess(); + _INFO("rule found (%s): [%s:%s]", result ? "accept" : "deny", aid.toString(), (*item).toString()); + goto END; + } + } + + /* Step B, find with aid and ALL_DEVICES_APPS */ + rule = findAccessRule(aid, ALL_DEVICE_APPS); + if (rule != NULL) { + result = rule->isAuthorizedNFCAccess(); + _INFO("rule found (%s): [%s:%s]", result ? "accept" : "deny", aid.toString(), "All device applications"); + goto END; + } + + /* Step C, find with ALL_SE_APPS and hashes */ + for (item = certHashes.rbegin(); item != certHashes.rend(); item++) { + rule = findAccessRule(ALL_SE_APPS, *item); + if (rule != NULL) { + result = rule->isAuthorizedNFCAccess(); + _INFO("rule found (%s): [%s:%s]", result ? "accept" : "deny", "All SE Applications", (*item).toString()); + goto END; } } + /* Step D, find with ALL_SE_APPS and ALL_DEVICES_APPS */ + rule = findAccessRule(ALL_SE_APPS, ALL_DEVICE_APPS); + if (rule != NULL) { + result = rule->isAuthorizedNFCAccess(); + _INFO("rule found (%s): [%s:%s]", result ? "accept" : "deny", "All SE Applications", "All device applications"); + } + +END : return result; } void AccessControlList::printAccessControlList() { ByteArray temp; - - /* release map and vector */ map::iterator iterMap; - _DBG("================ Certification Hashes =================="); + _DBG("================ Access Control Rules =================="); for (iterMap = mapConditions.begin(); iterMap != mapConditions.end(); iterMap++) { temp = iterMap->first; - _DBG("+ aid : %s", (temp == AID_DEFAULT) ? "DEFAULT" : (temp == AID_ALL) ? "ALL" : temp.toString()); + _DBG("+ aid : %s", (temp == DEFAULT_SE_APP) ? "Default Application" : (temp == ALL_SE_APPS) ? "All SE Applications" : temp.toString()); iterMap->second.printAccessConditions(); } diff --git a/common/ByteArray.cpp b/common/ByteArray.cpp index d68e47b..c62c775 100644 --- a/common/ByteArray.cpp +++ b/common/ByteArray.cpp @@ -156,6 +156,22 @@ namespace smartcard_service_api return min_len; } + ByteArray ByteArray::sub(uint32_t offset, uint32_t size) const + { + ByteArray newArray; + + if (length == 0 || offset >= length || (offset + size) > length) + { + _DBG("length is zero"); + + return newArray; + } + + newArray.setBuffer(buffer + offset, size); + + return newArray; + } + void ByteArray::releaseBuffer() { if (buffer != NULL) diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index ddd165c..3e07a78 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -66,7 +66,6 @@ SET(EXPORT_HEADER include/TerminalInterface.h include/Terminal.h include/SignatureHelper.h - include/GPSEACL.h ) INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${LIB_NAME}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) diff --git a/common/EFDIR.cpp b/common/EFDIR.cpp index 32b9e55..26022ba 100644 --- a/common/EFDIR.cpp +++ b/common/EFDIR.cpp @@ -27,25 +27,15 @@ namespace smartcard_service_api { + static unsigned char path_efdir[] = { 0x2f, 0x00 }; + static ByteArray PATH_EFDIR(ARRAY_AND_SIZE(path_efdir)); + EFDIR::EFDIR(Channel *channel) : FileObject(channel) { - unsigned char path[] = { 0x2f, 0x00 }; - ByteArray dirPath(ARRAY_AND_SIZE(path)); - int ret; - - ret = select(dirPath, false); - if (ret >= SCARD_ERROR_OK) - { - _DBG("response : %s", selectResponse.toString()); - } - else - { - _ERR("EFDIR select failed, [%d]", ret); - } } - EFDIR::EFDIR(Channel *channel, ByteArray selectResponse) - : FileObject(channel, selectResponse) + EFDIR::EFDIR(Channel *channel, ByteArray selectResponse) : + FileObject(channel, selectResponse) { } @@ -53,6 +43,19 @@ namespace smartcard_service_api { } + int EFDIR::select() + { + int ret; + + ret = FileObject::select(PATH_EFDIR, false); + if (ret < SCARD_ERROR_OK) + { + _ERR("EFDIR select failed, [%d]", ret); + } + + return ret; + } + ByteArray EFDIR::parseRecord(Record &record, ByteArray &aid) { bool matched = false; diff --git a/common/FileObject.cpp b/common/FileObject.cpp index ce00b80..41c07ad 100644 --- a/common/FileObject.cpp +++ b/common/FileObject.cpp @@ -32,7 +32,7 @@ namespace smartcard_service_api opened = false; } - FileObject::FileObject(Channel *channel, ByteArray selectResponse) + FileObject::FileObject(Channel *channel, const ByteArray &selectResponse) : ProviderHelper(channel) { opened = false; @@ -50,7 +50,7 @@ namespace smartcard_service_api selectResponse.releaseBuffer(); } - bool FileObject::setSelectResponse(ByteArray response) + bool FileObject::setSelectResponse(const ByteArray &response) { bool result = false; @@ -78,13 +78,13 @@ namespace smartcard_service_api } else { - _ERR("invalid response : %s", response.toString()); + _ERR("invalid response"); } return result; } - int FileObject::_select(ByteArray command) + int FileObject::_select(const ByteArray &command) { int ret = ERROR_ILLEGAL_STATE; ByteArray result; @@ -121,7 +121,7 @@ namespace smartcard_service_api return ret; } - int FileObject::select(ByteArray aid) + int FileObject::select(const ByteArray &aid) { int ret = ERROR_ILLEGAL_STATE; ByteArray command; @@ -134,7 +134,7 @@ namespace smartcard_service_api return ret; } - int FileObject::select(ByteArray path, bool fromCurrentDF) + int FileObject::select(const ByteArray &path, bool fromCurrentDF) { int ret = ERROR_ILLEGAL_STATE; ByteArray command; @@ -232,12 +232,12 @@ namespace smartcard_service_api return ret; } - int FileObject::writeRecord(unsigned int sfi, Record record) + int FileObject::writeRecord(unsigned int sfi, const Record &record) { return 0; } - int FileObject::searchRecord(unsigned int sfi, ByteArray searchParam, vector &result) + int FileObject::searchRecord(unsigned int sfi, const ByteArray &searchParam, vector &result) { return 0; } @@ -277,7 +277,7 @@ namespace smartcard_service_api return ret; } - int FileObject::writeBinary(unsigned int sfi, ByteArray data, unsigned int offset, unsigned int length) + int FileObject::writeBinary(unsigned int sfi, const ByteArray &data, unsigned int offset, unsigned int length) { ByteArray command, response; APDUCommand apdu; diff --git a/common/GPACE.cpp b/common/GPACE.cpp new file mode 100644 index 0000000..5f4cec2 --- /dev/null +++ b/common/GPACE.cpp @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "GPACE.h" +#include "GPARAACL.h" +#include "GPARFACL.h" +#include "SessionHelper.h" +#include "ReaderHelper.h" + +#ifndef EXTERN_API +#define EXTERN_API __attribute__((visibility("default"))) +#endif + +namespace smartcard_service_api +{ + GPACE::GPACE() : AccessControlList(), acl(NULL) + { + } + + GPACE::~GPACE() + { + if (acl != NULL) { + delete acl; + } + } + + int GPACE::loadACL(Channel *channel) + { + int result = SCARD_ERROR_OK; + + _BEGIN(); + + if (channel == NULL) + { + return SCARD_ERROR_ILLEGAL_PARAM; + } + + if (acl == NULL) { + /* first, check ara-m */ + GPARAACL *araACL = new GPARAACL; + + result = araACL->loadACL(channel); + if (result < SCARD_ERROR_OK) { + _ERR("ARA not found"); + + delete araACL; + + if (true) { + _INFO("try to use ARF"); + /* second, check arf when channel is for SIM */ + GPARFACL *arfACL = new GPARFACL; + + result = arfACL->loadACL(channel); + if (result >= SCARD_ERROR_OK) { + acl = arfACL; + } else { + delete arfACL; + } + } + } else { + acl = araACL; + } + } else { + result = acl->loadACL(channel); + } + + _END(); + + return result; + } + + bool GPACE::isAuthorizedAccess(ByteArray &aid, + ByteArray &certHash) + { + return (acl != NULL) ? acl->isAuthorizedAccess(aid, certHash) : false; + } + + bool GPACE::isAuthorizedAccess(unsigned char *aidBuffer, + unsigned int aidLength, unsigned char *certHashBuffer, + unsigned int certHashLength) + { + return (acl != NULL) ? acl->isAuthorizedAccess(aidBuffer, aidLength, certHashBuffer, certHashLength) : false; + } + + bool GPACE::isAuthorizedAccess(ByteArray &aid, + vector &certHashes) + { + return (acl != NULL) ? acl->isAuthorizedAccess(aid, certHashes) : false; + } + + bool GPACE::isAuthorizedAccess(ByteArray &aid, + vector &certHashes, ByteArray &command) + { + return (acl != NULL) ? acl->isAuthorizedAccess(aid, certHashes, command) : false; + } + + bool GPACE::isAuthorizedNFCAccess(ByteArray &aid, + vector &certHashes) + { + return (acl != NULL) ? acl->isAuthorizedNFCAccess(aid, certHashes) : false; + } + +} /* namespace smartcard_service_api */ diff --git a/common/GPARAACL.cpp b/common/GPARAACL.cpp new file mode 100644 index 0000000..4a93c33 --- /dev/null +++ b/common/GPARAACL.cpp @@ -0,0 +1,527 @@ +/* + * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "GPARAACL.h" +#include "GPARAM.h" +#include "NumberStream.h" +#include "SimpleTLV.h" +#include "ISO7816BERTLV.h" +#include "AccessCondition.h" + +#ifndef EXTERN_API +#define EXTERN_API __attribute__((visibility("default"))) +#endif + +namespace smartcard_service_api +{ + static unsigned char aid_aram[] = { 0xA0, 0x00, 0x00, 0x01, 0x51, 0x41, 0x43, 0x4C, 0x00 }; + static ByteArray AID_ARAM(ARRAY_AND_SIZE(aid_aram)); + +#define GET_DATA_ALL 0 +#define GET_DATA_SPECIFIC 1 +#define GET_DATA_REFRESH_TAG 2 +#define GET_DATA_NEXT 3 + +#define ARAM_TAG_ALL_AR 0x0000FF40 +#define ARAM_TAG_AR 0x0000FF50 +#define ARAM_TAG_REFRESH 0x0000DF20 + +#define DO_TAG_AID_REF 0x0000004F +#define DO_TAG_AID_REF_DEFAULT 0x000000C0 +#define DO_TAG_HASH_REF 0x000000C1 +#define DO_TAG_APDU_AR 0x000000D0 +#define DO_TAG_NFC_AR 0x000000D1 +#define DO_TAG_REF 0x000000E1 +#define DO_TAG_REF_AR 0x000000E2 +#define DO_TAG_AR 0x000000E3 + + GPARAACL::GPARAACL() : AccessControlList() + { + } + + GPARAACL::~GPARAACL() + { + } + + static ByteArray getAID(SimpleTLV &tlv) + { + ByteArray result; + + _BEGIN(); + + if (tlv.decodeTLV() == true) { + switch (tlv.getTag()) { + case DO_TAG_AID_REF : + if (tlv.getLength() > 0) { + result = tlv.getValue(); + } else { + result = AccessControlList::ALL_SE_APPS; + } + break; + + case DO_TAG_AID_REF_DEFAULT : + result = AccessControlList::DEFAULT_SE_APP; + break; + + default : + _ERR("decodeTLV failed, %s", tlv.toString()); + break; + } + } else { + _ERR("decodeTLV failed, %s", tlv.toString()); + } + + _END(); + + return result; + } + + static ByteArray getHash(SimpleTLV &tlv) + { + ByteArray result; + + _BEGIN(); + + if (tlv.decodeTLV() == true && + tlv.getTag() == DO_TAG_HASH_REF) { + if (tlv.getLength() > 0) { + result = tlv.getValue(); + } else { + result = AccessControlList::ALL_DEVICE_APPS; + } + } else { + _ERR("decodeTLV failed, %s", tlv.toString()); + } + + _END(); + + return result; + } + + static int parseRefDO(SimpleTLV &tlv, ByteArray &aid, ByteArray &hash) + { + int result = SCARD_ERROR_OK; + + _BEGIN(); + + if (tlv.decodeTLV() == true && tlv.getTag() == DO_TAG_REF) { + tlv.enterToValueTLV(); + aid = getAID(tlv); + hash = getHash(tlv); + tlv.returnToParentTLV(); + + _DBG("aid : %s, hash : %s", aid.toString(), hash.toString()); + } else { + _ERR("unknown tag : %s", tlv.toString()); + result = SCARD_ERROR_ILLEGAL_PARAM; + } + + _END(); + + return result; + } + + static int parseARDO(SimpleTLV &tlv, vector &apduRule, + ByteArray &nfcRule) + { + int result = SCARD_ERROR_OK; + + _BEGIN(); + + if (tlv.decodeTLV() == true && tlv.getTag() == DO_TAG_AR) { + tlv.enterToValueTLV(); + while (tlv.decodeTLV() == true) { + int length = tlv.getLength(); + + switch (tlv.getTag()) { + case DO_TAG_APDU_AR : + if (length > 1) { + int i; + ByteArray temp; + + for (i = 0; i < length; i += 8) { + temp.setBuffer(tlv.getValue().getBuffer(i), 8); + _DBG("apdu rule[%d] : %s", temp.getLength(), temp.toString()); + apduRule.push_back(temp); + } + } else if (length == 1){ + _DBG("apdu rule : %s", tlv.getValue().toString()); + apduRule.push_back(tlv.getValue()); + } else { + _ERR("invalid rule, %s", tlv.toString()); + } + break; + + case DO_TAG_NFC_AR : + nfcRule = tlv.getValue(); + _DBG("nfc rule : %s", tlv.getValue().toString()); + break; + + default : + break; + } + } + tlv.returnToParentTLV(); + } else { + result = SCARD_ERROR_ILLEGAL_PARAM; + } + + _END(); + + return result; + } + + void GPARAACL::addCondition(const ByteArray &aid, const ByteArray &hash, + const vector &apduRule, const ByteArray &nfcRule) + { + AccessCondition &condition = getAccessCondition(aid); + + _BEGIN(); + + condition.addAccessRule(hash); + + if (apduRule.size() > 0) { + if (apduRule.size() == 1 && + apduRule[0].getLength() == 1) { + /* apdu grant/deny */ + if (apduRule[0][0] == 1) { + condition.setAPDUAccessRule(hash, true); + } else { + condition.setAPDUAccessRule(hash, false); + } + } else { + size_t i; + + for (i = 0; i < apduRule.size(); i++) { + condition.addAPDUAccessRule(hash, apduRule[i]); + } + } + } + + if (nfcRule.getLength() == 1) { + if (nfcRule[0] == 1) { + condition.setNFCAccessRule(hash, true); + } else { + condition.setNFCAccessRule(hash, false); + } + } + + _END(); + } + + int GPARAACL::updateRule(ByteArray &data) + { + int result = SCARD_ERROR_OK; + SimpleTLV tlv(data); + + _BEGIN(); + + while (tlv.decodeTLV() == true) { + if (tlv.getTag() == DO_TAG_REF_AR) { + ByteArray aid, hash, nfcRule; + vector apduRule; + + tlv.enterToValueTLV(); + result = parseRefDO(tlv, aid, hash); + + if (result >= SCARD_ERROR_OK) { + result = parseARDO(tlv, apduRule, nfcRule); + } + tlv.returnToParentTLV(); + + addCondition(aid, hash, apduRule, nfcRule); + } else { + _ERR("unknown tag, [%x]", tlv.getTag()); + result = SCARD_ERROR_ILLEGAL_PARAM; + break; + } + } + + _END(); + + return result; + } + + int GPARAACL::loadACL(GPARAM &aram) + { + int result = SCARD_ERROR_OK; + ByteArray refreshTag, response; + + _BEGIN(); + + if (aram.isClosed() == true) { + return SCARD_ERROR_ILLEGAL_STATE; + } + + /* get refresh tag */ + result = aram.getDataRefreshTag(refreshTag); + if (result >= SCARD_ERROR_OK) { + /* check refresh tag */ + if (this->refreshTag.isEmpty() == true || + this->refreshTag != refreshTag) { + result = aram.getDataAll(response); + if (result >= SCARD_ERROR_OK) { + result = updateRule(response); + + /* update refresh tag */ + this->refreshTag = refreshTag; + } else { + _ERR("getDataAll failed, [%x]", result); + } + } + else + { + _INFO("access rules are not changed. skip update"); + } + + printAccessControlList(); + } else { + _ERR("transmitSync failed, %x", result); + } + + _END(); + + return result; + } + + int GPARAACL::loadACL(Channel *channel) + { + int result = SCARD_ERROR_OK; + + _BEGIN(); + + if (channel == NULL) { + return SCARD_ERROR_ILLEGAL_PARAM; + } + + GPARAM aram(channel); + + result = aram.select(); + if (result >= SCARD_ERROR_OK) { + result = loadACL(aram); + } else { + _ERR("select failed, [%x]", result); + } + + _END(); + + return result; + } + + static bool _isAuthorizedAccess(ByteArray &data, ByteArray &command) + { + vector apduRule; + ByteArray nfcRule; + SimpleTLV tlv(data); + bool result = false; + + if (parseARDO(tlv, apduRule, nfcRule) >= SCARD_ERROR_OK) { + if (apduRule.size() > 0) { + if (apduRule.size() > 1 || + apduRule[0].getLength() != 1) { + if (command.getLength() > 0) { + /* TODO : check apdu rule */ + } else { + /* check hash only */ + result = true; + } + } else { + result = (apduRule[0][0] == 1 ? true : false); + } + } else { + _ERR("unknown data : %s", tlv.toString()); + } + } else { + _ERR("parseARDO failed : %s", tlv.toString()); + } + + return result; + } + + static bool _isAuthorizedNFCAccess(ByteArray &data) + { + vector apduRule; + ByteArray nfcRule; + SimpleTLV tlv(data); + bool result = false; + + if (parseARDO(tlv, apduRule, nfcRule) >= SCARD_ERROR_OK) { + if (nfcRule.getLength() == 1) { + result = (nfcRule[0] == 1 ? true : false); + } else { + _ERR("unknown data : %s", nfcRule.toString()); + } + } else { + _ERR("parseARDO failed : %s", tlv.toString()); + } + + return result; + } + + bool GPARAACL::isAuthorizedAccess(GPARAM &aram, ByteArray &aid, + ByteArray &certHash) + { + vector hashes; + + hashes.push_back(certHash); + + return isAuthorizedAccess(aram, aid, hashes, ByteArray::EMPTY); + } + + bool GPARAACL::isAuthorizedAccess(GPARAM &aram, unsigned char *aidBuffer, + unsigned int aidLength, unsigned char *certHashBuffer, + unsigned int certHashLength) + { + ByteArray aid(aidBuffer, aidLength); + ByteArray hash(certHashBuffer, certHashLength); + + return isAuthorizedAccess(aram, aid, hash); + } + + bool GPARAACL::isAuthorizedAccess(GPARAM &aram, ByteArray &aid, + vector &certHashes) + { + return isAuthorizedAccess(aram, aid, certHashes, ByteArray::EMPTY); + } + + bool GPARAACL::isAuthorizedAccess(GPARAM &aram, ByteArray &aid, + vector &certHashes, ByteArray &command) + { + bool result = allGranted; + ByteArray data; + vector::reverse_iterator item; + + if (aram.isClosed() == true) + return result; + + _BEGIN(); + + if (result == true) { + goto END; + } + /* Step A, find with aid and cert hashes */ + for (item = certHashes.rbegin(); + result == false && item != certHashes.rend(); + item++) { + if (aram.getDataSpecific(aid, *item, data) + >= SCARD_ERROR_OK && data.getLength() > 0) { + result = _isAuthorizedAccess(data, command); + _INFO("rule found (%s): [%s:%s]", result ? "accept" : "deny", aid.toString(), (*item).toString()); + goto END; + } + } + + /* Step B, find with aid and ALL_DEVICES_APPS */ + if (aram.getDataSpecific(aid, ByteArray::EMPTY, data) + >= SCARD_ERROR_OK && data.getLength() > 0) { + result = _isAuthorizedAccess(data, command); + _INFO("rule found (%s): [%s:%s]", result ? "accept" : "deny", aid.toString(), "All device applications"); + goto END; + } + + /* Step C, find with ALL_SE_APPS and hashes */ + for (item = certHashes.rbegin(); + result == false && item != certHashes.rend(); + item++) { + if (aram.getDataSpecific(ByteArray::EMPTY, *item, data) + >= SCARD_ERROR_OK && data.getLength() > 0) { + result = _isAuthorizedAccess(data, command); + _INFO("rule found (%s): [%s:%s]", result ? "accept" : "deny", "All SE Applications", (*item).toString()); + goto END; + } + } + + /* Step D, find with ALL_SE_APPS and ALL_DEVICES_APPS */ + if (aram.getDataSpecific(ByteArray::EMPTY, ByteArray::EMPTY, data) + >= SCARD_ERROR_OK && data.getLength() > 0) { + result = _isAuthorizedAccess(data, command); + _INFO("rule found (%s): [%s:%s]", result ? "accept" : "deny", "All SE Applications", "All device applications"); + goto END; + } + + END : + _END(); + + return result; + } + + bool GPARAACL::isAuthorizedNFCAccess(GPARAM &aram, ByteArray &aid, + vector &certHashes) + { + bool result = allGranted; + ByteArray data; + vector::reverse_iterator item; + + if (aram.isClosed() == true) + return result; + + _BEGIN(); + + if (result == true) { + goto END; + } + /* Step A, find with aid and cert hashes */ + for (item = certHashes.rbegin(); + result == false && item != certHashes.rend(); + item++) { + if (aram.getDataSpecific(aid, *item, data) + >= SCARD_ERROR_OK && data.getLength() > 0) { + result = _isAuthorizedNFCAccess(data); + _INFO("rule found (%s): [%s:%s]", result ? "accept" : "deny", aid.toString(), (*item).toString()); + goto END; + } + } + + /* Step B, find with aid and ALL_DEVICES_APPS */ + if (aram.getDataSpecific(aid, ByteArray::EMPTY, data) + >= SCARD_ERROR_OK && data.getLength() > 0) { + result = _isAuthorizedNFCAccess(data); + _INFO("rule found (%s): [%s:%s]", result ? "accept" : "deny", aid.toString(), "All device applications"); + goto END; + } + + /* Step C, find with ALL_SE_APPS and hashes */ + for (item = certHashes.rbegin(); + result == false && item != certHashes.rend(); + item++) { + if (aram.getDataSpecific(ByteArray::EMPTY, *item, data) + >= SCARD_ERROR_OK && data.getLength() > 0) { + result = _isAuthorizedNFCAccess(data); + _INFO("rule found (%s): [%s:%s]", result ? "accept" : "deny", "All SE Applications", (*item).toString()); + goto END; + } + } + + /* Step D, find with ALL_SE_APPS and ALL_DEVICES_APPS */ + if (aram.getDataSpecific(ByteArray::EMPTY, ByteArray::EMPTY, data) + >= SCARD_ERROR_OK && data.getLength() > 0) { + result = _isAuthorizedNFCAccess(data); + _INFO("rule found (%s): [%s:%s]", result ? "accept" : "deny", "All SE Applications", "All device applications"); + goto END; + } + + END : + _END(); + + return result; + } +} /* namespace smartcard_service_api */ diff --git a/common/GPARAM.cpp b/common/GPARAM.cpp new file mode 100644 index 0000000..ff7f12c --- /dev/null +++ b/common/GPARAM.cpp @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "GPARAM.h" +#include "APDUHelper.h" +#include "FileObject.h" +#include "NumberStream.h" +#include "SimpleTLV.h" +#include "ISO7816BERTLV.h" +#include "AccessCondition.h" + +#ifndef EXTERN_API +#define EXTERN_API __attribute__((visibility("default"))) +#endif + +namespace smartcard_service_api +{ + static unsigned char aid_aram[] = { 0xA0, 0x00, 0x00, 0x01, 0x51, 0x41, 0x43, 0x4C, 00 }; + static ByteArray AID_ARAM(ARRAY_AND_SIZE(aid_aram)); + +#define GET_DATA_ALL 0 +#define GET_DATA_SPECIFIC 1 +#define GET_DATA_REFRESH_TAG 2 +#define GET_DATA_NEXT 3 + +#define ARAM_TAG_ALL_AR 0x0000FF40 +#define ARAM_TAG_AR 0x0000FF50 +#define ARAM_TAG_REFRESH 0x0000DF20 + +#define DO_TAG_AID_REF 0x0000004F +#define DO_TAG_AID_REF_DEFAULT 0x000000C0 +#define DO_TAG_HASH_REF 0x000000C1 +#define DO_TAG_APDU_AR 0x000000D0 +#define DO_TAG_NFC_AR 0x000000D1 +#define DO_TAG_REF 0x000000E1 +#define DO_TAG_REF_AR 0x000000E2 +#define DO_TAG_AR 0x000000E3 + + GPARAM::GPARAM(Channel *channel) + : FileObject(channel) + { + } + + int GPARAM::select() + { + return FileObject::select(AID_ARAM); + } + + static int doTransmit(Channel *channel, const ByteArray &command, ByteArray &response) + { + int result; + ByteArray resp; + + _BEGIN(); + + result = channel->transmitSync(command, resp); + if (result == SCARD_ERROR_OK) { + result = ResponseHelper::getStatus(resp); + if (result >= SCARD_ERROR_OK) { + response = ResponseHelper::getDataField(resp); + _DBG("response[%d] : %s", response.getLength(), response.toString()); + } else { + _ERR("transmit returns error, [%d]", result); + } + } else { + _ERR("transmitSync failed, [%d]", result); + } + + _END(); + + return result; + } + + static int doCommand(Channel *channel, int command, ByteArray &response) + { + int result; + APDUCommand helper; + ByteArray cmd, resp; + + _BEGIN(); + + switch (command) { + case GET_DATA_ALL : + helper.setCommand(0x80, 0xCA, 0xFF, 0x40, ByteArray::EMPTY, 0); + break; + + case GET_DATA_REFRESH_TAG : + helper.setCommand(0x80, 0xCA, 0xDF, 0x20, ByteArray::EMPTY, 0); + break; + + case GET_DATA_NEXT : + helper.setCommand(0x80, 0xCA, 0xFF, 0x60, ByteArray::EMPTY, 0); + break; + } + + helper.getBuffer(cmd); + + _DBG("command[%d] : %s", cmd.getLength(), cmd.toString()); + + result = doTransmit(channel, cmd, response); + + _END(); + + return result; + } + + static int doCommand(Channel *channel, ByteArray &data, ByteArray &response) + { + int result; + APDUCommand helper; + ByteArray cmd; + + helper.setCommand(0x80, 0xCA, 0xFF, 0x50, data, 0); + helper.getBuffer(cmd); + + result = doTransmit(channel, cmd, response); + + return result; + } + + int GPARAM::getDataAll(ByteArray &data) + { + int result; + ByteArray response; + + _BEGIN(); + + result = doCommand(channel, GET_DATA_ALL, response); + if (result >= SCARD_ERROR_OK) { + ISO7816BERTLV tlv(response); + + if (tlv.decodeTLV() == true && + tlv.getTag() == ARAM_TAG_ALL_AR) { + unsigned int length = tlv.getLength(); + + if (length > 0){ + data = tlv.getValue(); + + while (length > data.getLength()) { + result = doCommand(channel, GET_DATA_NEXT, response); + if (result >= SCARD_ERROR_OK) { + data += response; + } else { + _ERR("generateCommand failed, [%d]", result); + data.releaseBuffer(); + break; + } + } + + _DBG("data[%d] : %s", data.getLength(), data.toString()); + } else { + _INFO("Response-ALL-AR-DO is empty"); + data.releaseBuffer(); + } + } else { + _ERR("decodeTLV failed, %s", response.toString()); + result = SCARD_ERROR_ILLEGAL_PARAM; + } + } else { + _ERR("generateCommand failed, [%d]", result); + } + + _END(); + + return result; + } + + static int createRefDo(const ByteArray &aid, const ByteArray &hash, ByteArray &refDo) + { + ByteArray temp; + + temp = SimpleTLV::encode(DO_TAG_AID_REF, aid); + temp += SimpleTLV::encode(DO_TAG_HASH_REF, hash); + + refDo = SimpleTLV::encode(DO_TAG_REF, temp); + _DBG("encoded Ref DO : %s", refDo.toString()); + + return SCARD_ERROR_OK; + } + + int GPARAM::getDataSpecific(const ByteArray &aid, const ByteArray &hash, + ByteArray &data) + { + int result; + ByteArray refDo, response; + + _BEGIN(); + + createRefDo(aid, hash, refDo); + + result = doCommand(channel, refDo, response); + if (result >= SCARD_ERROR_OK) { + ISO7816BERTLV tlv(response); + + if (tlv.decodeTLV() == true && + tlv.getTag() == ARAM_TAG_AR) { + unsigned int length = tlv.getLength(); + + if (length > 0){ + data = tlv.getValue(); + + while (length > data.getLength()) { + result = doCommand(channel, GET_DATA_NEXT, response); + if (result >= SCARD_ERROR_OK) { + data += response; + } else { + _ERR("generateCommand failed, [%d]", result); + data.releaseBuffer(); + break; + } + } + _DBG("data[%d] : %s", data.getLength(), data.toString()); + } else { + _INFO("Response-ALL-AR-DO is empty"); + data.releaseBuffer(); + } + } else { + _ERR("decodeTLV failed, %s", response.toString()); + result = SCARD_ERROR_ILLEGAL_PARAM; + } + } else { + _ERR("doCommand failed, [%d]", result); + } + + _END(); + + return result; + } + + int GPARAM::getDataRefreshTag(ByteArray &tag) + { + int result; + ByteArray response; + + _BEGIN(); + + result = doCommand(channel, GET_DATA_REFRESH_TAG, response); + if (result >= SCARD_ERROR_OK) { + ISO7816BERTLV tlv(response); + + if (tlv.decodeTLV() == true && + tlv.getTag() == ARAM_TAG_REFRESH && + tlv.getLength() == 8) { + tag = tlv.getValue(); + result = SCARD_ERROR_OK; + _DBG("refreshTag[%d] : %s", tag.getLength(), tag.toString()); + } else { + _ERR("decodeTLV failed, %s", response.toString()); + result = SCARD_ERROR_ILLEGAL_PARAM; + } + } else { + _ERR("generateCommand failed, [%d]", result); + } + + _END(); + + return result; + } +} /* namespace smartcard_service_api */ diff --git a/common/GPARFACL.cpp b/common/GPARFACL.cpp new file mode 100644 index 0000000..4cad060 --- /dev/null +++ b/common/GPARFACL.cpp @@ -0,0 +1,416 @@ +/* + * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "GPARFACL.h" +#include "PKCS15ODF.h" +#include "PKCS15DODF.h" +#include "NumberStream.h" +#include "SimpleTLV.h" +#include "AccessCondition.h" + +#ifndef EXTERN_API +#define EXTERN_API __attribute__((visibility("default"))) +#endif + +namespace smartcard_service_api +{ + static unsigned char oid_globalplatform[] = { 0x2A, 0x86, 0x48, 0x86, 0xFC, 0x6B, 0x81, 0x48, 0x01, 0x01 }; + static ByteArray OID_GLOBALPLATFORM(ARRAY_AND_SIZE(oid_globalplatform)); + + GPARFACL::GPARFACL() : AccessControlList() + { + } + + GPARFACL::~GPARFACL() + { + } + + int GPARFACL::loadACL(Channel *channel) + { + int result = SCARD_ERROR_OK; + + _BEGIN(); + + if (channel == NULL) + { + return SCARD_ERROR_ILLEGAL_PARAM; + } + + PKCS15 pkcs15(channel); + + /* basically, all requests will be accepted when PKCS #15 doesn't exist or global platform OID is not placed */ + allGranted = false; + + result = pkcs15.select(); + if (result >= SCARD_ERROR_OK) + { + PKCS15ODF *odf; + + result = SCARD_ERROR_OK; + allGranted = true; + + if ((odf = pkcs15.getODF()) != NULL) + { + PKCS15DODF *dodf; + + if ((dodf = odf->getDODF()) != NULL) + { + result = loadAccessControl(channel, dodf); + if (result == SCARD_ERROR_OK) + { + printAccessControlList(); + } + else + { + _INFO("loadAccessControl failed, every request will be accepted."); + result = SCARD_ERROR_OK; + } + } + else + { + _INFO("dodf null, every request will be accepted."); + } + } + else + { + _INFO("odf null, every request will be accepted."); + } + } + else + { + _ERR("failed to open PKCS15, every request will be denied."); + } + + _END(); + + return result; + } + + int GPARFACL::loadAccessControl(Channel *channel, PKCS15DODF *dodf) + { + int result = -1; + ByteArray path; + + if ((result = dodf->searchOID(OID_GLOBALPLATFORM, path)) == 0) + { + ByteArray data; + FileObject file(channel); + + _DBG("oid path : %s", path.toString()); + + file.select(NumberStream::getLittleEndianNumber(path)); + file.readBinary(0, 0, file.getFCP()->getFileSize(), data); + + _DBG("data : %s", data.toString()); + + /* PKCS #15 and DODF OID exists. apply access control rule!! */ + allGranted = false; + + SimpleTLV tlv(data); + + if (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE : AccessControlMainFile */ + { + tlv.enterToValueTLV(); + + /* refresh Tag */ + ByteArray refreshTag; + + refreshTag = SimpleTLV::getOctetString(tlv); + _DBG("current refresh tag : %s", refreshTag.toString()); + + if (this->refreshTag != refreshTag) /* need to update access control list */ + { + this->refreshTag = refreshTag; + + releaseACL(); + + /* access control rule path */ + if (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE : Path */ + { + /* TODO : parse path */ + ByteArray path; + + /* OCTET STRING */ + path = SimpleTLV::getOctetString(tlv.getValue()); + _DBG("access control rule path : %s", path.toString()); + + if (loadRules(channel, path) == 0) + { + _DBG("loadRules success"); + } + else + { + _ERR("loadRules failed"); + } + } + } + else + { + _INFO("access rules are not changed. skip update"); + } + tlv.returnToParentTLV(); + } + else + { + _ERR("tlv.decodeTLV failed"); + } + } + else + { + _ERR("OID not found"); + } + + return result; + } + + int GPARFACL::loadRules(Channel *channel, const ByteArray &path) + { + FileObject file(channel); + ByteArray data, aid; + + file.select(NumberStream::getLittleEndianNumber(path)); + file.readBinary(0, 0, file.getFCP()->getFileSize(), data); + + _DBG("data : %s", data.toString()); + + SimpleTLV tlv(data); + + while (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE : Rule */ + { + tlv.enterToValueTLV(); + if (tlv.decodeTLV() == true) + { + /* target */ + switch (tlv.getTag()) + { + case 0xA0 : /* CHOICE 0 : EXPLICIT AID */ + /* OCTET STRING */ + aid = SimpleTLV::getOctetString(tlv.getValue()); + break; + + case 0x81 : /* CHOICE 1?? : default */ + aid = AccessControlList::DEFAULT_SE_APP; + break; + + case 0x82 : /* CHOICE 2?? : any application */ + aid = AccessControlList::ALL_SE_APPS; + break; + } + + _DBG("aid : %s", aid.toString()); + + /* access condition path */ + if (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE : Path */ + { + ByteArray path; + + /* OCTET STRING */ + path = SimpleTLV::getOctetString(tlv.getValue()); + _DBG("path : %s", path.toString()); + + if (loadAccessConditions(channel, aid, path) == 0) + { + _DBG("loadCertHashes success"); + } + else + { + _ERR("loadCertHashes failed"); + } + } + else + { + _ERR("decodeTLV failed"); + } + } + else + { + _ERR("decodeTLV failed"); + } + tlv.returnToParentTLV(); + } + + return 0; + } + + static void loadAPDUAccessRule(AccessRule *rule, const ByteArray &data) + { + SimpleTLV tlv(data); + + if (tlv.decodeTLV() == true) + { + switch (tlv.getTag()) + { + case 0xA0 : /* CHOICE 0 : APDUPermission */ + rule->setAPDUAccessRule(SimpleTLV::getBoolean(tlv.getValue())); + break; + + case 0xA1 : /* CHOICE 1 : APDUFilters */ + tlv.enterToValueTLV(); + while (tlv.decodeTLV() == true) + { + if (tlv.getTag() == 0x04) /* OCTET STRING */ + { + ByteArray apdu, mask, value; + + value = tlv.getValue(); + + _DBG("APDU rule : %s", value.toString()); + + if (value.getLength() == 8) /* apdu 4 bytes + mask 4 bytes */ + { + apdu.setBuffer(value.getBuffer(), 4); + mask.setBuffer(value.getBuffer(4), 4); + + rule->addAPDUAccessRule(apdu, mask); + } + else + { + _ERR("Invalid APDU rule : %s", value.toString()); + } + } + else + { + _ERR("Unknown tag : 0x%02X", tlv.getTag()); + } + } + tlv.returnToParentTLV(); + break; + + default : + _ERR("Unknown tag : 0x%02X", tlv.getTag()); + break; + } + } + } + + static void loadNFCAccessRule(AccessRule *rule, const ByteArray &data) + { + rule->setNFCAccessRule(SimpleTLV::getBoolean(data)); + } + + static void loadAccessCondition(AccessCondition &condition, const ByteArray &data) + { + if (data.getLength() > 0) + { + SimpleTLV tlv(data); + ByteArray hash; + + while (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE */ + { + if (tlv.getLength() > 0) + { + /* access granted for specific applications */ + tlv.enterToValueTLV(); + if (tlv.decodeTLV()) + { + switch (tlv.getTag()) + { + case 0x04 : /* OCTET STRING : CertHash */ + _DBG("aid : %s, hash : %s", condition.getAID().toString(), tlv.getValue().toString()); + + hash = tlv.getValue(); + condition.addAccessRule(tlv.getValue()); + break; + + case 0xA0 : /* CHOICE 0 : AccessRules */ + tlv.enterToValueTLV(); + if (tlv.decodeTLV()) + { + AccessRule *rule = condition.getAccessRule(hash); + if (rule == NULL) { + condition.addAccessRule(hash); + rule = condition.getAccessRule(hash); + } + + switch (tlv.getTag()) + { + case 0xA0 : /* CHOICE 0 : APDUAccessRule */ + loadAPDUAccessRule(rule, tlv.getValue()); + break; + + case 0xA1 : /* CHOICE 1 : NFCAccessRule */ + loadNFCAccessRule(rule, tlv.getValue()); + break; + + default : + _ERR("Unknown tag : 0x%02X", tlv.getTag()); + break; + } + } + else + { + _ERR("tlv.decodeTLV failed"); + } + tlv.returnToParentTLV(); + break; + + default : + _ERR("Unknown tag : 0x%02X", tlv.getTag()); + break; + } + } + else + { + _ERR("tlv.decodeTLV failed"); + } + tlv.returnToParentTLV(); + } + else + { + _INFO("access denied for all applications, aid : %s", condition.getAID().toString()); + + condition.setAccessCondition(false); + break; + } + } + } + else + { + _INFO("access denied for all applications, aid : %s", condition.getAID().toString()); + + condition.setAccessCondition(false); + } + } + + int GPARFACL::loadAccessConditions(Channel *channel, const ByteArray &aid, const ByteArray &path) + { + FileObject file(channel); + ByteArray data; + + file.select(NumberStream::getLittleEndianNumber(path)); + file.readBinary(0, 0, file.getFCP()->getFileSize(), data); + + _DBG("data : %s", data.toString()); + + AccessCondition condition; + + condition.setAID(aid); + loadAccessCondition(condition, data); + + pair newItem(aid, condition); + + mapConditions.insert(newItem); + + return 0; + } + +} /* namespace smartcard_service_api */ diff --git a/common/GPSEACL.cpp b/common/GPSEACL.cpp deleted file mode 100644 index d5ecc11..0000000 --- a/common/GPSEACL.cpp +++ /dev/null @@ -1,341 +0,0 @@ -/* - * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* standard library header */ - -/* SLP library header */ - -/* local header */ -#include "Debug.h" -#include "GPSEACL.h" -#include "PKCS15ODF.h" -#include "PKCS15DODF.h" -#include "NumberStream.h" -#include "SimpleTLV.h" -#include "AccessCondition.h" - -#ifndef EXTERN_API -#define EXTERN_API __attribute__((visibility("default"))) -#endif - -namespace smartcard_service_api -{ - static unsigned char oid_globalplatform[] = { 0x2A, 0x86, 0x48, 0x86, 0xFC, 0x6B, 0x81, 0x48, 0x01, 0x01 }; - ByteArray GPSEACL::OID_GLOBALPLATFORM(ARRAY_AND_SIZE(oid_globalplatform)); - - GPSEACL::GPSEACL():AccessControlList() - { - } - - GPSEACL::~GPSEACL() - { - } - - int GPSEACL::loadACL(Channel *channel) - { - int result = 0; - PKCS15 *pkcs15; - - if (channel == NULL) - { - return -1; - } - - pkcs15 = new PKCS15(channel, channel->getSelectResponse()); - if (pkcs15 != NULL) - { - /* basically, all requests will be accepted when PKCS #15 doesn't exist or global platform OID is not placed */ - allGranted = true; - - if (pkcs15->isClosed() == false) - { - PKCS15ODF *odf; - - if ((odf = pkcs15->getODF()) != NULL) - { - PKCS15DODF *dodf; - - if ((dodf = odf->getDODF()) != NULL) - { - if (loadAccessControl(channel, dodf) == 0) - { - printAccessControlList(); - - result = 0; - } - else - { - _ERR("loadAccessControl failed, every request will be accepted."); - } - } - else - { - _ERR("dodf null, every request will be accepted."); - } - } - else - { - _ERR("odf null, every request will be accepted."); - } - } - else - { - _ERR("failed to open PKCS15, every request will be accepted."); - } - - delete pkcs15; - } - else - { - return -1; - } - - return result; - } - - int GPSEACL::loadAccessControl(Channel *channel, PKCS15DODF *dodf) - { - int result = -1; - ByteArray path; - - if ((result = dodf->searchOID(OID_GLOBALPLATFORM, path)) == 0) - { - ByteArray data; - FileObject file(channel); - - _DBG("oid path : %s", path.toString()); - - file.select(NumberStream::getLittleEndianNumber(path)); - file.readBinary(0, 0, file.getFCP()->getFileSize(), data); - - _DBG("data : %s", data.toString()); - - /* PKCS #15 and DODF OID exists. apply access control rule!! */ - allGranted = false; - - SimpleTLV tlv(data); - - if (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE : AccessControlMainFile */ - { - tlv.enterToValueTLV(); - - /* refresh Tag */ - ByteArray refreshTag; - - refreshTag = SimpleTLV::getOctetString(tlv); - _DBG("current refresh tag : %s", refreshTag.toString()); - - if (this->refreshTag != refreshTag) /* need to update access control list */ - { - this->refreshTag = refreshTag; - - releaseACL(); - - /* access control rule path */ - if (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE : Path */ - { - /* TODO : parse path */ - ByteArray path; - - /* OCTET STRING */ - path = SimpleTLV::getOctetString(tlv.getValue()); - _DBG("access control rule path : %s", path.toString()); - - if (loadRules(channel, path) == 0) - { - _DBG("loadRules success"); - } - else - { - _ERR("loadRules failed"); - } - } - } - tlv.returnToParentTLV(); - } - else - { - _ERR("tlv.decodeTLV failed"); - } - } - else - { - _ERR("OID not found"); - } - - return result; - } - - int GPSEACL::loadRules(Channel *channel, ByteArray path) - { - FileObject file(channel); - ByteArray data, aid; - - file.select(NumberStream::getLittleEndianNumber(path)); - file.readBinary(0, 0, file.getFCP()->getFileSize(), data); - - _DBG("data : %s", data.toString()); - - SimpleTLV tlv(data); - - while (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE : Rule */ - { - tlv.enterToValueTLV(); - if (tlv.decodeTLV() == true) - { - /* target */ - switch (tlv.getTag()) - { - case 0xA0 : /* CHOICE 0 : EXPLICIT AID */ - /* OCTET STRING */ - aid = SimpleTLV::getOctetString(tlv.getValue()); - break; - - case 0x81 : /* CHOICE 1?? : default */ - aid = AccessControlList::AID_DEFAULT; - break; - - case 0x82 : /* CHOICE 2?? : any application */ - aid = AccessControlList::AID_ALL; - break; - } - - _DBG("aid : %s", aid.toString()); - - /* access condition path */ - if (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE : Path */ - { - ByteArray path; - - /* OCTET STRING */ - path = SimpleTLV::getOctetString(tlv.getValue()); - _DBG("path : %s", path.toString()); - - if (loadAccessConditions(channel, aid, path) == 0) - { - _DBG("loadCertHashes success"); - } - else - { - _ERR("loadCertHashes failed"); - } - } - else - { - _ERR("decodeTLV failed"); - } - } - else - { - _ERR("decodeTLV failed"); - } - tlv.returnToParentTLV(); - } - - return 0; - } - - int GPSEACL::loadAccessConditions(Channel *channel, ByteArray aid, ByteArray path) - { - FileObject file(channel); - ByteArray data; - - file.select(NumberStream::getLittleEndianNumber(path)); - file.readBinary(0, 0, file.getFCP()->getFileSize(), data); - - _DBG("data : %s", data.toString()); - - AccessCondition condition; - - condition.loadAccessCondition(aid, data); - - pair newItem(aid, condition); - - mapConditions.insert(newItem); - - return 0; - } - -} /* namespace smartcard_service_api */ - -/* export C API */ -#define GP_SE_ACL_EXTERN_BEGIN \ - if (handle != NULL) \ - { \ - GPSEACL *acl = (GPSEACL *)handle; - -#define GP_SE_ACL_EXTERN_END \ - } \ - else \ - { \ - _ERR("Invalid param"); \ - } - -using namespace smartcard_service_api; - -EXTERN_API gp_se_acl_h gp_se_acl_create_instance() -{ - GPSEACL *acl = new GPSEACL(); - - return (gp_se_acl_h)acl; -} - -EXTERN_API int gp_se_acl_load_acl(gp_se_acl_h handle, channel_h channel) -{ - int result = -1; - - GP_SE_ACL_EXTERN_BEGIN; - result = acl->loadACL((Channel *)channel); - GP_SE_ACL_EXTERN_END; - - return result; -} - -EXTERN_API int gp_se_acl_update_acl(gp_se_acl_h handle, channel_h channel) -{ - int result = -1; - - GP_SE_ACL_EXTERN_BEGIN; - acl->updateACL((Channel *)channel); - GP_SE_ACL_EXTERN_END; - - return result; -} - -EXTERN_API void gp_se_acl_release_acl(gp_se_acl_h handle) -{ - GP_SE_ACL_EXTERN_BEGIN; - acl->releaseACL(); - GP_SE_ACL_EXTERN_END; -} - -EXTERN_API bool gp_se_acl_is_authorized_access(gp_se_acl_h handle, unsigned char *aidBuffer, unsigned int aidLength, unsigned char *certHashBuffer, unsigned int certHashLength) -{ - bool result = false; - - GP_SE_ACL_EXTERN_BEGIN; - result = acl->isAuthorizedAccess(aidBuffer, aidLength, certHashBuffer, certHashLength); - GP_SE_ACL_EXTERN_END; - - return result; -} - -EXTERN_API void gp_se_acl_destroy_instance(gp_se_acl_h handle) -{ - GP_SE_ACL_EXTERN_BEGIN; - delete acl; - GP_SE_ACL_EXTERN_END; -} diff --git a/common/ISO7816BERTLV.cpp b/common/ISO7816BERTLV.cpp index eb0719d..2633526 100644 --- a/common/ISO7816BERTLV.cpp +++ b/common/ISO7816BERTLV.cpp @@ -25,13 +25,15 @@ namespace smartcard_service_api { - ISO7816BERTLV::ISO7816BERTLV():TLVHelper() + ISO7816BERTLV::ISO7816BERTLV() + : TLVHelper() { tagClass = 0; encoding = 0; } - ISO7816BERTLV::ISO7816BERTLV(TLVHelper *parent):TLVHelper(parent) + ISO7816BERTLV::ISO7816BERTLV(TLVHelper *parent) + : TLVHelper(parent) { parentTLV = parent; @@ -39,13 +41,15 @@ namespace smartcard_service_api encoding = 0; } - ISO7816BERTLV::ISO7816BERTLV(const ByteArray &array):TLVHelper(array) + ISO7816BERTLV::ISO7816BERTLV(const ByteArray &array) + : TLVHelper(array) { tagClass = 0; encoding = 0; } - ISO7816BERTLV::ISO7816BERTLV(const ByteArray &array, TLVHelper *parent):TLVHelper(array, parent) + ISO7816BERTLV::ISO7816BERTLV(const ByteArray &array, TLVHelper *parent) + : TLVHelper(array, parent) { parentTLV = parent; @@ -71,7 +75,7 @@ namespace smartcard_service_api } /* first byte */ - tagClass = (buffer[0] & 0xE0) >> 6; + tagClass = (buffer[0] & 0xC0) >> 6; encoding = (buffer[0] & 0x20) >> 5; currentT = buffer[0]; diff --git a/common/PKCS15.cpp b/common/PKCS15.cpp index 6b4d0c7..dc195fa 100644 --- a/common/PKCS15.cpp +++ b/common/PKCS15.cpp @@ -30,12 +30,30 @@ namespace smartcard_service_api 0x4B, 0x43, 0x53, 0x2D, 0x31, 0x35 }; ByteArray PKCS15::PKCS15_AID(ARRAY_AND_SIZE(aid)); - PKCS15::PKCS15(Channel *channel) - : PKCS15Object(channel), odf(NULL) + PKCS15::PKCS15(Channel *channel) : + PKCS15Object(channel), odf(NULL) + { + } + + PKCS15::PKCS15(Channel *channel, const ByteArray &selectResponse) : + PKCS15Object(channel, selectResponse), odf(NULL) + { + } + + PKCS15::~PKCS15() + { + if (odf != NULL) + { + delete odf; + odf = NULL; + } + } + + int PKCS15::select() { int ret; - ret = select(PKCS15::PKCS15_AID); + ret = PKCS15Object::select(PKCS15::PKCS15_AID); if (ret >= SCARD_ERROR_OK) { _DBG("response : %s", selectResponse.toString()); @@ -44,7 +62,8 @@ namespace smartcard_service_api { _ERR("PKCS15 AID not found, search in EF DIR"); - if (selectFromEFDIR() == true) + ret = selectFromEFDIR(); + if (ret >= SCARD_ERROR_OK) { _DBG("response : %s", selectResponse.toString()); } @@ -57,49 +76,40 @@ namespace smartcard_service_api { _ERR("PKCS15 select failed, [%d]", ret); } - } - PKCS15::PKCS15(Channel *channel, ByteArray selectResponse) - : PKCS15Object(channel, selectResponse), odf(NULL) - { + return ret; } - PKCS15::~PKCS15() + int PKCS15::selectFromEFDIR() { - if (odf != NULL) - { - delete odf; - odf = NULL; - } - } - - bool PKCS15::selectFromEFDIR() - { - bool result = false; + int ret; ByteArray path; EFDIR dir(channel); - path = dir.getPathByAID(PKCS15_AID); - if (path.getLength() > 0) + ret = dir.select(); + if (ret >= SCARD_ERROR_OK) { - int ret; - - ret = select(path, false); - if (ret >= SCARD_ERROR_OK) + path = dir.getPathByAID(PKCS15_AID); + if (path.getLength() > 0) { - result = true; + ret = PKCS15Object::select(path, false); + if (ret < SCARD_ERROR_OK) + { + _ERR("PKCS15 select failed, [%d]", ret); + } } else { - _ERR("path select failed, [%d]", ret); + _ERR("PKCS15 path is not found"); + ret = SCARD_ERROR_NOT_SUPPORTED; } } else { - _ERR("PKCS15 not found"); + _ERR("select EFDIR failed, [%x]", -ret); } - return result; + return ret; } PKCS15ODF *PKCS15::getODF() diff --git a/common/PKCS15DODF.cpp b/common/PKCS15DODF.cpp index e3d504f..2c5c6d2 100644 --- a/common/PKCS15DODF.cpp +++ b/common/PKCS15DODF.cpp @@ -25,12 +25,8 @@ namespace smartcard_service_api { -// PKCS15DODF::PKCS15DODF():PKCS15Object() -// { -// -// } - - PKCS15DODF::PKCS15DODF(unsigned int fid, Channel *channel):PKCS15Object(channel) + PKCS15DODF::PKCS15DODF(unsigned int fid, Channel *channel) : + PKCS15Object(channel) { int ret = 0; @@ -57,7 +53,8 @@ namespace smartcard_service_api } } - PKCS15DODF::PKCS15DODF(ByteArray path, Channel *channel):PKCS15Object(channel) + PKCS15DODF::PKCS15DODF(ByteArray path, Channel *channel) : + PKCS15Object(channel) { int ret = 0; diff --git a/common/PKCS15ODF.cpp b/common/PKCS15ODF.cpp index 84c9590..aa37499 100644 --- a/common/PKCS15ODF.cpp +++ b/common/PKCS15ODF.cpp @@ -26,8 +26,8 @@ namespace smartcard_service_api { - PKCS15ODF::PKCS15ODF(Channel *channel) - : PKCS15Object(channel), dodf(NULL) + PKCS15ODF::PKCS15ODF(Channel *channel) : + PKCS15Object(channel), dodf(NULL) { int ret = 0; @@ -54,8 +54,8 @@ namespace smartcard_service_api } } - PKCS15ODF::PKCS15ODF(Channel *channel, ByteArray selectResponse) - : PKCS15Object(channel, selectResponse), dodf(NULL) + PKCS15ODF::PKCS15ODF(Channel *channel, ByteArray selectResponse) : + PKCS15Object(channel, selectResponse), dodf(NULL) { int ret = 0; ByteArray odfData; diff --git a/common/SignatureHelper.cpp b/common/SignatureHelper.cpp index 6619975..9db34a1 100644 --- a/common/SignatureHelper.cpp +++ b/common/SignatureHelper.cpp @@ -61,8 +61,6 @@ namespace smartcard_service_api } pkgmgrinfo_appinfo_destroy_appinfo(handle_appinfo); - SCARD_DEBUG("package name : %s", pkgid); - if ((ret = pkgmgr_pkginfo_create_certinfo(&handle)) == 0) { if ((ret = pkgmgr_pkginfo_load_certinfo(pkgid, handle)) == 0) @@ -159,8 +157,6 @@ namespace smartcard_service_api return result; } - SCARD_DEBUG("package name : %s", pkgid); - if ((ret = pkgmgr_pkginfo_create_certinfo(&handle)) == 0) { if ((ret = pkgmgr_pkginfo_load_certinfo(pkgid, handle)) == 0) diff --git a/common/include/AccessCondition.h b/common/include/AccessCondition.h index 20ca90a..f9aac60 100644 --- a/common/include/AccessCondition.h +++ b/common/include/AccessCondition.h @@ -18,8 +18,8 @@ #define ACCESSCONDITION_H_ /* standard library header */ -#include #include +#include /* SLP library header */ @@ -30,39 +30,34 @@ using namespace std; namespace smartcard_service_api { - class APDUAccessRule + class AccessRule { private : - bool permission; - map mapApduFilters; + bool apduRule; + bool nfcRule; + vector > listFilters; + + void printAccessRules(); public : - APDUAccessRule() + AccessRule() : apduRule(true), nfcRule(true) { - permission = true; } - void loadAPDUAccessRule(const ByteArray &data); - bool isAuthorizedAccess(const ByteArray &command); + inline void setAPDUAccessRule(bool rule) { apduRule = rule; } + inline void setNFCAccessRule(bool rule) { nfcRule = rule; } - void printAPDUAccessRules(); - }; - - class NFCAccessRule - { - private : - bool permission; + void addAPDUAccessRule(const ByteArray &apdu, + const ByteArray &mask); - public : - NFCAccessRule() + inline bool isAuthorizedAccess(void) { - permission = true; + return (apduRule || (listFilters.size() > 0)); } + bool isAuthorizedAPDUAccess(const ByteArray &command); + bool isAuthorizedNFCAccess(void); - void loadNFCAccessRule(const ByteArray &data); - bool isAuthorizedAccess(void); - - void printNFCAccessRules(); + friend class AccessCondition; }; class AccessCondition @@ -70,21 +65,37 @@ namespace smartcard_service_api private : bool permission; ByteArray aid; - vector hashes; - APDUAccessRule apduRule; - NFCAccessRule nfcRule; + map mapRules; + + void printAccessConditions(); public : AccessCondition() : permission(false) { } - void loadAccessCondition(ByteArray &aid, ByteArray &data); - bool isAuthorizedAccess(ByteArray &certHash); - bool isAuthorizedAPDUAccess(ByteArray &command); - bool isAuthorizedNFCAccess(); + inline void setAID(const ByteArray &aid) { this->aid = aid; } + inline ByteArray getAID() { return aid; } + inline void setAccessCondition(bool rule) { permission = rule; } + void addAccessRule(const ByteArray &hash); + AccessCondition *getAccessCondition(const ByteArray &hash); - void printAccessConditions(); + void setAPDUAccessRule(const ByteArray &certHash, bool rule); + void addAPDUAccessRule(const ByteArray &certHash, + const ByteArray &apdu, const ByteArray &mask); + void addAPDUAccessRule(const ByteArray &certHash, + const ByteArray &rule); + + void setNFCAccessRule(const ByteArray &certHash, bool rule); + + bool isAuthorizedAccess(const ByteArray &certHash); + bool isAuthorizedAPDUAccess(const ByteArray &certHash, + const ByteArray &command); + bool isAuthorizedNFCAccess(const ByteArray &certHash); + + AccessRule *getAccessRule(const ByteArray &certHash); + + friend class AccessControlList; }; } /* namespace smartcard_service_api */ diff --git a/common/include/AccessControlList.h b/common/include/AccessControlList.h index 1bbbb76..b2af0d4 100644 --- a/common/include/AccessControlList.h +++ b/common/include/AccessControlList.h @@ -26,25 +26,28 @@ /* local header */ #include "ByteArray.h" #include "Channel.h" +#include "AccessCondition.h" using namespace std; namespace smartcard_service_api { - class AccessCondition; - class AccessControlList { protected: map mapConditions; bool allGranted; + AccessRule *findAccessRule(const ByteArray &aid, + const ByteArray &hash); + AccessCondition &getAccessCondition(const ByteArray &aid); + void printAccessControlList(); - bool isAuthorizedAccess(ByteArray aid, ByteArray certHash, bool update); public: - static ByteArray AID_ALL; - static ByteArray AID_DEFAULT; + static ByteArray ALL_SE_APPS; + static ByteArray DEFAULT_SE_APP; + static ByteArray ALL_DEVICE_APPS; AccessControlList(); virtual ~AccessControlList(); @@ -54,9 +57,17 @@ namespace smartcard_service_api int updateACL(Channel *channel) { return loadACL(channel); } void releaseACL(); - bool isAuthorizedAccess(ByteArray aid, ByteArray certHash); - bool isAuthorizedAccess(unsigned char *aidBuffer, unsigned int aidLength, unsigned char *certHashBuffer, unsigned int certHashLength); - bool isAuthorizedAccess(ByteArray aid, vector &certHashes); + bool isAuthorizedAccess(ByteArray &aid, + ByteArray &certHash); + bool isAuthorizedAccess(unsigned char *aidBuffer, + unsigned int aidLength, unsigned char *certHashBuffer, + unsigned int certHashLength); + bool isAuthorizedAccess(ByteArray &aid, + vector &certHashes); + bool isAuthorizedAccess(ByteArray &aid, + vector &certHashes, ByteArray &command); + bool isAuthorizedNFCAccess(ByteArray &aid, + vector &certHashes); }; } /* namespace smartcard_service_api */ diff --git a/common/include/ByteArray.h b/common/include/ByteArray.h index cc08c5b..ee1edf9 100644 --- a/common/include/ByteArray.h +++ b/common/include/ByteArray.h @@ -62,6 +62,8 @@ namespace smartcard_service_api uint32_t copyFromArray(uint8_t *array, uint32_t bufferLen) const; + ByteArray sub(uint32_t offset, uint32_t size) const; + /* operator overloading */ ByteArray &operator =(const ByteArray &T); ByteArray operator +(const ByteArray &T); @@ -72,7 +74,7 @@ namespace smartcard_service_api bool operator >(const ByteArray &T) const; uint8_t &operator [](uint32_t index) const; - inline bool isEmpty() { return (buffer == (void *)0 || length == 0); } + inline bool isEmpty() const { return (buffer == (void *)0 || length == 0); } const char *toString(); }; diff --git a/common/include/EFDIR.h b/common/include/EFDIR.h index c2fd9f1..556cdf6 100644 --- a/common/include/EFDIR.h +++ b/common/include/EFDIR.h @@ -35,12 +35,12 @@ namespace smartcard_service_api ByteArray parseRecord(Record &record, ByteArray &aid); public: - static const unsigned int EFDIR_FID = 0x002f; - EFDIR(Channel *channel); EFDIR(Channel *channel, ByteArray selectResponse); ~EFDIR(); + int select(); + ByteArray getPathByAID(ByteArray &aid); }; } /* namespace smartcard_service_api */ diff --git a/common/include/FileObject.h b/common/include/FileObject.h index 55bd2f7..d38105a 100644 --- a/common/include/FileObject.h +++ b/common/include/FileObject.h @@ -39,11 +39,11 @@ namespace smartcard_service_api FCP fcp; bool opened; - int _select(ByteArray command); + int _select(const ByteArray &command); protected: ByteArray selectResponse; - bool setSelectResponse(ByteArray response); + bool setSelectResponse(const ByteArray &response); public: static const int SUCCESS = 0; @@ -58,13 +58,13 @@ namespace smartcard_service_api static const unsigned int MF_FID = 0x003F; FileObject(Channel *channel); - FileObject(Channel *channel, ByteArray selectResponse); + FileObject(Channel *channel, const ByteArray &selectResponse); ~FileObject(); void close(); inline bool isClosed() { return (opened == false); } - int select(ByteArray aid); - int select(ByteArray path, bool fromCurrentDF); + int select(const ByteArray &aid); + int select(const ByteArray &path, bool fromCurrentDF); int select(unsigned int fid); int selectParent(); @@ -74,12 +74,12 @@ namespace smartcard_service_api FCP *getFCP(); int readRecord(unsigned int sfi, unsigned int recordId, Record &result); - int writeRecord(unsigned int sfi, Record record); + int writeRecord(unsigned int sfi, const Record &record); - int searchRecord(unsigned int sfi, ByteArray searchParam, vector &result); + int searchRecord(unsigned int sfi, const ByteArray &searchParam, vector &result); int readBinary(unsigned int sfi, unsigned int offset, unsigned int length, ByteArray &result); - int writeBinary(unsigned int sfi, ByteArray data, unsigned int offset, unsigned int length); + int writeBinary(unsigned int sfi, const ByteArray &data, unsigned int offset, unsigned int length); }; } /* namespace smartcard_service_api */ diff --git a/common/include/GPACE.h b/common/include/GPACE.h new file mode 100644 index 0000000..4754d31 --- /dev/null +++ b/common/include/GPACE.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef GPACE_H_ +#define GPACE_H_ + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "smartcard-types.h" +#ifdef __cplusplus +#include "AccessControlList.h" +#endif /* __cplusplus */ + +#ifdef __cplusplus +namespace smartcard_service_api +{ + class GPACE : public AccessControlList + { + private : + AccessControlList *acl; + + public : + GPACE(); + ~GPACE(); + + int loadACL(Channel *channel); + + bool isAuthorizedAccess(ByteArray &aid, + ByteArray &certHash); + bool isAuthorizedAccess(unsigned char *aidBuffer, + unsigned int aidLength, unsigned char *certHashBuffer, + unsigned int certHashLength); + bool isAuthorizedAccess(ByteArray &aid, + vector &certHashes); + bool isAuthorizedAccess(ByteArray &aid, + vector &certHashes, ByteArray &command); + bool isAuthorizedNFCAccess(ByteArray &aid, + vector &certHashes); + }; + +} /* namespace smartcard_service_api */ +#endif /* __cplusplus */ +#endif /* GPACE_H_ */ diff --git a/common/include/GPARAACL.h b/common/include/GPARAACL.h new file mode 100644 index 0000000..305f7f9 --- /dev/null +++ b/common/include/GPARAACL.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef GPARAACL_H_ +#define GPARAACL_H_ + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "smartcard-types.h" +#ifdef __cplusplus +#include "AccessControlList.h" +#include "GPARAM.h" +#endif /* __cplusplus */ + +#ifdef __cplusplus +namespace smartcard_service_api +{ + class GPARAACL : public AccessControlList + { + private: + ByteArray refreshTag; + + void addCondition(const ByteArray &aid, const ByteArray &hash, + const vector &apduRule, const ByteArray &nfcRule); + + int updateRule(ByteArray &data); + + public: + GPARAACL(); + ~GPARAACL(); + + int loadACL(Channel *channel); + int loadACL(GPARAM &aram); + + bool isAuthorizedAccess(GPARAM &aram, ByteArray &aid, + ByteArray &certHash); + bool isAuthorizedAccess(GPARAM &aram, ByteArray &aid, + ByteArray &certHash, ByteArray &command); + bool isAuthorizedAccess(GPARAM &aram, unsigned char *aidBuffer, + unsigned int aidLength, unsigned char *certHashBuffer, + unsigned int certHashLength); + bool isAuthorizedAccess(GPARAM &aram, ByteArray &aid, + vector &certHashes); + bool isAuthorizedAccess(GPARAM &aram, ByteArray &aid, + vector &certHashes, ByteArray &command); + bool isAuthorizedNFCAccess(GPARAM &aram, ByteArray &aid, + vector &certHashes); + }; + +} /* namespace smartcard_service_api */ +#endif /* __cplusplus */ + +#endif /* GPARAACL_H_ */ diff --git a/common/include/GPARAM.h b/common/include/GPARAM.h new file mode 100644 index 0000000..d4b3116 --- /dev/null +++ b/common/include/GPARAM.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef GPARAM_H_ +#define GPARAM_H_ + +/* standard library header */ +#include + +/* SLP library header */ + +/* local header */ +#include "FileObject.h" + +using namespace std; + +namespace smartcard_service_api +{ + class GPARAM : public FileObject + { + public: + GPARAM(Channel *channel); + GPARAM(Channel *channel, const ByteArray &selectResponse); + ~GPARAM() {} + + int select(); + + int getDataAll(ByteArray &data); + int getDataSpecific(const ByteArray &aid, const ByteArray &hash, ByteArray &data); + int getDataRefreshTag(ByteArray &tag); + + /* override not supported functions */ + int select(const ByteArray &aid) { return SCARD_ERROR_NOT_SUPPORTED; } + int select(const ByteArray &path, bool fromCurrentDF) { return SCARD_ERROR_NOT_SUPPORTED; } + int select(unsigned int fid) { return SCARD_ERROR_NOT_SUPPORTED; } + int selectParent() { return SCARD_ERROR_NOT_SUPPORTED; } + int readRecord(unsigned int sfi, unsigned int recordId, Record &result) { return SCARD_ERROR_NOT_SUPPORTED; } + int writeRecord(unsigned int sfi, const Record &record) { return SCARD_ERROR_NOT_SUPPORTED; } + int searchRecord(unsigned int sfi, const ByteArray &searchParam, vector &result) { return SCARD_ERROR_NOT_SUPPORTED; } + int readBinary(unsigned int sfi, unsigned int offset, unsigned int length, ByteArray &result) { return SCARD_ERROR_NOT_SUPPORTED; } + int writeBinary(unsigned int sfi, const ByteArray &data, unsigned int offset, unsigned int length) { return SCARD_ERROR_NOT_SUPPORTED; } + }; + +} /* namespace smartcard_service_api */ +#endif /* GPARAM_H_ */ diff --git a/common/include/GPSEACL.h b/common/include/GPARFACL.h similarity index 55% rename from common/include/GPSEACL.h rename to common/include/GPARFACL.h index 4e1bb8e..396adbe 100644 --- a/common/include/GPSEACL.h +++ b/common/include/GPARFACL.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef GPSEACL_H_ -#define GPSEACL_H_ +#ifndef GPARFACL_H_ +#define GPARFACL_H_ /* standard library header */ @@ -31,45 +31,22 @@ #ifdef __cplusplus namespace smartcard_service_api { - class GPSEACL: public AccessControlList + class GPARFACL : public AccessControlList { private: ByteArray refreshTag; - static ByteArray OID_GLOBALPLATFORM; - int loadAccessControl(Channel *channel, PKCS15DODF *dodf); - int loadRules(Channel *channel, ByteArray path); - int loadAccessConditions(Channel *channel, ByteArray aid, ByteArray path); + int loadRules(Channel *channel, const ByteArray &path); + int loadAccessConditions(Channel *channel, const ByteArray &aid, const ByteArray &path); public: - GPSEACL(); - ~GPSEACL(); + GPARFACL(); + ~GPARFACL(); int loadACL(Channel *channel); - }; } /* namespace smartcard_service_api */ #endif /* __cplusplus */ - -/* export C API */ -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - -typedef void *gp_se_acl_h; - -gp_se_acl_h gp_se_acl_create_instance(); -int gp_se_acl_load_acl(gp_se_acl_h handle, channel_h channel); -int gp_se_acl_update_acl(gp_se_acl_h handle, channel_h channel); -void gp_se_acl_release_acl(gp_se_acl_h handle); -bool gp_se_acl_is_authorized_access(gp_se_acl_h handle, unsigned char *aidBuffer, unsigned int aidLength, unsigned char *certHashBuffer, unsigned int certHashLength); -void gp_se_acl_destroy_instance(gp_se_acl_h handle); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* GPSEACL_H_ */ +#endif /* GPARFACL_H_ */ diff --git a/common/include/PKCS15.h b/common/include/PKCS15.h index b761eba..5d6f265 100644 --- a/common/include/PKCS15.h +++ b/common/include/PKCS15.h @@ -36,15 +36,17 @@ namespace smartcard_service_api map recordElement; PKCS15ODF *odf; - bool selectFromEFDIR(); + int selectFromEFDIR(); public: static ByteArray PKCS15_AID; PKCS15(Channel *channel); - PKCS15(Channel *channel, ByteArray selectResponse); + PKCS15(Channel *channel, const ByteArray &selectResponse); ~PKCS15(); + int select(); + PKCS15ODF *getODF(); int getTokenInfo(ByteArray &path); }; diff --git a/common/include/PKCS15DODF.h b/common/include/PKCS15DODF.h index 3860b54..24660fe 100644 --- a/common/include/PKCS15DODF.h +++ b/common/include/PKCS15DODF.h @@ -27,7 +27,7 @@ namespace smartcard_service_api { - class PKCS15DODF: public PKCS15Object + class PKCS15DODF : public PKCS15Object { private: map mapOID; @@ -35,7 +35,6 @@ namespace smartcard_service_api bool parseData(ByteArray data); public: - PKCS15DODF(); PKCS15DODF(unsigned int fid, Channel *channel); PKCS15DODF(ByteArray path, Channel *channel); ~PKCS15DODF(); diff --git a/common/include/PKCS15ODF.h b/common/include/PKCS15ODF.h index 3139959..409ffde 100644 --- a/common/include/PKCS15ODF.h +++ b/common/include/PKCS15ODF.h @@ -30,7 +30,7 @@ using namespace std; namespace smartcard_service_api { - class PKCS15ODF: public PKCS15Object + class PKCS15ODF : public PKCS15Object { private: bool parseData(ByteArray data); diff --git a/server/ServerChannel.cpp b/server/ServerChannel.cpp index 8d13597..9765541 100644 --- a/server/ServerChannel.cpp +++ b/server/ServerChannel.cpp @@ -26,13 +26,11 @@ namespace smartcard_service_api { ServerChannel::ServerChannel(ServerSession *session, void *caller, - int channelNum, Terminal *terminal) - : Channel(session) + int channelNum, Terminal *terminal) : + Channel(session), terminal(terminal), caller(caller), + privilege(true) { - this->terminal = terminal; - this->caller = caller; this->channelNum = channelNum; - this->privilege = true; } ServerChannel::~ServerChannel() diff --git a/server/ServerReader.cpp b/server/ServerReader.cpp index 8f0d614..43cd288 100644 --- a/server/ServerReader.cpp +++ b/server/ServerReader.cpp @@ -26,7 +26,7 @@ #include "Debug.h" #include "ServerSEService.h" #include "ServerReader.h" -#include "GPSEACL.h" +#include "GPACE.h" namespace smartcard_service_api { @@ -95,7 +95,7 @@ namespace smartcard_service_api if (acList == NULL) { /* load access control */ - acList = new GPSEACL(); + acList = new GPACE(); if (acList != NULL) { acList->loadACL(adminChannel); diff --git a/server/ServerResource.cpp b/server/ServerResource.cpp index 2843fa7..4f70519 100644 --- a/server/ServerResource.cpp +++ b/server/ServerResource.cpp @@ -29,7 +29,8 @@ #include "TerminalInterface.h" #include "APDUHelper.h" #include "SignatureHelper.h" -#include "GPSEACL.h" +#include "GPACE.h" +#include "PKCS15.h" #ifndef EXTERN_API #define EXTERN_API __attribute__((visibility("default"))) @@ -396,14 +397,30 @@ namespace smartcard_service_api AccessControlList *acList = NULL; /* request open channel sequence */ - if ((acList = getAccessControlList(channel)) != NULL) + if ((acList = getAccessControlList(channel)) == NULL) { - PKCS15 pkcs15(channel); - - channel->setSelectResponse(pkcs15.getSelectResponse()); + /* load access control defined by Global Platform */ + GPACE *acl = new GPACE(); + if (acl != NULL) + { + int ret; - acList->loadACL(channel); - result = acList->isAuthorizedAccess(aid, hashes); + ret = acl->loadACL(channel); + if (ret >= SCARD_ERROR_OK) + { + acList = acl; + addAccessControlList(channel, acList); + } + else + { + _ERR("unknown error, 0x%x", -ret); + delete acl; + } + } + else + { + _ERR("alloc failed"); + } } else { @@ -411,6 +428,11 @@ namespace smartcard_service_api result = false; } + if (acList != NULL) + { + result = acList->isAuthorizedAccess(aid, hashes); + } + return result; } @@ -526,7 +548,8 @@ namespace smartcard_service_api { PKCS15 pkcs15(channel); - if (pkcs15.isClosed() == false) + rv = pkcs15.select(); + if (rv >= SCARD_ERROR_OK) { /* remove privilege mode */ channel->unsetPrivilegeMode(); @@ -534,7 +557,7 @@ namespace smartcard_service_api } else { - _ERR("select failed"); + _ERR("select failed, [%x]", -rv); service->closeChannel(result); throw ExceptionBase(SCARD_ERROR_IO_FAILED); @@ -553,7 +576,7 @@ namespace smartcard_service_api } else { - _ERR("select failed [%d]", rv); + _ERR("select failed [%x]", -rv); service->closeChannel(result); throw ExceptionBase(SCARD_ERROR_IO_FAILED); @@ -646,26 +669,41 @@ namespace smartcard_service_api } } - AccessControlList *ServerResource::getAccessControlList(Terminal *terminal) + void ServerResource::addAccessControlList(Terminal *terminal, AccessControlList *acl) { - AccessControlList *result = NULL; map::iterator item; if ((item = mapACL.find(terminal)) == mapACL.end()) { - /* load access control */ - result = new GPSEACL(); - if (result != NULL) - { - mapACL.insert(make_pair(terminal, result)); - } - else - { - _ERR("alloc failed"); - } + mapACL.insert(make_pair(terminal, acl)); + } + else + { + item->second = acl; + } + } + + void ServerResource::addAccessControlList(ServerChannel *channel, AccessControlList *acl) + { + map::iterator item; + + if ((item = mapACL.find(channel->getTerminal())) == mapACL.end()) + { + mapACL.insert(make_pair(channel->getTerminal(), acl)); } else { + item->second = acl; + } + } + + AccessControlList *ServerResource::getAccessControlList(Terminal *terminal) + { + AccessControlList *result = NULL; + map::iterator item; + + if ((item = mapACL.find(terminal)) != mapACL.end()) + { result = item->second; } @@ -677,20 +715,7 @@ namespace smartcard_service_api AccessControlList *result = NULL; map::iterator item; - if ((item = mapACL.find(channel->getTerminal())) == mapACL.end()) - { - /* load access control */ - result = new GPSEACL(); - if (result != NULL) - { - mapACL.insert(make_pair(channel->getTerminal(), result)); - } - else - { - _ERR("alloc failed"); - } - } - else + if ((item = mapACL.find(channel->getTerminal())) != mapACL.end()) { result = item->second; } @@ -1037,6 +1062,51 @@ namespace smartcard_service_api } } + bool ServerResource::isAuthorizedNFCAccess(Terminal *terminal, ByteArray &aid, vector &hashes) + { + bool result = false; + + if (terminal == NULL) { + return result; + } + + int num = _openLogicalChannel(terminal); + if (num > 0) { + /* create channel instance */ + ServerChannel *channel = new ServerChannel(NULL, NULL, num, terminal); + if (channel != NULL) { + AccessControlList *acl = getAccessControlList(channel); + if (acl == NULL) { + + /* load access control defined by Global Platform */ + GPACE *acl = new GPACE(); + if (acl != NULL) { + int ret; + + ret = acl->loadACL(channel); + if (ret >= SCARD_ERROR_OK) { + addAccessControlList(channel, acl); + } else { + _ERR("unknown error, 0x%x", -ret); + delete acl; + } + } else { + _ERR("alloc failed"); + } + } else { + acl->updateACL(channel); + } + + delete channel; + + if (acl != NULL) { + result = acl->isAuthorizedNFCAccess(aid, hashes); + } + } + } + + return result; + } } /* namespace smartcard_service_api */ using namespace smartcard_service_api; diff --git a/server/ServerSession.cpp b/server/ServerSession.cpp index 7dc80fc..ff272f6 100644 --- a/server/ServerSession.cpp +++ b/server/ServerSession.cpp @@ -26,7 +26,7 @@ #include "ServerReader.h" #include "ServerChannel.h" #include "APDUHelper.h" -#include "GPSEACL.h" +#include "GPACE.h" namespace smartcard_service_api { diff --git a/server/include/ServerResource.h b/server/include/ServerResource.h index ea544d8..337a9f0 100644 --- a/server/include/ServerResource.h +++ b/server/include/ServerResource.h @@ -138,11 +138,16 @@ namespace smartcard_service_api Channel *getChannel(int socket, unsigned int context, unsigned int channelID); void removeChannel(int socket, unsigned int context, unsigned int channelID); + void addAccessControlList(Terminal *terminal, AccessControlList *acl); + void addAccessControlList(ServerChannel *channel, AccessControlList *acl); AccessControlList *getAccessControlList(Terminal *terminal); AccessControlList *getAccessControlList(ServerChannel *channel); bool sendMessageToAllClients(Message &msg); + bool isAuthorizedNFCAccess(Terminal *terminal, ByteArray &aid, + vector &hashes); + friend void terminalCallback(void *terminal, int event, int error, void *user_param); }; -- 2.7.4