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.
19 #include "PKCS15ODF.h"
20 #include "PKCS15DODF.h"
21 #include "NumberStream.h"
22 #include "SimpleTLV.h"
23 #include "AccessCondition.h"
26 #define EXTERN_API __attribute__((visibility("default")))
29 namespace smartcard_service_api
31 static unsigned char oid_globalplatform[] = { 0x2A, 0x86, 0x48, 0x86, 0xFC, 0x6B, 0x81, 0x48, 0x01, 0x01 };
32 static ByteArray OID_GLOBALPLATFORM(ARRAY_AND_SIZE(oid_globalplatform));
34 GPARFACL::GPARFACL() : AccessControlList()
42 int GPARFACL::loadACL(Channel *channel)
44 int result = SCARD_ERROR_OK;
50 return SCARD_ERROR_ILLEGAL_PARAM;
53 PKCS15 pkcs15(channel);
55 /* basically, all requests will be accepted when PKCS #15 doesn't exist or global platform OID is not placed */
58 result = pkcs15.select();
59 if (result >= SCARD_ERROR_OK)
63 result = SCARD_ERROR_OK;
66 if ((odf = pkcs15.getODF()) != NULL)
70 if ((dodf = odf->getDODF()) != NULL)
72 result = loadAccessControl(channel, dodf);
73 if (result == SCARD_ERROR_OK)
78 _INFO("loadAccessControl failed, every request will be accepted.");
79 result = SCARD_ERROR_OK;
84 _INFO("dodf null, every request will be accepted.");
89 _INFO("odf null, every request will be accepted.");
94 _ERR("failed to open PKCS15, every request will be denied.");
102 int GPARFACL::loadAccessControl(Channel *channel, PKCS15DODF *dodf)
107 if ((result = dodf->searchOID(OID_GLOBALPLATFORM, path)) == 0)
110 FileObject file(channel);
112 _DBG("oid path : %s", path.toString().c_str());
114 file.select(NumberStream::getLittleEndianNumber(path));
115 file.readBinary(0, 0, file.getFCP()->getFileSize(), data);
117 _DBG("data : %s", data.toString().c_str());
119 /* PKCS #15 and DODF OID exists. apply access control rule!! */
124 if (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE : AccessControlMainFile */
126 tlv.enterToValueTLV();
129 ByteArray refreshTag;
131 refreshTag = SimpleTLV::getOctetString(tlv);
132 _DBG("current refresh tag : %s", refreshTag.toString().c_str());
134 if (this->refreshTag != refreshTag) /* need to update access control list */
136 this->refreshTag = refreshTag;
140 /* access control rule path */
141 if (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE : Path */
143 /* TODO : parse path */
147 path = SimpleTLV::getOctetString(tlv.getValue());
148 _DBG("access control rule path : %s", path.toString().c_str());
150 if (loadRules(channel, path) == 0)
152 _DBG("loadRules success");
156 _ERR("loadRules failed");
162 _INFO("access rules are not changed. skip update");
164 tlv.returnToParentTLV();
168 _ERR("tlv.decodeTLV failed");
173 _ERR("OID not found");
179 int GPARFACL::loadRules(Channel *channel, const ByteArray &path)
181 FileObject file(channel);
184 file.select(NumberStream::getLittleEndianNumber(path));
185 file.readBinary(0, 0, file.getFCP()->getFileSize(), data);
187 _DBG("data : %s", data.toString().c_str());
191 while (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE : Rule */
193 tlv.enterToValueTLV();
194 if (tlv.decodeTLV() == true)
197 switch (tlv.getTag())
199 case 0xA0 : /* CHOICE 0 : EXPLICIT AID */
201 aid = SimpleTLV::getOctetString(tlv.getValue());
204 case 0x81 : /* CHOICE 1?? : default */
205 aid = AccessControlList::DEFAULT_SE_APP;
208 case 0x82 : /* CHOICE 2?? : any application */
209 aid = AccessControlList::ALL_SE_APPS;
213 _DBG("aid : %s", aid.toString().c_str());
215 /* access condition path */
216 if (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE : Path */
221 path = SimpleTLV::getOctetString(tlv.getValue());
222 _DBG("path : %s", path.toString().c_str());
224 if (loadAccessConditions(channel, aid, path) == 0)
226 _DBG("loadCertHashes success");
230 _ERR("loadCertHashes failed");
235 _ERR("decodeTLV failed");
240 _ERR("decodeTLV failed");
242 tlv.returnToParentTLV();
248 static void loadAPDUAccessRule(AccessRule *rule, const ByteArray &data)
253 _ERR("invalid parameter");
257 if (tlv.decodeTLV() == true)
259 switch (tlv.getTag())
261 case 0xA0 : /* CHOICE 0 : APDUPermission */
262 rule->setAPDUAccessRule(SimpleTLV::getBoolean(tlv.getValue()));
265 case 0xA1 : /* CHOICE 1 : APDUFilters */
266 tlv.enterToValueTLV();
267 while (tlv.decodeTLV() == true)
269 if (tlv.getTag() == 0x04) /* OCTET STRING */
271 ByteArray apdu, mask, value;
273 value = tlv.getValue();
275 _DBG("APDU rule : %s", value.toString().c_str());
277 if (value.size() == 8) /* apdu 4 bytes + mask 4 bytes */
279 apdu.assign(value.getBuffer(), 4);
280 mask.assign(value.getBuffer(4), 4);
282 rule->addAPDUAccessRule(apdu, mask);
286 _ERR("Invalid APDU rule : %s", value.toString().c_str());
291 _ERR("Unknown tag : 0x%02X", tlv.getTag());
294 tlv.returnToParentTLV();
298 _ERR("Unknown tag : 0x%02X", tlv.getTag());
304 static void loadNFCAccessRule(AccessRule *rule, const ByteArray &data)
307 _ERR("invalid parameter");
311 rule->setNFCAccessRule(SimpleTLV::getBoolean(data));
314 static void loadAccessCondition(AccessCondition &condition, const ByteArray &data)
321 while (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE */
325 /* access granted for specific applications */
326 tlv.enterToValueTLV();
329 switch (tlv.getTag())
331 case 0x04 : /* OCTET STRING : CertHash */
332 _DBG("aid : %s, hash : %s", condition.getAID().toString().c_str(), tlv.getValue().toString().c_str());
334 hash = tlv.getValue();
335 condition.addAccessRule(tlv.getValue());
338 case 0xA0 : /* CHOICE 0 : AccessRules */
339 tlv.enterToValueTLV();
342 AccessRule *rule = condition.getAccessRule(hash);
344 condition.addAccessRule(hash);
345 rule = condition.getAccessRule(hash);
348 switch (tlv.getTag())
350 case 0xA0 : /* CHOICE 0 : APDUAccessRule */
351 loadAPDUAccessRule(rule, tlv.getValue());
354 case 0xA1 : /* CHOICE 1 : NFCAccessRule */
355 loadNFCAccessRule(rule, tlv.getValue());
359 _ERR("Unknown tag : 0x%02X", tlv.getTag());
365 _ERR("tlv.decodeTLV failed");
367 tlv.returnToParentTLV();
371 _ERR("Unknown tag : 0x%02X", tlv.getTag());
377 _ERR("tlv.decodeTLV failed");
379 tlv.returnToParentTLV();
383 _INFO("access denied for all applications, aid : %s", condition.getAID().toString().c_str());
385 condition.setAccessCondition(false);
392 /* empty file, it means deny for all application */
393 _INFO("access denied for all applications, aid : %s", condition.getAID().toString().c_str());
395 condition.setAccessCondition(false);
399 int GPARFACL::loadAccessConditions(Channel *channel, const ByteArray &aid, const ByteArray &path)
401 FileObject file(channel);
404 file.select(NumberStream::getLittleEndianNumber(path));
405 file.readBinary(0, 0, file.getFCP()->getFileSize(), data);
407 _DBG("data : %s", data.toString().c_str());
409 AccessCondition condition;
411 condition.setAID(aid);
412 loadAccessCondition(condition, data);
414 pair<ByteArray, AccessCondition> newItem(aid, condition);
416 mapConditions.insert(newItem);
421 } /* namespace smartcard_service_api */