2 * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 /* standard library header */
19 /* SLP library header */
24 #include "PKCS15ODF.h"
25 #include "PKCS15DODF.h"
26 #include "NumberStream.h"
27 #include "SimpleTLV.h"
28 #include "AccessCondition.h"
31 #define EXTERN_API __attribute__((visibility("default")))
34 namespace smartcard_service_api
37 static unsigned char oid_globalplatform[] = { 0x2A, 0x86, 0x48, 0x86, 0xFC, 0x6B, 0x81, 0x48, 0x01, 0x01 };
38 static ByteArray OID_GLOBALPLATFORM(ARRAY_AND_SIZE(oid_globalplatform));
40 GPARFACL::GPARFACL() : AccessControlList()
48 int GPARFACL::loadACL(Channel *channel)
50 int result = SCARD_ERROR_OK;
54 if (channel == NULL) {
55 return SCARD_ERROR_ILLEGAL_PARAM;
58 PKCS15 pkcs15(channel);
60 /* basically, all requests will be accepted when PKCS #15 doesn't exist or global platform OID is not placed */
61 #if 1 /* FOR ORANGE */
62 /* for Orange, every requests will be denied in same cases */
68 result = pkcs15.select();
69 if (result >= SCARD_ERROR_OK) {
72 result = SCARD_ERROR_OK;
74 if ((odf = pkcs15.getODF()) != NULL) {
77 if ((dodf = odf->getDODF()) != NULL) {
78 result = loadAccessControl(channel, dodf);
79 if (result == SCARD_ERROR_OK) {
80 printAccessControlList();
82 #if 1 /* FOR ORANGE */
83 _ERR("loadAccessControl failed, every request will be denied.");
85 _INFO("loadAccessControl failed, every request will be accepted.");
87 result = SCARD_ERROR_OK;
90 #if 1 /* FOR ORANGE */
91 _ERR("dodf null, every request will be denied.");
93 _INFO("dodf null, every request will be accepted.");
97 #if 1 /* FOR ORANGE */
98 _ERR("odf null, every request will be denied.");
100 _INFO("odf null, every request will be accepted.");
104 #if 1 /* FOR ORANGE */
105 _ERR("failed to open PKCS#15, every request will be denied.");
107 _INFO("failed to open PKCS#15, every request will be accepted.");
116 int GPARFACL::loadAccessControl(Channel *channel, PKCS15DODF *dodf)
121 if ((result = dodf->searchOID(OID_GLOBALPLATFORM, path)) == 0) {
123 FileObject file(channel);
125 _DBG("oid path : %s", path.toString().c_str());
127 file.select(NumberStream::getLittleEndianNumber(path));
128 file.readBinaryAll(0, data);
130 _DBG("data : %s", data.toString().c_str());
132 /* PKCS #15 and DODF OID exists. apply access control rule!! */
137 if (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE : AccessControlMainFile */ {
138 tlv.enterToValueTLV();
141 ByteArray refreshTag;
143 refreshTag = SimpleTLV::getOctetString(tlv);
144 _DBG("current refresh tag : %s", refreshTag.toString().c_str());
146 if (this->refreshTag != refreshTag) /* need to update access control list */ {
147 this->refreshTag = refreshTag;
151 /* access control rule path */
152 if (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE : Path */ {
153 /* TODO : parse path */
157 path = SimpleTLV::getOctetString(tlv.getValue());
158 _DBG("access control rule path : %s", path.toString().c_str());
160 if (loadRules(channel, path) == 0) {
161 _DBG("loadRules success");
163 _ERR("loadRules failed");
167 _INFO("access rules are not changed. skip update");
169 tlv.returnToParentTLV();
171 _ERR("tlv.decodeTLV failed");
174 _ERR("OID not found");
180 int GPARFACL::loadRules(Channel *channel, const ByteArray &path)
182 FileObject file(channel);
185 file.select(NumberStream::getLittleEndianNumber(path));
186 file.readBinaryAll(0, data);
188 _DBG("data : %s", data.toString().c_str());
192 while (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE : Rule */ {
193 tlv.enterToValueTLV();
194 if (tlv.decodeTLV() == true) {
196 switch (tlv.getTag()) {
197 case 0xA0 : /* CHOICE 0 : EXPLICIT AID */
199 aid = SimpleTLV::getOctetString(tlv.getValue());
202 case 0x81 : /* CHOICE 1?? : default */
203 aid = AccessControlList::DEFAULT_SE_APP;
206 case 0x82 : /* CHOICE 2?? : any application */
207 aid = AccessControlList::ALL_SE_APPS;
211 _DBG("aid : %s", aid.toString().c_str());
213 /* access condition path */
214 if (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE : Path */ {
218 tlv_path = SimpleTLV::getOctetString(tlv.getValue());
219 _DBG("tlv_path : %s", tlv_path.toString().c_str());
221 if (loadAccessConditions(channel, aid, tlv_path) == 0) {
222 _DBG("loadCertHashes success");
224 _ERR("loadCertHashes failed");
227 _ERR("decodeTLV failed");
230 _ERR("decodeTLV failed");
232 tlv.returnToParentTLV();
238 static void loadAPDUAccessRule(AccessRule *rule, const ByteArray &data)
243 _ERR("invalid parameter");
247 if (tlv.decodeTLV() == true) {
248 switch (tlv.getTag()) {
249 case 0xA0 : /* CHOICE 0 : APDUPermission */
250 rule->setAPDUAccessRule(SimpleTLV::getBoolean(tlv.getValue()));
253 case 0xA1 : /* CHOICE 1 : APDUFilters */
254 tlv.enterToValueTLV();
255 while (tlv.decodeTLV() == true) {
256 if (tlv.getTag() == 0x04) /* OCTET STRING */ {
257 ByteArray apdu, mask, value;
259 value = tlv.getValue();
261 _DBG("APDU rule : %s", value.toString().c_str());
263 if (value.size() == 8) /* apdu 4 bytes + mask 4 bytes */ {
264 apdu.assign(value.getBuffer(), 4);
265 mask.assign(value.getBuffer(4), 4);
267 rule->addAPDUAccessRule(apdu, mask);
269 _ERR("Invalid APDU rule : %s", value.toString().c_str());
272 _ERR("Unknown tag : 0x%02X", tlv.getTag());
275 tlv.returnToParentTLV();
279 _ERR("Unknown tag : 0x%02X", tlv.getTag());
285 static void loadNFCAccessRule(AccessRule *rule, const ByteArray &data)
288 _ERR("invalid parameter");
292 rule->setNFCAccessRule(SimpleTLV::getBoolean(data));
295 static void loadAccessCondition(AccessCondition &condition, const ByteArray &data)
297 if (data.size() > 0) {
301 while (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE */ {
302 if (tlv.size() > 0) {
303 /* access granted for specific applications */
304 tlv.enterToValueTLV();
305 if (tlv.decodeTLV()) {
306 switch (tlv.getTag()) {
307 case 0x04 : /* OCTET STRING : CertHash */
308 _DBG("aid : %s, hash : %s", condition.getAID().toString().c_str(), tlv.getValue().toString().c_str());
310 hash = tlv.getValue();
311 condition.addAccessRule(tlv.getValue());
314 case 0xA0 : /* CHOICE 0 : AccessRules */
315 tlv.enterToValueTLV();
316 if (tlv.decodeTLV()) {
317 AccessRule *rule = condition.getAccessRule(hash);
319 condition.addAccessRule(hash);
320 rule = condition.getAccessRule(hash);
323 switch (tlv.getTag()) {
324 case 0xA0 : /* CHOICE 0 : APDUAccessRule */
325 loadAPDUAccessRule(rule, tlv.getValue());
328 case 0xA1 : /* CHOICE 1 : NFCAccessRule */
329 loadNFCAccessRule(rule, tlv.getValue());
333 _ERR("Unknown tag : 0x%02X", tlv.getTag());
337 _ERR("tlv.decodeTLV failed");
339 tlv.returnToParentTLV();
343 _ERR("Unknown tag : 0x%02X", tlv.getTag());
347 _ERR("tlv.decodeTLV failed");
349 tlv.returnToParentTLV();
351 /* empty rule, it means allow for all application */
352 _INFO("access allowed for all applications, aid : %s", condition.getAID().toString().c_str());
354 condition.setAccessCondition(true);
359 /* empty file, it means deny for all application */
360 _INFO("access denied for all applications, aid : %s", condition.getAID().toString().c_str());
362 condition.setAccessCondition(false);
366 int GPARFACL::loadAccessConditions(Channel *channel, const ByteArray &aid, const ByteArray &path)
368 FileObject file(channel);
371 file.select(NumberStream::getLittleEndianNumber(path));
372 file.readBinaryAll(0, data);
374 _DBG("data : %s", data.toString().c_str());
376 AccessCondition condition;
378 condition.setAID(aid);
379 loadAccessCondition(condition, data);
381 pair<ByteArray, AccessCondition> newItem(aid, condition);
383 mapConditions.insert(newItem);
389 } /* namespace smartcard_service_api */