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)
83 _INFO("loadAccessControl failed, every request will be accepted.");
84 result = SCARD_ERROR_OK;
89 _INFO("dodf null, every request will be accepted.");
94 _INFO("odf null, every request will be accepted.");
99 _ERR("failed to open PKCS15, every request will be denied.");
107 int GPARFACL::loadAccessControl(Channel *channel, PKCS15DODF *dodf)
112 if ((result = dodf->searchOID(OID_GLOBALPLATFORM, path)) == 0)
115 FileObject file(channel);
117 _DBG("oid path : %s", path.toString().c_str());
119 file.select(NumberStream::getLittleEndianNumber(path));
120 file.readBinary(0, 0, file.getFCP()->getFileSize(), data);
122 _DBG("data : %s", data.toString().c_str());
124 /* PKCS #15 and DODF OID exists. apply access control rule!! */
129 if (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE : AccessControlMainFile */
131 tlv.enterToValueTLV();
134 ByteArray refreshTag;
136 refreshTag = SimpleTLV::getOctetString(tlv);
137 _DBG("current refresh tag : %s", refreshTag.toString().c_str());
139 if (this->refreshTag != refreshTag) /* need to update access control list */
141 this->refreshTag = refreshTag;
145 /* access control rule path */
146 if (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE : Path */
148 /* TODO : parse path */
152 path = SimpleTLV::getOctetString(tlv.getValue());
153 _DBG("access control rule path : %s", path.toString().c_str());
155 if (loadRules(channel, path) == 0)
157 _DBG("loadRules success");
161 _ERR("loadRules failed");
167 _INFO("access rules are not changed. skip update");
169 tlv.returnToParentTLV();
173 _ERR("tlv.decodeTLV failed");
178 _ERR("OID not found");
184 int GPARFACL::loadRules(Channel *channel, const ByteArray &path)
186 FileObject file(channel);
189 file.select(NumberStream::getLittleEndianNumber(path));
190 file.readBinary(0, 0, file.getFCP()->getFileSize(), data);
192 _DBG("data : %s", data.toString().c_str());
196 while (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE : Rule */
198 tlv.enterToValueTLV();
199 if (tlv.decodeTLV() == true)
202 switch (tlv.getTag())
204 case 0xA0 : /* CHOICE 0 : EXPLICIT AID */
206 aid = SimpleTLV::getOctetString(tlv.getValue());
209 case 0x81 : /* CHOICE 1?? : default */
210 aid = AccessControlList::DEFAULT_SE_APP;
213 case 0x82 : /* CHOICE 2?? : any application */
214 aid = AccessControlList::ALL_SE_APPS;
218 _DBG("aid : %s", aid.toString().c_str());
220 /* access condition path */
221 if (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE : Path */
226 path = SimpleTLV::getOctetString(tlv.getValue());
227 _DBG("path : %s", path.toString().c_str());
229 if (loadAccessConditions(channel, aid, path) == 0)
231 _DBG("loadCertHashes success");
235 _ERR("loadCertHashes failed");
240 _ERR("decodeTLV failed");
245 _ERR("decodeTLV failed");
247 tlv.returnToParentTLV();
253 static void loadAPDUAccessRule(AccessRule *rule, const ByteArray &data)
258 _ERR("invalid parameter");
262 if (tlv.decodeTLV() == true)
264 switch (tlv.getTag())
266 case 0xA0 : /* CHOICE 0 : APDUPermission */
267 rule->setAPDUAccessRule(SimpleTLV::getBoolean(tlv.getValue()));
270 case 0xA1 : /* CHOICE 1 : APDUFilters */
271 tlv.enterToValueTLV();
272 while (tlv.decodeTLV() == true)
274 if (tlv.getTag() == 0x04) /* OCTET STRING */
276 ByteArray apdu, mask, value;
278 value = tlv.getValue();
280 _DBG("APDU rule : %s", value.toString().c_str());
282 if (value.size() == 8) /* apdu 4 bytes + mask 4 bytes */
284 apdu.assign(value.getBuffer(), 4);
285 mask.assign(value.getBuffer(4), 4);
287 rule->addAPDUAccessRule(apdu, mask);
291 _ERR("Invalid APDU rule : %s", value.toString().c_str());
296 _ERR("Unknown tag : 0x%02X", tlv.getTag());
299 tlv.returnToParentTLV();
303 _ERR("Unknown tag : 0x%02X", tlv.getTag());
309 static void loadNFCAccessRule(AccessRule *rule, const ByteArray &data)
312 _ERR("invalid parameter");
316 rule->setNFCAccessRule(SimpleTLV::getBoolean(data));
319 static void loadAccessCondition(AccessCondition &condition, const ByteArray &data)
326 while (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE */
330 /* access granted for specific applications */
331 tlv.enterToValueTLV();
334 switch (tlv.getTag())
336 case 0x04 : /* OCTET STRING : CertHash */
337 _DBG("aid : %s, hash : %s", condition.getAID().toString().c_str(), tlv.getValue().toString().c_str());
339 hash = tlv.getValue();
340 condition.addAccessRule(tlv.getValue());
343 case 0xA0 : /* CHOICE 0 : AccessRules */
344 tlv.enterToValueTLV();
347 AccessRule *rule = condition.getAccessRule(hash);
349 condition.addAccessRule(hash);
350 rule = condition.getAccessRule(hash);
353 switch (tlv.getTag())
355 case 0xA0 : /* CHOICE 0 : APDUAccessRule */
356 loadAPDUAccessRule(rule, tlv.getValue());
359 case 0xA1 : /* CHOICE 1 : NFCAccessRule */
360 loadNFCAccessRule(rule, tlv.getValue());
364 _ERR("Unknown tag : 0x%02X", tlv.getTag());
370 _ERR("tlv.decodeTLV failed");
372 tlv.returnToParentTLV();
376 _ERR("Unknown tag : 0x%02X", tlv.getTag());
382 _ERR("tlv.decodeTLV failed");
384 tlv.returnToParentTLV();
388 _INFO("access denied for all applications, aid : %s", condition.getAID().toString().c_str());
390 condition.setAccessCondition(false);
397 /* empty file, it means deny for all application */
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 */