2 // Copyright (c) 2012 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 * @file FSecCert_X509CertificateStoreImpl.cpp
19 * @brief This is the implementation file for _X509CertificateStoreImpl class.
24 #include <unique_ptr.h>
25 #include <FBaseResult.h>
26 #include <FSecCertX509Certificate.h>
27 #include <FBaseSysLog.h>
28 #include <FBase_StringConverter.h>
29 #include <FSec_AccessController.h>
30 #include <FSec_AccessControlTypes.h>
31 #include <FSecCert_CertServer.h>
32 #include <FSecCert_CertService.h>
33 #include <FSecCert_CertServiceProxy.h>
34 #include <FSecCert_X509CertificateStoreImpl.h>
36 using namespace Tizen::Base;
38 namespace Tizen { namespace Security { namespace Cert
41 static const int _MAX_CERT_BUFFER_SIZE = 2048;
44 GetIndexFromCertType(int certType)
49 case _CERT_TYPE_ROOT_CA:
53 case _CERT_TYPE_ROOT_DOMAIN1:
57 case _CERT_TYPE_ROOT_DOMAIN3:
62 SysTryReturn(NID_SEC_CERT, false, -1, E_INVALID_ARG, "[%s] Invalid certificate type.", GetErrorMessage(E_INVALID_ARG));
69 _X509CertificateStoreImpl::_X509CertificateStoreImpl(void)
70 : __certType(static_cast< int >(_CERT_TYPE_NOT_BOUNDED))
75 memset(__context, 0, sizeof(__context));
77 __pCertServiceProxy = _CertServiceProxy::GetInstance();
78 SysTryReturnVoidResult(NID_SEC_CERT, __pCertServiceProxy != null, E_SYSTEM, "[E_SYSTEM] Failed to get certificate proxy instance.");
80 // restore root CA cert DB
81 //__pCertServiceProxy->RestoreRootCaIntegrity();
85 _X509CertificateStoreImpl::~_X509CertificateStoreImpl(void)
87 if ((__certType > _CERT_TYPE_NOT_BOUNDED) && (__certType < _CERT_TYPE_MAX))
89 __pCertServiceProxy->CloseCertificateStore(__certType);
94 _X509CertificateStoreImpl::GetName(String& name) const
96 name = L"CertServiceStore";
101 _X509CertificateStoreImpl::SetCertificateSelector(const Tizen::Security::Cert::ICertificateSelector& selector)
103 result r = E_SUCCESS;
105 int prevIndex = GetIndexFromCertType(__certType);
106 if (__certType == _CERT_TYPE_USER_CERT)
108 r = __pCertServiceProxy->CloseCertificateStore(__certType);
109 SysTryReturnResult(NID_SEC_CERT, !IsFailed(r), E_SYSTEM, "Failed to close certificate store.");
111 else if (prevIndex > -1 && __context[prevIndex] != 0)
113 r = _CertServer::CloseCertificateStore(reinterpret_cast< CertificateStoreCtx >(__context[prevIndex]));
114 __context[prevIndex] = 0;
115 SysTryReturnResult(NID_SEC_CERT, !IsFailed(r), E_SYSTEM, "Failed to close certificate store.");
121 CertificateType certType = (const_cast< ICertificateSelector& >(selector)).GetType();
125 __certType = _CERT_TYPE_ROOT_CA;
128 case OPERATOR_DOMAIN:
129 __certType = _CERT_TYPE_ROOT_DOMAIN1;
132 case TRUSTED_THIRD_PARTY_DOMAIN:
133 __certType = _CERT_TYPE_ROOT_DOMAIN3;
137 __certType = _CERT_TYPE_USER_CERT;
138 return __pCertServiceProxy->OpenCertificateStoreByType(static_cast< _CaCertType >(__certType), count);
141 SysTryReturnResult(NID_SEC_CERT, false, E_INVALID_ARG, "Invalid certificate type.");
145 CertificateStoreCtx certList = null;
146 int index = GetIndexFromCertType(__certType);
148 if (__context[index] == 0)
150 certList = _CertServer::OpenCertificateStoreByType(static_cast< _CaCertType >(__certType), &count);
152 SysTryReturnResult(NID_SEC_CERT, !IsFailed(r), E_SYSTEM, "Failed to open certificate store.");
153 __context[index] = reinterpret_cast< int >(certList);
160 _X509CertificateStoreImpl::GetCertificateCount(int& count)
162 result r = E_SUCCESS;
164 if (__certType == _CERT_TYPE_USER_CERT)
166 r = __pCertServiceProxy->GetCertificateCount(__certType, count);
170 r = _AccessController::CheckUserPrivilege(_PRV_CERTIFICATE_READ);
171 SysTryReturnResult(NID_SEC_CERT, !IsFailed(r), E_PRIVILEGE_DENIED, "The application does not have the privilege to call this method.");
173 int index = GetIndexFromCertType(__certType);
174 SysTryReturnResult(NID_SEC_CERT, index > -1, E_SYSTEM, "Failed to open certificate store.");
175 count = _CertServer::GetCertificateCount(reinterpret_cast< CertificateStoreCtx >(__context[index]));
181 Tizen::Security::Cert::ICertificate*
182 _X509CertificateStoreImpl::GetNextCertificateN(void)
184 result r = E_SUCCESS;
185 ByteBuffer certBuffer;
186 byte certBytes[_MAX_CERT_BUFFER_SIZE] = {0, };
187 int certLen = sizeof(certBytes);
188 int curPos = __curPos;
192 if (__certType == _CERT_TYPE_USER_CERT)
194 r = __pCertServiceProxy->GetNextCertificate(__certType, curPos, certBytes, certLen);
195 SysTryReturn(NID_SEC_CERT, !IsFailed(r), null, r, "[%s] Failed to get next root certificate.", GetErrorMessage(r));
199 r = _AccessController::CheckUserPrivilege(_PRV_CERTIFICATE_READ);
200 SysTryReturn(NID_SEC_CERT, !IsFailed(r), null, E_PRIVILEGE_DENIED, "The application does not have the privilege to call this method.");
202 _CertRootCaInfo* pRootCa = null;
203 _CertRootList* pTemp = null;
206 int index = GetIndexFromCertType(__certType);
207 SysTryReturnResult(NID_SEC_CERT, index > -1, null, "Failed to open certificate store.");
209 CertificateStoreCtx certificateStoreCtx = reinterpret_cast< CertificateStoreCtx >(__context[index]);
210 SysTryReturn(NID_SEC_CERT, certificateStoreCtx != null, null, E_INVALID_ARG, "Invalid certificate store context.");
212 pRootCa = reinterpret_cast< _CertRootCaInfo* >(certificateStoreCtx);
213 SysTryReturn(NID_SEC_CERT, pRootCa->pRootList != null, null, E_OBJ_NOT_FOUND, "Certificate list is empty.");
215 pTemp = pRootCa->pRootList;
217 while (count != curPos)
220 SysTryReturn(NID_SEC_CERT, pTemp->pNext != null, null, E_OBJ_NOT_FOUND, "Certificate index not found.");
222 pTemp = pTemp->pNext;
225 pRootCa->pCurrRootList = pTemp;
226 if (certLen > static_cast< int >(pRootCa->pCurrRootList->length))
228 memcpy(certBytes, pRootCa->pCurrRootList->certificate, pRootCa->pCurrRootList->length);
229 certLen = pRootCa->pCurrRootList->length;
233 memcpy(certBytes, pRootCa->pCurrRootList->certificate, certLen);
241 r = certBuffer.Construct(certLen);
242 SysTryReturn(NID_SEC_CERT, !IsFailed(r), null, r, "[%s] Failed to allocate memory.", GetErrorMessage(r));
244 r = certBuffer.SetArray(certBytes, 0, certLen);
245 SysTryReturn(NID_SEC_CERT, !IsFailed(r), null, E_SYSTEM, "[E_SYSTEM]An unexpected system error occurred.");
249 std::unique_ptr< X509Certificate > pCert(new (std::nothrow) X509Certificate());
250 SysTryReturn(NID_SEC_CERT, pCert != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Failed to allocate memory.");
252 r = pCert->Construct(certBuffer);
253 SysTryReturn(NID_SEC_CERT, !IsFailed(r), null, E_SYSTEM, "[E_SYSTEM] X509Certificate instance is not constructed.");
255 return pCert.release();
260 _X509CertificateStoreImpl::Insert(CertificateType certificateType, const Tizen::Security::Cert::ICertificate& certificate)
262 result r = E_SUCCESS;
263 byte* pBuffer = null;
265 _CaCertType certType = _CERT_TYPE_NOT_BOUNDED;
267 switch (certificateType)
270 certType = _CERT_TYPE_ROOT_CA;
273 case OPERATOR_DOMAIN:
274 certType = _CERT_TYPE_ROOT_DOMAIN1;
277 case TRUSTED_THIRD_PARTY_DOMAIN:
278 certType = _CERT_TYPE_ROOT_DOMAIN3;
282 certType = _CERT_TYPE_USER_CERT;
286 SysTryReturnResult(NID_SEC_CERT, false, E_INVALID_ARG, "Invalid certificate type.");
290 std::unique_ptr< ByteBuffer > pEncodedData(certificate.GetEncodedDataN());
291 SysTryReturnResult(NID_SEC_CERT, pEncodedData != null, E_INVALID_ARG, "Failed to get encoded data on input certificate.");
293 pBuffer = const_cast< byte* >(pEncodedData->GetPointer());
294 SysTryReturnResult(NID_SEC_CERT, pBuffer != null, E_INVALID_ARG, "Invalid input argument passed.");
296 bufferLen = pEncodedData->GetRemaining();
297 SysTryReturnResult(NID_SEC_CERT, bufferLen > 0, E_INVALID_ARG, "Length value is not positive.");
299 if (certType == _CERT_TYPE_USER_CERT)
301 r = __pCertServiceProxy->InsertUserCertChainPrivateKey(reinterpret_cast< char* >(pBuffer), bufferLen, null, 0);
305 r = __pCertServiceProxy->InsertCaCertificate(static_cast< int >(certType), _CERT_X509, pBuffer, bufferLen);
307 UpdateCertStoreContext(certType);
308 SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s] Failed to update cert store.", GetErrorMessage(r));
311 if (r == E_FILE_ALREADY_EXIST)
315 SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s] Failed to insert root certificate.", GetErrorMessage(r));
321 _X509CertificateStoreImpl::InsertPkcs12(const String& filePath, const String& password, bool checkPrivilege)
323 result r = E_SUCCESS;
324 std::unique_ptr< char[] > pFilePath(_StringConverter::CopyToCharArrayN(filePath));
325 std::unique_ptr< char[] > pPassword(_StringConverter::CopyToCharArrayN(password));
327 SysTryReturnResult(NID_SEC_CERT, filePath.GetLength() > 0, E_INVALID_ARG, "Length of file path is not positive.");
328 SysTryReturnResult(NID_SEC_CERT, pFilePath != null, E_INVALID_ARG, "File path is invalid.");
330 //password can be null
331 r = __pCertServiceProxy->InsertPkcs12Content(pFilePath.get(), pPassword.get(), checkPrivilege);
332 if (r == E_FILE_ALREADY_EXIST)
336 SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s] Failed to insert pkcs 12 user certificate.", GetErrorMessage(r));
343 _X509CertificateStoreImpl::Update(CertificateType certificateType, const Tizen::Security::Cert::ICertificate& oldCert, const Tizen::Security::Cert::ICertificate& newCert)
345 result r = E_SUCCESS;
346 byte* pOldBuffer = null;
347 byte* pNewBuffer = null;
348 int oldBufferLen = 0;
349 int newBufferLen = 0;
350 _CaCertType certType = _CERT_TYPE_NOT_BOUNDED;
352 switch (certificateType)
355 certType = _CERT_TYPE_ROOT_CA;
358 case OPERATOR_DOMAIN:
359 certType = _CERT_TYPE_ROOT_DOMAIN1;
362 case TRUSTED_THIRD_PARTY_DOMAIN:
363 certType = _CERT_TYPE_ROOT_DOMAIN3;
367 certType = _CERT_TYPE_USER_CERT;
371 SysTryReturnResult(NID_SEC_CERT, false, E_INVALID_ARG, "Invalid certificate type.");
375 std::unique_ptr< ByteBuffer > pOldEncodedData(oldCert.GetEncodedDataN());
376 SysTryReturnResult(NID_SEC_CERT, pOldEncodedData != null, E_INVALID_ARG, "Failed to get encoded data on old input certificate.");
378 pOldBuffer = const_cast< byte* >(pOldEncodedData->GetPointer());
379 SysTryReturnResult(NID_SEC_CERT, pOldBuffer != null, E_INVALID_ARG, "Invalid input argument passed.");
381 oldBufferLen = pOldEncodedData->GetRemaining();
382 SysTryReturnResult(NID_SEC_CERT, oldBufferLen > 0, E_INVALID_ARG, "Input old certificate length is not positive.");
384 pOldEncodedData.reset(null);
386 std::unique_ptr< ByteBuffer > pNewEncodedData(newCert.GetEncodedDataN());
387 SysTryReturnResult(NID_SEC_CERT, pNewEncodedData != null, E_INVALID_ARG, "Failed to get encoded data on new input certificate.");
389 pNewBuffer = const_cast< byte* >(pNewEncodedData->GetPointer());
390 SysTryReturnResult(NID_SEC_CERT, pNewBuffer != null, E_INVALID_ARG, "Invalid input argument passed.");
392 newBufferLen = pNewEncodedData->GetRemaining();
393 SysTryReturnResult(NID_SEC_CERT, newBufferLen > 0, E_INVALID_ARG, "Input new certificate length is not positive.");
395 if (certType == _CERT_TYPE_USER_CERT)
397 CertificateHandle certHandle = 0;
400 r = _CertService::OpenCertificate(reinterpret_cast< char* >(pOldBuffer), oldBufferLen, &certHandle);
401 SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s]Failed to open certificates.", GetErrorMessage(r));
403 r = _CertService::GetUserCertificateId(certHandle, certId);
405 _CertService::CloseCertificate(&certHandle);
406 SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s]Failed to find user certificates in store.", GetErrorMessage(r));
408 r = __pCertServiceProxy->RemoveUserCertChainByCertId(certId);
409 SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s]Failed to remove/update user certificates from store.", GetErrorMessage(r));
411 r = __pCertServiceProxy->InsertUserCertChainPrivateKey(reinterpret_cast< char* >(pNewBuffer), newBufferLen, null, 0);
412 SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s]Failed to install/update user certificates.", GetErrorMessage(r));
416 r = __pCertServiceProxy->UpdateCaCertificate(static_cast< int >(certType), pOldBuffer, oldBufferLen, pNewBuffer, newBufferLen);
417 SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s] Failed to update certificate.", GetErrorMessage(r));
419 UpdateCertStoreContext(certType);
420 SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s] Failed to update cert store.", GetErrorMessage(r));
428 _X509CertificateStoreImpl::Remove(CertificateType certificateType, const Tizen::Security::Cert::ICertificate& certificate)
430 result r = E_SUCCESS;
431 byte* pBuffer = null;
434 _CaCertType certType = _CERT_TYPE_NOT_BOUNDED;
436 switch (certificateType)
439 certType = _CERT_TYPE_ROOT_CA;
442 case OPERATOR_DOMAIN:
443 certType = _CERT_TYPE_ROOT_DOMAIN1;
446 case TRUSTED_THIRD_PARTY_DOMAIN:
447 certType = _CERT_TYPE_ROOT_DOMAIN3;
451 certType = _CERT_TYPE_USER_CERT;
455 SysTryReturnResult(NID_SEC_CERT, false, E_INVALID_ARG, "Invalid certificate type.");
459 std::unique_ptr< ByteBuffer > pEncodedData(certificate.GetEncodedDataN());
460 SysTryReturnResult(NID_SEC_CERT, pEncodedData != null, E_INVALID_ARG, "Failed to get encoded data on input certificate.");
462 pBuffer = const_cast< byte* >(pEncodedData->GetPointer());
463 SysTryReturnResult(NID_SEC_CERT, pBuffer != null, E_INVALID_ARG, "Invalid input argument passed.");
465 bufferLen = pEncodedData->GetRemaining();
466 SysTryReturnResult(NID_SEC_CERT, bufferLen > 0, E_INVALID_ARG, "Input certificate length is not positive.");
468 if (certType == _CERT_TYPE_USER_CERT)
470 CertificateHandle certHandle = 0;
473 r = _CertService::OpenCertificate(reinterpret_cast< char* >(pBuffer), bufferLen, &certHandle);
474 SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s]Failed to open certificates.", GetErrorMessage(r));
476 r = _CertService::GetUserCertificateId(certHandle, certId);
478 _CertService::CloseCertificate(&certHandle);
479 SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s]Failed to find user certificates in store.", GetErrorMessage(r));
481 r = __pCertServiceProxy->RemoveUserCertChainByCertId(certId);
482 SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s]Failed to remove user certificates.", GetErrorMessage(r));
486 r = __pCertServiceProxy->RemoveCaCertificate(static_cast< int >(certType), pBuffer, bufferLen);
487 SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s] Failed to remove certificate.", GetErrorMessage(r));
489 UpdateCertStoreContext(certType);
490 SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s] Failed to update cert store.", GetErrorMessage(r));
497 _X509CertificateStoreImpl::UpdateCertStoreContext(int type)
499 result r = E_SUCCESS;
501 CertificateStoreCtx certList = null;
502 int index = GetIndexFromCertType(type);
506 if (index > -1 && type == __certType)
508 if (__context[index] != 0)
510 r = _CertServer::CloseCertificateStore(reinterpret_cast< CertificateStoreCtx >(__context[index]));
511 TryReturnResult(!IsFailed(r), r, r, "[%s] Propagating.", GetErrorMessage(r));
513 certList = _CertServer::OpenCertificateStoreByType(static_cast< _CaCertType >(type), &count);
515 SysTryReturnResult(NID_SEC_CERT, !IsFailed(r), E_SYSTEM, "Failed to open certificate store.");
516 __context[index] = reinterpret_cast< int >(certList);
522 _X509CertificateStoreImpl*
523 _X509CertificateStoreImpl::GetInstance(X509CertificateStore& x509CertificateStore)
525 return x509CertificateStore.__pX509CertificateStoreImpl;
528 const _X509CertificateStoreImpl*
529 _X509CertificateStoreImpl::GetInstance(const X509CertificateStore& x509CertificateStore)
531 return x509CertificateStore.__pX509CertificateStoreImpl;
535 InsertPkcs12Content(const char* pPath, const char* pPassword)
537 result r = E_SUCCESS;
538 _X509CertificateStoreImpl store;
542 filePath.SetCapacity(strlen(pPath) + 1);
543 password.SetCapacity(strlen(pPassword) + 1);
545 filePath.Format(strlen(pPath) + 1, L"%s", pPath);
546 password.Format(strlen(pPassword) + 1, L"%s", pPassword);
548 r = store.InsertPkcs12(filePath, password, false);
549 SysTryReturn(NID_SEC_CERT, !IsFailed(r), -1, r, "[%s] Failed to remove certificate.", GetErrorMessage(r));
555 } } } // Tizen::Security::Cert