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.
18 /* standard library header */
20 /* SLP library header */
25 #include "PKCS15ODF.h"
26 #include "PKCS15DODF.h"
27 #include "NumberStream.h"
28 #include "SimpleTLV.h"
29 #include "AccessCondition.h"
32 #define EXTERN_API __attribute__((visibility("default")))
35 namespace smartcard_service_api
37 static unsigned char oid_globalplatform[] = { 0x2A, 0x86, 0x48, 0x86, 0xFC, 0x6B, 0x81, 0x48, 0x01, 0x01 };
38 ByteArray GPSEACL::OID_GLOBALPLATFORM(ARRAY_AND_SIZE(oid_globalplatform));
40 GPSEACL::GPSEACL():AccessControlList()
48 int GPSEACL::loadACL(Channel *channel)
58 pkcs15 = new PKCS15(channel, channel->getSelectResponse());
61 /* basically, all requests will be accepted when PKCS #15 doesn't exist or global platform OID is not placed */
64 if (pkcs15->isClosed() == false)
68 if ((odf = pkcs15->getODF()) != NULL)
72 if ((dodf = odf->getDODF()) != NULL)
74 if (loadAccessControl(channel, dodf) == 0)
76 printAccessControlList();
82 SCARD_DEBUG_ERR("loadAccessControl failed, every request will be accepted.");
87 SCARD_DEBUG_ERR("dodf null, every request will be accepted.");
92 SCARD_DEBUG_ERR("odf null, every request will be accepted.");
97 SCARD_DEBUG_ERR("failed to open PKCS15, every request will be accepted.");
110 int GPSEACL::loadAccessControl(Channel *channel, PKCS15DODF *dodf)
115 if ((result = dodf->searchOID(OID_GLOBALPLATFORM, path)) == 0)
118 FileObject file(channel);
120 SCARD_DEBUG("oid path : %s", path.toString());
122 file.select(NumberStream::getLittleEndianNumber(path));
123 file.readBinary(0, 0, file.getFCP()->getFileSize(), data);
125 SCARD_DEBUG("data : %s", data.toString());
127 /* PKCS #15 and DODF OID exists. apply access control rule!! */
132 if (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE : AccessControlMainFile */
134 tlv.enterToValueTLV();
137 ByteArray refreshTag;
139 refreshTag = SimpleTLV::getOctetString(tlv);
140 SCARD_DEBUG("current refresh tag : %s", refreshTag.toString());
142 if (this->refreshTag != refreshTag) /* need to update access control list */
144 this->refreshTag = refreshTag;
148 /* access control rule path */
149 if (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE : Path */
151 /* TODO : parse path */
155 path = SimpleTLV::getOctetString(tlv.getValue());
156 SCARD_DEBUG("access control rule path : %s", path.toString());
158 if (loadRules(channel, path) == 0)
160 SCARD_DEBUG("loadRules success");
164 SCARD_DEBUG_ERR("loadRules failed");
168 tlv.returnToParentTLV();
172 SCARD_DEBUG_ERR("tlv.decodeTLV failed");
177 SCARD_DEBUG_ERR("OID not found");
183 int GPSEACL::loadRules(Channel *channel, ByteArray path)
185 FileObject file(channel);
188 file.select(NumberStream::getLittleEndianNumber(path));
189 file.readBinary(0, 0, file.getFCP()->getFileSize(), data);
191 SCARD_DEBUG("data : %s", data.toString());
195 while (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE : Rule */
197 tlv.enterToValueTLV();
198 if (tlv.decodeTLV() == true)
201 switch (tlv.getTag())
203 case 0xA0 : /* CHOICE 0 : EXPLICIT AID */
205 aid = SimpleTLV::getOctetString(tlv.getValue());
208 case 0x81 : /* CHOICE 1?? : default */
209 aid = AccessControlList::AID_DEFAULT;
212 case 0x82 : /* CHOICE 2?? : any application */
213 aid = AccessControlList::AID_ALL;
217 SCARD_DEBUG("aid : %s", aid.toString());
219 /* access condition path */
220 if (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE : Path */
225 path = SimpleTLV::getOctetString(tlv.getValue());
226 SCARD_DEBUG("path : %s", path.toString());
228 if (loadAccessConditions(channel, aid, path) == 0)
230 SCARD_DEBUG("loadCertHashes success");
234 SCARD_DEBUG_ERR("loadCertHashes failed");
239 SCARD_DEBUG_ERR("decodeTLV failed");
244 SCARD_DEBUG_ERR("decodeTLV failed");
246 tlv.returnToParentTLV();
252 int GPSEACL::loadAccessConditions(Channel *channel, ByteArray aid, ByteArray path)
254 FileObject file(channel);
257 file.select(NumberStream::getLittleEndianNumber(path));
258 file.readBinary(0, 0, file.getFCP()->getFileSize(), data);
260 SCARD_DEBUG("data : %s", data.toString());
262 AccessCondition condition;
264 condition.loadAccessCondition(aid, data);
266 pair<ByteArray, AccessCondition> newItem(aid, condition);
268 mapConditions.insert(newItem);
273 } /* namespace smartcard_service_api */
276 #define GP_SE_ACL_EXTERN_BEGIN \
277 if (handle != NULL) \
279 GPSEACL *acl = (GPSEACL *)handle;
281 #define GP_SE_ACL_EXTERN_END \
285 SCARD_DEBUG_ERR("Invalid param"); \
288 using namespace smartcard_service_api;
290 EXTERN_API gp_se_acl_h gp_se_acl_create_instance()
292 GPSEACL *acl = new GPSEACL();
294 return (gp_se_acl_h)acl;
297 EXTERN_API int gp_se_acl_load_acl(gp_se_acl_h handle, channel_h channel)
301 GP_SE_ACL_EXTERN_BEGIN;
302 result = acl->loadACL((Channel *)channel);
303 GP_SE_ACL_EXTERN_END;
308 EXTERN_API int gp_se_acl_update_acl(gp_se_acl_h handle, channel_h channel)
312 GP_SE_ACL_EXTERN_BEGIN;
313 acl->updateACL((Channel *)channel);
314 GP_SE_ACL_EXTERN_END;
319 EXTERN_API void gp_se_acl_release_acl(gp_se_acl_h handle)
321 GP_SE_ACL_EXTERN_BEGIN;
323 GP_SE_ACL_EXTERN_END;
326 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)
330 GP_SE_ACL_EXTERN_BEGIN;
331 result = acl->isAuthorizedAccess(aidBuffer, aidLength, certHashBuffer, certHashLength);
332 GP_SE_ACL_EXTERN_END;
337 EXTERN_API void gp_se_acl_destroy_instance(gp_se_acl_h handle)
339 GP_SE_ACL_EXTERN_BEGIN;
341 GP_SE_ACL_EXTERN_END;