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
36 static unsigned char oid_globalplatform[] = { 0x2A, 0x86, 0x48, 0x86, 0xFC, 0x6B, 0x81, 0x48, 0x01, 0x01 };
37 static ByteArray OID_GLOBALPLATFORM(ARRAY_AND_SIZE(oid_globalplatform));
39 GPARFACL::GPARFACL() : AccessControlList()
47 int GPARFACL::loadACL(Channel *channel)
49 int result = SCARD_ERROR_OK;
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 */
63 result = pkcs15.select();
64 if (result >= SCARD_ERROR_OK)
68 result = SCARD_ERROR_OK;
71 if ((odf = pkcs15.getODF()) != NULL)
75 if ((dodf = odf->getDODF()) != NULL)
77 result = loadAccessControl(channel, dodf);
78 if (result == SCARD_ERROR_OK)
80 printAccessControlList();
84 _INFO("loadAccessControl failed, every request will be accepted.");
85 result = SCARD_ERROR_OK;
90 _INFO("dodf null, every request will be accepted.");
95 _INFO("odf null, every request will be accepted.");
100 _ERR("failed to open PKCS15, every request will be denied.");
108 int GPARFACL::loadAccessControl(Channel *channel, PKCS15DODF *dodf)
113 if ((result = dodf->searchOID(OID_GLOBALPLATFORM, path)) == 0)
116 FileObject file(channel);
118 _DBG("oid path : %s", path.toString().c_str());
120 file.select(NumberStream::getLittleEndianNumber(path));
121 file.readBinary(0, 0, file.getFCP()->getFileSize(), data);
123 _DBG("data : %s", data.toString().c_str());
125 /* PKCS #15 and DODF OID exists. apply access control rule!! */
130 if (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE : AccessControlMainFile */
132 tlv.enterToValueTLV();
135 ByteArray refreshTag;
137 refreshTag = SimpleTLV::getOctetString(tlv);
138 _DBG("current refresh tag : %s", refreshTag.toString().c_str());
140 if (this->refreshTag != refreshTag) /* need to update access control list */
142 this->refreshTag = refreshTag;
146 /* access control rule path */
147 if (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE : Path */
149 /* TODO : parse path */
153 path = SimpleTLV::getOctetString(tlv.getValue());
154 _DBG("access control rule path : %s", path.toString().c_str());
156 if (loadRules(channel, path) == 0)
158 _DBG("loadRules success");
162 _ERR("loadRules failed");
168 _INFO("access rules are not changed. skip update");
170 tlv.returnToParentTLV();
174 _ERR("tlv.decodeTLV failed");
179 _ERR("OID not found");
185 int GPARFACL::loadRules(Channel *channel, const ByteArray &path)
187 FileObject file(channel);
190 file.select(NumberStream::getLittleEndianNumber(path));
191 file.readBinary(0, 0, file.getFCP()->getFileSize(), data);
193 _DBG("data : %s", data.toString().c_str());
197 while (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE : Rule */
199 tlv.enterToValueTLV();
200 if (tlv.decodeTLV() == true)
203 switch (tlv.getTag())
205 case 0xA0 : /* CHOICE 0 : EXPLICIT AID */
207 aid = SimpleTLV::getOctetString(tlv.getValue());
210 case 0x81 : /* CHOICE 1?? : default */
211 aid = AccessControlList::DEFAULT_SE_APP;
214 case 0x82 : /* CHOICE 2?? : any application */
215 aid = AccessControlList::ALL_SE_APPS;
219 _DBG("aid : %s", aid.toString().c_str());
221 /* access condition path */
222 if (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE : Path */
227 path = SimpleTLV::getOctetString(tlv.getValue());
228 _DBG("path : %s", path.toString().c_str());
230 if (loadAccessConditions(channel, aid, path) == 0)
232 _DBG("loadCertHashes success");
236 _ERR("loadCertHashes failed");
241 _ERR("decodeTLV failed");
246 _ERR("decodeTLV failed");
248 tlv.returnToParentTLV();
254 static void loadAPDUAccessRule(AccessRule *rule, const ByteArray &data)
259 _ERR("invalid parameter");
263 if (tlv.decodeTLV() == true)
265 switch (tlv.getTag())
267 case 0xA0 : /* CHOICE 0 : APDUPermission */
268 rule->setAPDUAccessRule(SimpleTLV::getBoolean(tlv.getValue()));
271 case 0xA1 : /* CHOICE 1 : APDUFilters */
272 tlv.enterToValueTLV();
273 while (tlv.decodeTLV() == true)
275 if (tlv.getTag() == 0x04) /* OCTET STRING */
277 ByteArray apdu, mask, value;
279 value = tlv.getValue();
281 _DBG("APDU rule : %s", value.toString().c_str());
283 if (value.size() == 8) /* apdu 4 bytes + mask 4 bytes */
285 apdu.assign(value.getBuffer(), 4);
286 mask.assign(value.getBuffer(4), 4);
288 rule->addAPDUAccessRule(apdu, mask);
292 _ERR("Invalid APDU rule : %s", value.toString().c_str());
297 _ERR("Unknown tag : 0x%02X", tlv.getTag());
300 tlv.returnToParentTLV();
304 _ERR("Unknown tag : 0x%02X", tlv.getTag());
310 static void loadNFCAccessRule(AccessRule *rule, const ByteArray &data)
313 _ERR("invalid parameter");
317 rule->setNFCAccessRule(SimpleTLV::getBoolean(data));
320 static void loadAccessCondition(AccessCondition &condition, const ByteArray &data)
327 while (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE */
331 /* access granted for specific applications */
332 tlv.enterToValueTLV();
335 switch (tlv.getTag())
337 case 0x04 : /* OCTET STRING : CertHash */
338 _DBG("aid : %s, hash : %s", condition.getAID().toString().c_str(), tlv.getValue().toString().c_str());
340 hash = tlv.getValue();
341 condition.addAccessRule(tlv.getValue());
344 case 0xA0 : /* CHOICE 0 : AccessRules */
345 tlv.enterToValueTLV();
348 AccessRule *rule = condition.getAccessRule(hash);
350 condition.addAccessRule(hash);
351 rule = condition.getAccessRule(hash);
354 switch (tlv.getTag())
356 case 0xA0 : /* CHOICE 0 : APDUAccessRule */
357 loadAPDUAccessRule(rule, tlv.getValue());
360 case 0xA1 : /* CHOICE 1 : NFCAccessRule */
361 loadNFCAccessRule(rule, tlv.getValue());
365 _ERR("Unknown tag : 0x%02X", tlv.getTag());
371 _ERR("tlv.decodeTLV failed");
373 tlv.returnToParentTLV();
377 _ERR("Unknown tag : 0x%02X", tlv.getTag());
383 _ERR("tlv.decodeTLV failed");
385 tlv.returnToParentTLV();
389 _INFO("access denied for all applications, aid : %s", condition.getAID().toString().c_str());
391 condition.setAccessCondition(false);
398 _INFO("access denied for all applications, aid : %s", condition.getAID().toString().c_str());
400 condition.setAccessCondition(false);
404 int GPARFACL::loadAccessConditions(Channel *channel, const ByteArray &aid, const ByteArray &path)
406 FileObject file(channel);
409 file.select(NumberStream::getLittleEndianNumber(path));
410 file.readBinary(0, 0, file.getFCP()->getFileSize(), data);
412 _DBG("data : %s", data.toString().c_str());
414 AccessCondition condition;
416 condition.setAID(aid);
417 loadAccessCondition(condition, data);
419 pair<ByteArray, AccessCondition> newItem(aid, condition);
421 mapConditions.insert(newItem);
426 } /* namespace smartcard_service_api */